4 votes

En utilisant C++, tester l'existence d'un membre statique en utilisant SFINAE, retourner une valeur erronée.

J'apprends la métaprogrammation de modèles. Lorsque j'essaie de tester un membre statique en utilisant le code suivant, le second SFINAE renvoie toujours une valeur erronée :

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

J'utilise le compilateur optimisant Microsoft (R) C/C++ version 19.15.26732.1 pour x64.

true
true
false
false

Cependant, lors de la compilation avec GCC, il retourne la valeur attendue.

true
false
false
true

Quand on définit has_b avant has_a ( CTRL-XV has_b avant has_a ), MSVC retourne

false
false
true
true

Alors, est-ce un problème de compilateur ?

L'alternative suivante fonctionne sur les deux compilateurs, mais elle renvoie également true pour les membres non-statiques. Existe-t-il un moyen de détecter les membres statiques réels ?

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

4voto

P.W Points 3960

C'est un bogue de MSVC.

Un rapport de bogue intitulé : Expression du problème SFINAE a été déposée pour elle.

Conformément à la solution mentionnée dans le rapport, ce problème est corrigé et il est disponible dans la dernière preview Visual Studio 2019.

Cela fonctionne correctement à la fois sur GCC et Clang.

0 votes

Merci pour cette réponse rapide, je suppose que je dois améliorer mes compétences en matière de recherche sur Google.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X