假设我有一个类模板template <typename T> class X
是否有可能使用类型特征或类似技术来调用T的(静态)方法,但仅当类型T声明这样的方法时,例如像这样的东西:
template <typename T>
class X {
static void foo(){
if(has_method(T,bar)) //Something like this
T::bar(); //If T has no bar() method, then foo does nothing
}
};
答案 0 :(得分:3)
template <typename T>
class X {
public:
static void foo() {
foo_impl(static_cast<T*>(nullptr));
}
private:
// foo_impl #1
template <typename U>
static auto foo_impl(U*) -> decltype(U::bar(), void()) {
U::bar();
}
// foo_impl #2
static void foo_impl(...) {}
};
由于SFINAE规则,当foo_impl
不是有效表达式时,U::bar()
#1不在重载集中,而foo_impl
#2被调用。如果foo_impl
#1的类型推导确实成功,那么转换将始终比省略号更好。
Ideone演示:http://ideone.com/UKVmIB
答案 1 :(得分:2)
首先,您需要在编译时做出决定,因为 否则,你需要提供这个功能,即使你 永远不要进入分店。我可以想象:
template <typename T, void (T::*)() > struct HasBar;
template <typename T>
void doBar( HasBar<&T::bar>* ) { T::bar(); }
template <typename T>
void doBar( ... ) {}
template <typename T>
class X
{
static void f()
{
doBar<T>( 0 );
}
};
这或多或少是经典的伎俩;如果&T::bar
失败(因为
T没有成员栏),然后doBar(
HasBar<...>)
的实例化失败,该功能未添加到过载
设置,所以另一个被调用。如果&T::bar
是合法的
表达式,两个函数模板都可以成功
实例化,并选择0
到指针的转换
在与...
匹配之前(这总是最后的手段
确定函数重载决议。)
编辑:
我错过了这个功能是静态的这个事实。以上是 用于非静态功能。对于静态功能,请更改 第一行:
template <typename T, void (*)() struct HasBar;
其余的应该按原样运作。