Используя C ++, проверьте существование статического члена с помощью SFINAE, верните неправильное значение - PullRequest
4 голосов
/ 21 марта 2019

Я изучаю метапрограммирование шаблонов. При попытке проверить статический член, используя следующий код, второй 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;
};

1 Ответ

4 голосов
/ 21 марта 2019

Это ошибка MSVC.

Отчет об ошибке под названием: Выражение SFINAE проблема было подано для него.

В соответствии с решением, упомянутым в отчете, эта проблема исправленаи он доступен в последнем предварительном просмотре Visual Studio 2019.

Это работает правильно как в GCC, так и в Clang.

...