如何使用 SFINAE 检查静态常量成员的存在

How to check presence of static const member with SFINAE

假设我有几个带有可选字段的结构:

struct Param1
{
    static const bool x = true;
};

struct Param2
{
};

并且想写模板函数

template <class ParamType>
bool ReturnParam();

如果静态字段 x 存在,应该 return ParamType::x,否则应该 return false

我想一些 SFINAE 魔术应该有所帮助。

约束

我使用的是 MSVC 2010,所以我无法使用大部分 C++11 功能。

我使用以下特征:

#define DEFINE_HAS_SIGNATURE(traitsName, funcName, signature)               \
    template <typename U>                                                   \
    class traitsName                                                        \
    {                                                                       \
    private:                                                                \
        template<typename T, T> struct helper;                              \
        template<typename T>                                                \
        static char check(helper<signature, &funcName>*);                   \
        template<typename T> static int check(...);                         \
    public:                                                                 \
        enum { value = sizeof(check<U>(0)) == sizeof(char)};                \
    }

DEFINE_HAS_SIGNATURE(has_x, T::x, const bool *);

然后SFINAE或标签调度:

template <typename T>
typename std::enable_if<has_x<T>::value, bool>::type
ReturnParam()
{
    return T::x;
}

template <typename T>
typename std::enable_if<!has_x<T>::value, bool>::type
ReturnParam()
{
    return false;
}

此代码完美运行:

template<typename T, typename MemberPtrGetter>
struct has_member_impl
{
private:
    template<typename U> static char Test(typename MemberPtrGetter::template type<U>*);
    template<typename U> static int Test(...);

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


template <typename T, typename MemberPtrGetter>
struct has_member: public std::integral_constant<bool, has_member_impl<T, MemberPtrGetter>::value>
{
};

struct StaticMemberGetter
{
    template <typename T, const bool = T::x>
    struct type
    {
    };
};

struct Param1
{
    static const bool x = true;
};

struct Param2
{
};

template <typename Param, typename T = void> 
struct ExtractParam
{
    static const bool x = false;
};

template <typename Param>
struct ExtractParam<Param, std::true_type>
{
    static const bool x = Param::x;
};

template <typename Param>
bool ReturnParam()
{
    return ExtractParam<Param, has_member<Param, StaticMemberGetter>>::x;
}