[英]Template type deduction for a pointer to member function
我有一个与Morpheus提出的问题非常相似的问题,在下面的问题中:
Richard Corden提出的解决方案要求用户明确指定函数参数类型,以区分它们的重载。 但是,此解决方案似乎不适用于具有相同类型的不同数量的参数的重载。
考虑这个例子(源自原始问题):
template <typename T>
class A
{
public:
template<class Arg1>
void connect(void (T::*f)(Arg1))
{
//Do some stuff
}
template<class Arg1, class Arg2>
void connect(void (T::*f)(Arg1,Arg2))
{
//Do some stuff
}
void connect(void (T::*f)())
{
//Do some stuff
}
};
class GApp
{
public:
void foo() {}
void foo(double d) {}
void foo(double d1, double d2) {}
};
int main ()
{
A<GApp> a;
a.connect (&GApp::foo); // foo () - OK
a.connect<double> (&GApp::foo); // foo (double) - FAIL
a.connect<double,double> (&GApp::foo); // foo (double,double) - OK
}
GNU G ++ 3.4.5和MSVC 2008不编译上面的代码,两者都提供类似的错误消息:
test.cpp: In function `int main()':
test.cpp:36: error: call of overloaded `connect(<unknown type>)' is ambiguous
test.cpp:7: note: candidates are: void A<T>::connect(void (T::*)(Arg1)) [with Arg1 = double, T = GApp]
test3.cpp:13: note: void A<T>::connect(void (T::*)(Arg1, Arg2)) [with Arg1 = double, Arg2 = double, T = GApp]
我知道一些可以使其编译的变通方法,比如将指针指定给完全相同类型的变量(例如void (GApp::*tmp)(double) = &GApp::foo;
)或者,使用更多调用connect函数时的表达形式(例如connect((void (GApp::*)(double))(&GApp::foo));
)。
但是,我更喜欢第一种解决方案,并想知道它为什么不起作用。
先感谢您!
对于a.connect<double> (&GApp::foo)
, foo(double)
和foo(double, double)
将匹配connect
的重载与one,并分别与两个模板参数匹配(在两个参数的情况下)版本,将推导出第二个模板参数,第一个参数由您明确提供)。
如果你想消除模棱两可的情况,我建议你传递确切的类型,这样就不会出现任何意外。 而不是那些重载,为什么不有一个重载
template<typename MType, typename T>
void connect(MType T::*f)
{
//Do some stuff
}
a.connect<void()> (&GApp::foo);
a.connect<void(double)> (&GApp::foo);
a.connect<void(double, double)> (&GApp::foo);
最后一次调用connect
应该在你的代码中正常工作。 然后,您可以在connect
单独模板时剖析类型MType
,以获取参数和返回类型。
原始代码的问题在于您明确定义了错误的部分。 当你指定一个模板参数列表时,即使你指定了一个模板参数列表,编译器也会尝试推导出第二个模板参数,然后它会立即运行到模糊状态,因为它不知道你是否想要使用(double,double)或(双)变异。
让编译器推导出它们,而不是定义模板参数,而是明确指定要使用哪个foo()函数:
int main()
{
A<GApp> a;
a.connect (&GApp::foo); // foo () - OK
a.connect( ( void (GApp::*)(double) )&GApp::foo); // foo (double) - OK
a.connect( ( void (GApp::*)(double, double) ) &GApp::foo); // foo (double,double) - OK
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.