Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;具有类型特征的条件函数调用_C++_Templates_Typetraits - Fatal编程技术网

C++ C++;具有类型特征的条件函数调用

C++ C++;具有类型特征的条件函数调用,c++,templates,typetraits,C++,Templates,Typetraits,假设我有一个类模板模板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 nothi

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

};
模板
X类{
静态void foo(){
if(has_method(T,bar))//类似这样的东西
T::bar();//如果T没有bar()方法,那么foo什么也不做
}
};

首先,您需要在编译时做出决定,因为 否则,您将需要提供该函数,即使您 永远不要进入树枝。我可以想象这样的情况:

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 );
    }
};
其余部分应按原样工作。

模板
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(...) {}
};
X类{ 公众: 静态void foo(){ foo_impl(静态_cast(nullptr)); } 私人: //foo#u impl#1 模板 静态自动foo_impl(U*)->decltype(U::bar(),void()){ U::bar(); } //foo#u impl#2 静态void foo_impl(…){} };
由于SFINAE规则,当
U::bar()
不是有效表达式时,
foo_impl
\1不在重载集中,而是调用
foo_impl
\35; 2。如果
foo_impl
#1的类型推导成功,那么它总是比省略号更好的转换


Ideone演示:

搜索“标记分派”并查看。什么是
void(&T::bar)(
?@aschepler错误:-))。当您获取地址时,它应该是
&T::bar
。我会纠正它。使用函数指针会取消函数的资格,比如
静态空白条(int n=0)。(但我不认为只有使用C++03就可以解决这个问题。)@Ascheppler说得对。但是在实例化它的类中,总是可以重载:只需添加
静态void bar(){bar(0);}
并删除默认参数。
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(...) {}
};