更多模板化的困境......我喜欢C ++,但有时我讨厌它。
我无法弄清楚为什么编译器在这里抱怨,以及我能做些什么呢。
struct blah
{
template<class t>
blah(void(*)(t), t){}
};
void Func(int i) {}
void Func2(int& i) {}
void test()
{
int i = 3;
blah b(Func, i);
blah b2(Func2, i); //error C2660: 'blah::blah' : function does not take 2 arguments
blah b3(Func2, (int&)i); //error C2660: 'blah::blah' : function does not take 2 arguments
}
这里发生了什么?
我正在使用MSVC2008。
答案 0 :(得分:7)
其他答案解释了发生了什么:当模板参数推导找到两种推断模板参数的方法时,它会单独查看每个参数,并且它们都必须完全一致。
您可以通过确保t
的第二次使用处于“非推断的上下文”中来使本课程以您的预期方式运行:
template<typename T>
struct identity { typedef T type; };
struct blah
{
template<class t>
blah(void(*)(t), typename identity<t>::type){}
};
这样,当调用blah
构造函数时,C ++将从函数指针中推导出t
,但不会尝试从第二个参数中推导出它。推导出的类型然后在两个地方被替换。
答案 1 :(得分:3)
如果您编译相同的snippet on gcc,则会收到更直观的错误消息:
test.cpp:14:20: note: deduced conflicting types for parameter ‘t’ (‘int&’ and ‘int’)
编译器推断第一个参数的模板参数t
为int&
,第二个参数为int
。由于这些是不同的类型,因此会出现编译错误。
答案 2 :(得分:3)
在MSVC 2012中,Intellisense说(大致翻译):
1智能感知:没有构造函数的实例“”blah :: blah“”匹配参数列表。
参数类型为:
(void (int &i), int)
@mfontanini是正确的,你在这里有一个演绎问题。
您可以添加第二个构造函数
template<class t>
blah(void(*)(t), t){}
template<class t>
blah(void(*)(t&), t&){}