6

更多的模板问题...我喜欢 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。

4

3 回答 3

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从函数指针中推断出来,但不会尝试从第二个参数中推断出来。然后推导出的类型在两个地方都被替换。

于 2013-06-28T17:44:22.213 回答
3

如果您在 gcc 上编译相同的代码段,您会收到更直观的错误消息:

test.cpp:14:20: note:   deduced conflicting types for parameter ‘t’ (‘int&’ and ‘int’)

编译器推断模板参数t用于int&第一个参数,而int用于第二个参数。由于这些是不同的类型,因此您会收到编译错误。

于 2013-06-28T17:08:28.637 回答
3

在 MSVC 2012 Intellisense 中说(大致翻译):

1 IntelliSense:没有构造函数“blah::blah”的实例与参数列表匹配。

参数类型有:(void (int &i), int)

@mfontanini 是正确的,您在这里有一个扣除问题。

您可以添加第二个构造函数

template<class t>
blah(void(*)(t), t){}
template<class t>
blah(void(*)(t&), t&){}
于 2013-06-28T17:17:51.763 回答