Я изучаю метапрограммирование шаблонов.
При попытке проверить статический член, используя следующий код, второй 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;
}
Я использую оптимизирующий компилятор Microsoft (R) C / C ++ версии 19.15.26732.1 для x64
true
true
false
false
Однако при компиляции с GCC возвращается ожидаемое значение
true
false
false
true
Когда определение has_b перед has_a (CTRL-XV has_b перед has_a), 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;
};