Question

Le titre original était ici Solution pour le bogue SFINAE dans VS2005 C ++

Ceci est l'utilisation provisoire de SFINAE pour faire l'équivalent de la classe de modèle is_pod qui existe dans TR1 (En VS2005 il n'y a pas encore TR1). Il devrait avoir son valeur vrai membre lorsque le paramètre de modèle est un type POD (y compris les types primitifs et struct en eux) et faux quand il est pas (comme avec les constructeurs non triviales).

template <typename T> class is_pod
{
  public:

    typedef char Yes;
    typedef struct {char a[2];} No;

    template <typename C> static Yes test(int)
    {
      union {T validPodType;} u;
    }
    template <typename C> static No test(...)
    {
    }
    enum {value = (sizeof(test<T>(0)) == sizeof(Yes))};
};

class NonPOD
{
  public:
    NonPod(const NonPod &);
    virtual ~NonPOD();
};

int main()
{
  bool a = is_pod<char>::value;
  bool b = is_pod<NonPOD>::value;
  if (a) 
    printf("char is POD\n");
  if (b)
    printf("NonPOD is POD ?!?!?\n");
  return 0;
}

Le problème est, non seulement VS 2005 n'a pas TR1, il ne se soucient de l'union ci-dessus (qui ne devrait pas être valide lorsque le paramètre de modèle n'est pas un POD), donc a et b évaluer à vrai.


Merci pour les réponses affichées ci-dessous. Après avoir lu attentivement (et le code), je compris que ce que je voulais faire était vraiment une mauvaise approche. L'idée était de combiner le comportement SFINAE avec une adaptation au modèle must_be_pod (que je trouve dans le livre Imperfect C ++ , mais il se trouve dans un autre endroit, aussi). En fait, cela nécessiterait un ensemble tout à fait particulier de règles pour SFINAE, qui ne sont pas ce que la norme définit, évidemment. Ce n'est pas vraiment un bug dans VS, après tout.

Était-ce utile?

La solution

Le plus gros problème avec votre approche est que vous ne faites pas SFINAE ici -. SFINAE applique uniquement aux types de paramètres et le type de retour ici

Cependant, de toutes les situations SFINAE dans la norme, ne s'applique à votre situation. Ils sont

  • tableaux de vide, des références, des fonctions ou de taille non valide
  • membre de type qui n'est pas un type
  • des pointeurs vers des références, des références à des références, des références à Void
  • pointeur vers un membre d'un type non-classe
  • conversions non valides de paramètres de valeur de modèle
  • types de fonction avec des arguments de type void
  • const / type de fonction volatile

C'est probablement la raison pour laquelle dans la documentation Boost, il y a:

  

Sans certains (encore non spécifié) aide   du compilateur, ne sera jamais ispod   rapport qu'une classe ou struct est un   COSSE; ce qui est toujours sûr, si possible   sous-optimale. À l'heure actuelle (mai 2005) seulement   MWCW 9 et Visual C ++ 8 ont la   compilateur _intrinsics nécessaire.

Autres conseils

Cela ne fonctionne pas avec VS2008 non plus, mais je suppose que vous saviez que trop. SFINAE est pour déduisant arguments de modèle pour les paramètres de modèle; vous ne pouvez pas déduire vraiment le type de quelque chose qui révèle le constructeur-ness d'un type, même si vous pouvez créer un type qui est incompatible avec un autre type (par exemple, les syndicats ne peuvent pas utiliser non-POD).

En fait, VS 2008 utilise le soutien du compilateur pour des caractères à mettre en œuvre std::tr1::type_traits.

Je ne suis pas sûr de la façon dont vous essayez de faire SFINAE ici, puisque is_pod<T>::test(...) correspondra is_pod<T>::test(0) aussi. Peut-être que si vous utilisez un autre type au lieu de « int » vous obtiendrez une meilleure correspondance:

template <typename T> class is_pod
{
  struct my_special_type { };
  public:
    typedef char Yes;
    typedef struct {char a[2];} No;

    template <typename C> static Yes test(my_special_type)
    {
      union {T validPodType;} u;
    }

    template <typename C> static No test(...)
    {
    }
    enum {value = (sizeof(test<T>(my_special_type())) == sizeof(Yes))};
};

Vous pouvez également regarder Boost.Enable_i f pour faire votre SFINAE pour vous -. à moins que vous essayez de mettre en œuvre votre propre bibliothèque ou pour une raison quelconque

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top