2017-03-15 9 views
1

型にvoid型のメンバ関数があるかどうかを検出するテンプレートメタ関数を記述しようとしています。C++テンプレートメタプログラミングのvoidメソッドの検出

現在、私は、メンバ関数は、ダブルなどint型、に示すように

template<typename C> static auto Test(void*) -> decltype(int{std::declval<C>().foo()}, Yes{}); 

そして、もちろん、私はそれを反転することができます(のようなものを使用したとして、明確な形を持っているかどうかを検出するためにSFINAEを使用することができています添付のコードスニペット)を使って、intではないことをテストしますが、それが無効であることをテストする方法を理解することはできません。

以下のコードは、現在のCのfoo()メソッドは、double型があり、従って、これは誤った出力であり、ただし

A does not have void foo 
B has void foo 
C has void foo 

出力します。 void foo()を正しく確認するにはどうすれば調整できますか?

#include <iostream> 
#include <memory> 

class A { 
public: 
    int foo() { 
     return 0; 
    } 
}; 

class B { 
public: 
    void foo() { 
    } 
}; 

class C { 
public: 
    double foo() { 
     return 0; 
    } 
}; 

template <typename T> 
class has_void_foo { 
private: 
    typedef char Yes; 
    typedef Yes No[2]; 

    template<typename C> static auto Test(void*) -> decltype(int{std::declval<C>().foo()}, Yes{}); 
    template<typename> static No& Test(...); 

public: 
    static bool const value = sizeof(Test<T>(0)) != sizeof(Yes); 
}; 

int main(void) { 
    std::cout << "A "; 
    if (has_void_foo<A>::value) { 
     std::cout << " has void foo"; 
    } else { 
     std::cout << " does not have void foo"; 
    } 
    std::cout << std::endl << "B "; 
    if (has_void_foo<B>::value) { 
     std::cout << " has void foo"; 
    } else { 
     std::cout << " does not have void foo"; 
    } 
    std::cout << std::endl << "C "; 
    if (has_void_foo<C>::value) { 
     std::cout << " has void foo"; 
    } else { 
     std::cout << " does not have void foo"; 
    } 
    std::cout << std::endl; 

    return 0; 
} 
+1

あなたはC++ 11で 'で'のstd :: is_void' 'を知っていますか? –

答えて

0

それはconstexpr機能に基づいて可能な解決策を、以下:

#include <type_traits> 

struct A { 
    int foo() { 
     return 0; 
    } 
}; 

struct B { 
    void foo() { 
    } 
}; 

struct C { 
    double foo() { 
     return 0; 
    } 
}; 

template<typename T, typename R, typename... Args> 
constexpr bool has_void_foo(R(T::*)(Args...)) { return std::is_void<R>::value; } 

int main() { 
    static_assert(not has_void_foo(&A::foo), "!"); 
    static_assert(has_void_foo(&B::foo), "!"); 
    static_assert(not has_void_foo(&C::foo), "!"); 
} 
関連する問題