Domanda

Il titolo originale era qui Soluzione per SFINAE bug in VS2005 C ++

Questa è l'uso sperimentale di SFINAE per rendere l'equivalente per la classe template is_pod che esiste in TR1 (in VS2005 non c'è TR1 ancora). Esso dovrebbe avere il suo valore membro vero quando il parametro di modello è un tipo di POD (inclusi i tipi primitivi e le strutture fatte di loro) e false quando non è (come con i costruttori non banali).

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

Il problema è, non solo VS 2005 non ha TR1, non si preoccupano il sindacato di cui sopra (che non dovrebbe essere valida quando il parametro modello non è un POD), così sia A che B restituire vero.


Grazie per le risposte postato qui sotto. Dopo aver letto con attenzione loro (e il codice) mi sono reso conto che quello che stavo cercando di fare è stato davvero un approccio sbagliato. L'idea era di combinare il comportamento SFINAE con un adattamento al modello must_be_pod (che ho trovato nel libro imperfetta C ++ , ma lo si può trovare in un altro posti, anche). In realtà, questo richiederebbe piuttosto un particolare insieme di regole per SFINAE, che non sono ciò che lo standard definisce, ovviamente. Questo non è un bug in VS, dopo tutto.

È stato utile?

Soluzione

Il problema più grande con il vostro approccio è non fai SFINAE qui -. SFINAE si applica solo ai tipi di parametri e di ritorno Tipo qui

Tuttavia, di tutte le situazioni SFINAE nella norma, nessuno si applica alla vostra situazione. Sono

  • array di vuoto, i riferimenti, le funzioni, o di dimensione non valida
  • utente tipo che non è un tipo
  • puntatori a riferimenti, i riferimenti ai riferimenti, riferimenti revocatorie
  • puntatore a membro di un tipo non-class
  • conversioni non valide di parametri di valore template
  • tipi di funzione con argomenti di tipo void
  • const / tipo di funzione volatile

Questo è probabilmente il motivo per cui nella documentazione Boost, c'è:

  

Senza un aiuto (come ancora non specificata)   dal compilatore, ispod non sarà mai   riferiscono che una classe o struct è un   POD; questo è sempre sicuro, se, eventualmente,   sub-ottimale. Attualmente (maggio 2005) solo   Mwcw 9 e Visual C ++ 8 hanno il   necessaria compilatore-_intrinsics.

Altri suggerimenti

Questo non funziona con VS2008 sia, ma ho il sospetto si sapeva anche questo. SFINAE è per dedurre argomenti di template per i parametri del modello; non si può davvero dedurre il tipo di cosa che rivela il costruttore-ness di un tipo, anche se è possibile creare un tipo che non è compatibile con un altro tipo (vale a dire, i sindacati non possono utilizzare non-POD).

In realtà, VS 2008 utilizza il supporto del compilatore per i tratti di implementare std::tr1::type_traits.

Non sono sicuro circa il modo in cui si sta cercando di fare SFINAE qui, dal momento che is_pod<T>::test(...) corrisponderà is_pod<T>::test(0) troppo. Forse, se si utilizza un tipo diverso, invece di 'int' si otterrebbe una migliore corrispondenza:

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

Si potrebbe anche voler guardare Boost.Enable_i f per fare la tua SFINAE per te -. a meno che non si sta cercando di implementare la propria libreria o per qualche motivo

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top