模板类的默认值,C++

问题描述 投票:0回答:4

有没有办法为模板类提供默认值?

例如假设我有一个类

TimeSeries
,它是模板化的。 我有一个名为
Foo()
的函数,它返回
T

template <typename T>
class TimeSeries
{
    T foo();
}

我想要

Foo()
进行一些计算并返回
T
类型的内容。但如果不能,我希望它给出一个默认值。如果
T
double
,我希望它是
NaN
。如果
T
int
,我希望它是
0

TimeSeries<double> t;
t.foo(); // returns NAN

TimeSeries<int> t;
t.foo(); // returns 0

我如何实现这一目标?

一个糟糕的解决方案是让

Foo()
采用默认值。

template <typename T>
class TimeSeries
{
    T foo(T defaultValue)
    {
       T ret;
       // if OK
       ret = computeValue();
       // if not OK
       ret = defaultValue;
       return ret;
    }
}

因此默认值是

0
NaN
,具体取决于用户。

或者我一开始就要求有缺陷的设计?

编辑- 一个合乎逻辑的问题是问如果

T
不是
int
double
会发生什么。默认值到底意味着什么?

我使用

TimeSeries
T
的方式并不完全是通用类型。只能是
int
double
string
中的 1 个。 我想过简单地编写 3 个独立的
TimeSeries
类,但这似乎是一个有缺陷的方法。

我对其他想法持开放态度。

c++ templates
4个回答
10
投票

您可以声明以下模板,

default_value<>
:

template<typename>
struct default_value;

然后,使用名为

int
的成员提供
double
value
的完整专业化,该成员提供所需的默认值:

template<>
struct default_value<int> {
   static constexpr int value = 0;
};

template<>
struct default_value<double> {
   static constexpr double value = NaN;
};

然后,在您的

foo
函数模板中,您可以简单地返回该值:

return default_value<T>::value;

这取决于

T


4
投票

从 C++14 开始,您可以使用 变量模板:

template <class T> constexpr T default_value = {};
template <>
constexpr double default_value<double> = std::numeric_limits<double>::quiet_NaN();
template <typename T> class TimeSeries
{
    auto foo() -> T
    {
       T ret;

       if (condition)
         return ret;
       else
         return default_value<T>;
    }
};

3
投票

或者我一开始就要求有缺陷的设计?

就我而言,这是一个有效的要求。

我认为有两种方法可以满足该要求。

  1. 您可以使用

    default_value
    中建议的方法另一个答案

  2. 如果您可以选择使用 C++17,则可以使用

    std::optional

    如果您无法选择使用 C++17,则可以通过将返回值更改为

    std::optional
    ,以一种不太复杂的方式模拟
    std::pair<boo, T>
    ,并理解返回值的
    first
    已设置如果计算不成功,则为
    false
    ;如果计算成功,则为
    true

就我个人而言,我更喜欢第二种解决方案。它不依赖哨兵值。它以清晰明确的方式捕获计算是否成功的状态。


0
投票

我也有类似的问题。就我而言,我只是想初始化模板参数类型的变量,而不是作为默认返回。我无法使上述任何方法发挥作用。我使用了 @jfMR 建议的变体。 (作为格式化的单独答案发布)。就我而言,我还想支持原始类型和对象类型。

我使用第二个模板参数来提供一个可调用结构,生成我需要的默认值。完整样本:

#include <stdio.h>
#include <string>
#include <iostream>

struct DefaultInt
{
    int operator () () const { return 42; }
};
struct DefaultChar
{
    char operator () () const { return 'z'; }
};
struct DefaultString
{
    std::string operator () () const { return std::string("waldo"); }
};

template<class TP, class TPDefaultValue> class DemoWrapper
{
public:
    DemoWrapper()
    {
        TPDefaultValue valueFactory;
        _wrap = valueFactory();
    }
    DemoWrapper(TP wrap) : _wrap(wrap)
    {}

    void Print() { std::cout << _wrap << std::endl; }

private:
    TP _wrap;
};

int main(int argc, const char *argv[])
{
    std::string demoString("Thanks for all the fish");
    const int demoInt = 13;
    DemoWrapper<int, DefaultInt> dw1(demoInt);
    DemoWrapper<int, DefaultInt> dw2;
    DemoWrapper<std::string, DefaultString> dw3(demoString);
    DemoWrapper<std::string, DefaultString> dw4;
    
    dw1.Print();
    dw2.Print();
    dw3.Print();
    dw4.Print();
}

输出:

13
42
Thanks for all the fish
waldo
© www.soinside.com 2019 - 2024. All rights reserved.