nsh*_*lov 10 c++ templates std-function template-argument-deduction argument-deduction
你能帮我理解为什么参数推导适用于类模板而不适用于函数模板?
如果我理解正确,类模板定义了一个函数,所以当我调用它时,编译器可以进行隐式转换,但是在函数模板的情况下,目前没有函数定义,所以隐式转换没有发生.
但是我不明白为什么编译器不能创建函数定义然后应用隐式转换?
#include <functional>
template<typename ...ARGS>
class Test1
{
public:
void add(const std::function<void(ARGS...)>&) {}
};
class Test2
{
public:
template<typename ...ARGS>
void add(const std::function<void(ARGS...)>&) {}
};
void func(int) {}
int main()
{
Test1<int> test1;
test1.add(func);
Test2 test2;
test2.add<int>(func);
}
Run Code Online (Sandbox Code Playgroud)
错误是:
在函数'int main()'中:
25:24:错误:没有匹配函数来调用'Test2 :: add(void(&)(int))'
25:24:注意:候选人是:
14:10:注意:模板void Test2 :: add(const std :: function&)
14:10:注意:模板参数扣除/替换失败:
25:24:注意:不匹配的类型'const std :: function'和'void(int)'
在第一种情况下,您将显式实例化类模板Test1.这意味着其add成员的函数声明是使用签名生成的add(const std::function<void(int)>&).当编译器随后尝试解析时test1.add(func),只有一个候选者.由于std::function<void(int)>可以从void(int)函数隐式构造,签名匹配,编译器只是实例化成员函数定义,一切都很好.
在第二种情况下,编译器必须执行模板参数推导/替换以查看它是否可以"使用" add模板.您可能认为指定int会确定模板参数,以便不需要进行推导,但情况并非如此:可能是您要部分指定模板参数,请参见此处.换句话说,您可能尝试使用比显式指定的参数更多的参数来实例化函数模板,至少编译器不知道您是否这样做.因此,它仍然必须尝试匹配类型std::function<void(ARGS...)>(或更准确地说,std::function<void(int, ...)>并且void(int),它不能,因为隐式转换不考虑扣除.
简而言之:指定显式模板参数不会阻止可变参数函数模板的模板参数推导.
注意:我不是100%坚定的确切术语,任何语言律师纠正我是值得赞赏的!
编辑:我主要基于我在这里阅读的内容.
| 归档时间: |
|
| 查看次数: |
289 次 |
| 最近记录: |