使用C ++,使用SFINAE测试静态成员的存在,返回错误值

时间:2019-03-21 09:58:21

标签: c++ template-meta-programming

我正在学习模板元编程。 当尝试使用以下代码测试静态成员时,第二个SFINAE总​​是返回错误的值:

#include <cstdio>
#include <type_traits>

// ts_a
struct ts_a
{
    static int a;
};

// ts_b
struct ts_b
{
    static int b;
};

// has_a
template<typename T, typename = std::void_t<>>
struct has_a : std::false_type {};
template<typename T>
struct has_a<T, std::void_t<decltype( T::a )>> : std::true_type {};

// has_b
template<typename T, typename = std::void_t<>>
struct has_b : std::false_type {};
template<typename T>
struct has_b<T, std::void_t<decltype( T::b )>> : std::true_type {};

int main()
{
    printf( "%s\n", has_a<ts_a>::value ? "true" : "false" );
    printf( "%s\n", has_b<ts_a>::value ? "true" : "false" );
    printf( "%s\n", has_a<ts_b>::value ? "true" : "false" );
    printf( "%s\n", has_b<ts_b>::value ? "true" : "false" );  

    return 0;
}

我正在使用x64的Microsoft(R)C / C ++优化编译器版本19.15.26732.1

true
true
false
false

但是,当使用GCC进行编译时,它会返回预期值

true
false
false
true

当在has_a之前定义has_b(在has_a之前CTRL-XV has_b)时,MSVC返回

false
false
true
true

那么,这是编译器问题吗?

以下替代方法可在两种编译器上使用,但对非静态成员也返回true。有没有办法可以检测到真正的静态成员?

template <class T>                                                  
struct has_a_2
{                                           
    template<typename U>                        
    static std::true_type check( decltype( U::a )* );
    template<typename U>
    static std::false_type check(...);                          

public:                                                             
    static constexpr const bool value = decltype( check<T>( 0 ) )::value;
};

1 个答案:

答案 0 :(得分:4)

这是MSVC错误。

为此提交了一个错误报告,标题为Expression SFINAE problem

根据报告中提到的解决方案,此问题已修复,可以在最新的Visual Studio 2019预览版中找到。

这在GCC和Clang上均可正常使用。