¿Qué es decltype con dos argumentos?

Editar, para evitar confusiones: decltype no acepta dos argumentos. Ver respuestas.

Las siguientes dos estructuras pueden usarse para verificar la existencia de una función miembro en un tipo T durante el tiempo de comstackción:

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

Creo que la idea es utilizar SFINAE cuando se comprueba la existencia de una función miembro, por lo que en caso de que p->foo() no sea válida, solo se define la versión de test de puntos suspensivos, que devuelve std::false_type . De lo contrario, el primer método se define para T* y devolverá std::true_type . El “cambio” real ocurre en la segunda clase, que hereda del tipo devuelto por la test . Esto parece inteligente y “ligero” en comparación con diferentes enfoques con is_same y cosas por el estilo.

El decltype con dos argumentos primero me pareció sorprendente, ya que pensé que simplemente tiene el tipo de expresión. Cuando vi el código anterior, pensé que era algo así como “intente comstackr las expresiones y siempre devuelva el tipo del segundo. Fallar si las expresiones no se comstackn” (así que oculte esta especialización, SFINAE).

Pero:

Entonces pensé que podría usar este método para escribir cualquier verificador “es una expresión válida”, siempre que dependa de algún tipo T Ejemplo:

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

http://ideone.com/dJkLPF

Esto, así que pensé, devolverá std::true_type si y solo si se define bar aceptando una T como el primer parámetro (o si T es convertible, etc.), es decir: if bar(*p) comstackría si fue escrito en algún contexto donde p se define de tipo T* .

Sin embargo, la modificación anterior siempre se evalúa como std::false_type . ¿Por qué es esto? No quiero arreglarlo con un código diferente y complicado. Solo quiero saber por qué no funciona como esperaba. Claramente, decltype con dos argumentos funciona diferente de lo que pensaba. No pude encontrar ninguna documentación; solo se explica con una expresión en todas partes.

    Es una lista de expresiones separadas por comas, el tipo es idéntico al tipo de la última expresión en la lista. Usualmente se usa para verificar que la primera expresión sea válida (comstackble, piense en SFINAE), la segunda se usa para especificar que decltype debería regresar en caso de que la primera expresión sea válida.

    decltype no toma dos argumentos. Simplemente, puede tener una expresión como argumento, y el operador de coma es una forma de crear expresiones. Según el párrafo 5.18 / 1:

    […] Un par de expresiones separadas por una coma se evalúa de izquierda a derecha; la expresión izquierda es una expresión de valor descartado (Cláusula 5). Cada cómputo de valor y efecto secundario asociado con la expresión izquierda se secuencia antes de cada cálculo de valor y efecto secundario asociado con la expresión correcta. El tipo y el valor del resultado son el tipo y el valor del operando correcto ; el resultado es de la misma categoría de valor que su operando derecho, y es un campo de bits si su operando derecho es un glvalue y un campo de bit. Si el valor del operando derecho es temporal (12.2), el resultado es temporal.

    Por lo tanto:

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