如何检查SFINAE是否存在静态常量成员

How to check presence of static const member with SFINAE

本文关键字:存在 是否 静态 常量 成员 SFINAE 何检查 检查      更新时间:2023-10-16

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

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

并想编写模板函数

template <class ParamType>
bool ReturnParam();

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

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

约束

我使用的是 MSVC 2010,因此无法使用C++11 功能中的大多数。

这段代码完美运行:

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;
}

我使用以下特征:

#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;
}