Pregunta

El título original era aquí Solución para SFINAE error en VS2005 C ++

Este es el uso provisional de SFINAE para hacer el equivalente de la clase de plantilla is_pod que existe en TR1 (En VS2005 no hay TR1 aún). Debe tener su valor miembro de verdad cuando el parámetro de plantilla es un tipo POD (incluyendo tipos primitivos y estructuras hechas de ellos) y falso cuando no lo es (al igual que con los constructores no 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;
}

El problema es, no sólo VS 2005 no tiene TR1, no se preocupan por la unión anterior (que no debería ser válido cuando el parámetro de plantilla no es un POD), por lo tanto A como B a evaluar verdadera.


Gracias por las respuestas publicadas a continuación. Después de leerlos con atención (y el código) me di cuenta de que lo que yo estaba tratando de hacer era realmente un enfoque equivocado. La idea era combinar el comportamiento SFINAE con una adaptación a la plantilla must_be_pod (que me encontré en el libro Imperfect C ++ , pero se puede encontrar en otros lugares, también). En realidad, esto requeriría un conjunto muy particular de reglas para SFINAE, que no son lo que define el estándar, obviamente. Esto no es realmente un error en VS, después de todo.

¿Fue útil?

Solución

El mayor problema con el enfoque es que no hace SFINAE aquí -. SFINAE sólo se aplica a los tipos de parámetros y retorno tipo aquí

Sin embargo, de todas las situaciones SFINAE en la norma, no se aplica a su situación. Son

  • matrices de vacío, referencias, funciones, o de tamaño no válido
  • miembro de tipo que no es un tipo
  • punteros a referencias, las referencias a las referencias, las referencias para anular
  • puntero a miembro de un tipo no-clase
  • conversiones no válidas de parámetros de valor de plantilla
  • los tipos de función con argumentos de tipo void
  • const / volátil tipo de función

Eso es probablemente por eso que en la documentación Boost, existe:

  

Sin un poco de ayuda (aún no especificado)   del compilador, ispod nunca lo hará   informan de que una clase o estructura es una   VAINA; esto es siempre seguro, si es posible   sub-óptima. Actualmente (mayo de 2005), sólo   Mwcw 9 y Visual C ++ 8 tienen la   necesaria compilador _intrinsics.

Otros consejos

Esto no funciona con VS2008 bien, pero sospecho que también lo sabía. SFINAE es para deducir argumentos de plantilla para los parámetros de plantilla; realmente no se puede deducir el tipo de algo que revela el constructor-dad de un tipo, a pesar de que se puede crear un tipo que no es compatible con otro tipo (es decir, los sindicatos no pueden utilizar no-POD).

De hecho, VS 2008 utiliza el apoyo del compilador para los rasgos de implementar std::tr1::type_traits.

No estoy seguro acerca de la forma en que está tratando de hacer SFINAE aquí, ya is_pod<T>::test(...) coincidirá is_pod<T>::test(0) también. Tal vez si se utiliza un tipo diferente en lugar de 'int' se obtendría una mejor correspondencia:

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

También puede ser que desee mirar a Boost.Enable_i f para hacer su SFINAE para usted -. a menos que estés tratando de poner en práctica su propia biblioteca o por alguna razón

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top