Cosa è decltype con due argomenti?

Modifica, per evitare confusione: decltype non accetta due argomenti. Vedi le risposte.

Le seguenti due strutture possono essere utilizzate per verificare l’esistenza di una funzione membro su un tipo T durante la compilazione:

 // Non-templated helper struct: struct _test_has_foo { template static auto test(T* p) -> decltype(p->foo(), std::true_type()); template static auto test(...) -> std::false_type; }; // Templated actual struct: template struct has_foo : decltype(_test_has_foo::test(0)) {}; 

Penso che l’idea sia usare SFINAE quando si verifica l’esistenza di una funzione membro, quindi nel caso in cui p->foo() non sia valido, solo la versione di test di ellissi, che restituisce lo std::false_type è definita. Altrimenti il ​​primo metodo è definito per T* e restituirà std::true_type . L’attuale “switch” avviene nella seconda class, che eredita dal tipo restituito dal test . Questo sembra intelligente e “leggero” rispetto ai diversi approcci con is_same e cose del genere.

Il decltype con due argomenti mi è sembrato inizialmente sorprendente, poiché pensavo che ottenesse solo il tipo di espressione. Quando ho visto il codice sopra, ho pensato che fosse qualcosa come “prova a compilare le espressioni e restituisci sempre il tipo del secondo. Fallisci se le espressioni non riescono a compilare” (quindi nascondi questa specializzazione, SFINAE).

Ma:

    Poi ho pensato che avrei potuto utilizzare questo metodo per scrivere qualsiasi correttore “è un’espressione valida”, a patto che dipenda da qualche tipo T Esempio:

     ... template static auto test(T* p) -> decltype(bar(*p), std::true_type()); ... 

    http://ideone.com/dJkLPF

    Questo, quindi ho pensato, restituirà uno std::true_type se e solo se la bar è definita accettando una T come primo parametro (o se T è convertibile, ecc …), cioè: se bar(*p) si compilerebbe se è stato scritto in un contesto in cui p è definito di tipo T* .

    Tuttavia, la modifica sopra valuta sempre su std::false_type . Perchè è questo? Non voglio sistemarlo con un codice diverso complicato. Voglio solo sapere perché non funziona come mi aspettavo. Chiaramente, decltype con due argomenti funziona diversamente da come pensavo. Non sono riuscito a trovare alcuna documentazione; è spiegato solo con un’espressione ovunque.

    È un elenco di espressioni separate da virgole, il tipo è identico al tipo di ultima espressione nell’elenco. Solitamente viene usato per verificare che la prima espressione sia valida (compilabile, si pensi a SFINAE), la seconda è usata per specificare che decltype dovrebbe ritornare nel caso in cui la prima espressione sia valida.

    decltype non decltype due argomenti. Semplicemente, può avere un’espressione come argomento, e l’operatore virgola è un modo per creare espressioni. Per paragrafo 5.18 / 1:

    […] Una coppia di espressioni separate da una virgola viene valutata da sinistra a destra; l’espressione sinistra è un’espressione di valore scartato (clausola 5). Ogni calcolo del valore ed effetto collaterale associato all’espressione sinistra viene sequenziato prima di ogni calcolo del valore ed effetto collaterale associato all’espressione corretta. Il tipo e il valore del risultato sono il tipo e il valore dell’operando di destra ; il risultato è della stessa categoria di valore dell’operando di destra, ed è un campo di bit se il suo operando di destra è un glivalue e un campo di bit. Se il valore dell’operando di destra è temporaneo (12.2), il risultato è temporaneo.

    Perciò:

     static_assert(std::is_same::value, "Will not fire");