C++中什么时候需要使用模板参数?

5

我很好奇在C++中什么时候需要使用模板参数。

例如,让我们定义一个类:

template<typename T> class Add {
    T value;
public:
    Add(T value) : value(value){};

    T operator() (T valrhs){
        return value + valrhs; 
    }
};

如果我们想要使用double类型创建一个Add对象,为了避免错误,需要按照以下方式定义它:
Add<double> add5 = Add<double>(5.0);

现在让我们考虑以下定义的函数:

template<typename T, typename Function> T doOperation (T data, Function f){
    return f(data);
}

在代码中,如果调用doOperation函数,则不需要任何模板参数。例如,

std::cout << doOperation(5.0, add5);

输出将为10。为什么doOperation不需要模板参数,而定义add5需要模板参数?

此外,是否可以使用函数指针来定义这个问题。我一直在试图弄清楚如何使用函数指针作为参数变量传递像这样的仿函数,而不是第二个模板参数。

谢谢,任何帮助都会受到赞赏。

3个回答

14
在这段代码中{{}}
std::cout << doOperation(5.0, add5);

编译器执行函数模板参数推导
在这行中,
Add<double> add5 = Add<double>(5.0);

由于编译器不会执行类模板参数推导,因此您需要提供模板参数。

然而,从c++17开始,编译器将执行类模板参数推导,然后这个编译就可以正常完成。

Add add5(5.0);

有些情况下,您可能需要明确提供折扣指南。

template<typename T>  Add(T) -> Add<T>;

顺便提一下,你的类Add看起来可以被返回lambda的函数模板替换。

template<typename T>
auto Add (T value) { 
    return [value] (T valrhs) { 
        return value + valrhs; 
    }; 
}

使用方式将如下所示

auto add5 = Add(5.0);
std::cout << doOperation(5.0, add5);

4
什么情况下需要在C++中提供模板参数?
只有当无法推断参数时,必须显式地提供模板参数 - 除非该参数具有默认参数。
函数模板的模板参数可以从非模板参数中推导出来。如果模板类具有一个推导指南(可能是隐式生成的),则可以从构造函数的参数中推导出类模板的模板参数。
为什么doOperation不需要模板参数?
因为模板参数从非模板参数data中推断出来。
但是定义add5需要模板参数吗?
实际上,add5并不需要显式的模板参数。以下写法也可以:
Add add5(5.0);

除非你使用旧版的C++,否则不需要写模板推导指南(这是在C++17中引入的)。


2

自C++17以来,引入了类模板参数推导,如上所述。 但是你必须谨慎使用它,因为它可能会产生不想要的结果。

Add a(5.0); // the type Add<double> is deduced

Add b(5); // the type Add<int> is deduced, which may be unwanted, if you need Add<double> 
          // if so you must specify the desired type

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接