c++c++11visual-studio-2015msvc12msvc14

method existence checker code breaks in vs2015


The following code checks if foo() method exists in class A. This code is compiling under vs2013, but static assertion fails on vs2015. Which compiler version tells the truth? If vs2015, then how to fix the code?

#include <type_traits>

struct MethodTester_foo {
    template<typename U, typename MethodType>
    static auto test(U* p) -> decltype(static_cast<MethodType>(U::foo));
    template<typename U, typename MethodType> static auto test(...)->std::false_type;
};

template <typename Class, typename MethodType, class MethodTester>
using HasMethod =
typename std::conditional
<
    std::is_same<
        decltype(MethodTester::template test<Class, MethodType>(0)),
        std::false_type
    >::value,
    std::false_type, std::true_type
>::type;

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

static_assert(HasMethod<A, int(A::*)(), MethodTester_foo>::value, "Has no method named foo");

Solution

  • 2015 is correct. Instead of U::foo you need &U::foo. The &ClassName::methodName is the only way to get a pointer to a member function in C++.


    As an aside, your code can be substantially simplified:

    #include <type_traits>
    
    struct MethodTester_foo {
        template<typename U, typename MethodType, typename = decltype(static_cast<MethodType>(&U::foo))>
        static auto test(U* p) -> std::true_type;
        template<typename U, typename MethodType>
        static auto test(...) -> std::false_type;
    };
    
    template <typename Class, typename MethodType, class MethodTester>
    using HasMethod = decltype(MethodTester::template test<Class, MethodType>(0));
    
    struct A { int foo() { return 1; } };
    
    static_assert(HasMethod<A, int(A::*)(), MethodTester_foo>::value, "Has no method named foo");