我正在学习模板元编程。 当尝试使用以下代码测试静态成员时,第二个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;
};
答案 0 :(得分:4)
这是MSVC错误。
为此提交了一个错误报告,标题为Expression SFINAE problem。
根据报告中提到的解决方案,此问题已修复,可以在最新的Visual Studio 2019预览版中找到。
这在GCC和Clang上均可正常使用。