用类型特征调用C ++条件函数

时间:2013-02-04 15:15:54

标签: c++ templates typetraits

假设我有一个类模板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
    }

};

2 个答案:

答案 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;

其余的应该按原样运作。