在如下所示的模板中,我希望调用Run(&Base::foo)
成功,而无需将Base类型命名两次(如编译Run<Base>(&Base::foo)
调用中所做的那样)。我可以吗?可能没有添加大量Boost标题?
使用提供的代码,我收到错误:
prog.cpp:26: error: no matching function for call to ‘Run(bool (Base::*)())’
(你可以在http://ideone.com/8NZkq)摆弄片段:
#include <iostream>
class Base {
public:
bool foo() { return true; }
};
Base* x;
template<typename T>
struct Traits {
typedef bool (T::*BoolMethodPtr)();
};
template<typename T>
void Run(typename Traits<T>::BoolMethodPtr check) {
T* y = dynamic_cast<T*>(x);
std::cout << (y->*check)();
}
int main() {
Base y;
x = &y;
Run<Base>(&Base::foo);
Run(&Base::foo); // why error?
}
答案 0 :(得分:9)
T
中的Traits<T>::BoolMethodPtr
处于非推导的上下文中,因此编译器不会自动从调用中推断出T应该是什么类型。
这是因为可能有这样的代码:
template<typename T>
struct Traits {
typedef bool (T::*BoolMethodPtr)();
};
template<>
struct Traits<int> {
typedef bool (Base::*BoolMethodPtr)();
};
Run(&Base::foo); /* What should T be deduced to? Base and int are both equally possible */
如果您没有Traits<T>
课程,可以将Run
写为:
template<class Class>
void Run(bool (Class::*check)()) {
Class* y = dynamic_cast<Class*>(x);
std::cout << (y->*check)();
}
在此背景下,Class
可以推断为Base
答案 1 :(得分:4)
要分离类型,任何类型,请使用部分特化。没有函数模板部分特化,所以你需要在其参数类型上直接参数化函数并检索里面的类类型。
template< typename T >
struct get_host_class; // most types are not ptmfs: don't implement this
template< typename C >
struct get_host_class< bool (C::*)() > { // implement partial specialization
typedef C host;
typedef void sfinae; // disallow function for non ptmf arguments
};
template< typename T >
typename get_host_class<T>::sfinae Run( T check) {
typedef T BoolMethodPtr; // or something
typedef typename get_host_class< T >::host host;
}
答案 2 :(得分:2)
我认为这是一个非演绎的背景。
$ 14.8.2.5 / 5-“未推断的背景 是: - a的嵌套名称说明符 使用a指定的类型 合格-ID“。
我认为这是适用于这种情况的引用。但是一些模板神需要批准我的理解。
答案 3 :(得分:2)
当编译器尝试匹配模板参数时,它只考虑主类类型。换句话说,当它遇到表达式时:
Run(&Base::foo);
...它试图找出Run
的模板参数,它只考虑foo
本身的类型,并不考虑任何类foo
是一个部分的。
编辑:
foo
的类型是bool(Base::*)(void)
,但您希望编译器找到的只是Base