compiler c++ c++11 type-inference

c++11 compiler



decltype, result_of o typeof? (2)

result_of no es una función ni un operador. result_of es una metafunción que tiene una función como parámetro de plantilla y establece el tipo de resultado en el tipo de miembro

typedef typename result_of<T::toCPD()>::type D;

Yo tengo:

class A { public: B toCPD() const;

Y:

template<typename T> class Ev { public: typedef result_of(T::toCPD()) D;

Después de instanciar Ev<A> , el compilador dice:

meta.h: 12: error: ''T :: toCPD'' no es un tipo

tampoco decltype ni typeof trabajo tampoco.


Como cualquier resultado que obtenga depende del parámetro de plantilla, typedef typename es necesario.

decltype es una característica estándar de C ++ 11. Es un "operador" que toma una expresión y devuelve un tipo.

typedef typename decltype( T().toCPD() ) D; // can''t use T:: as it''s nonstatic

Si T() no es válido ( T no predeterminado construible), querrá declval que es una función que toma un tipo y devuelve un valor inválido y sin sentido de ese tipo. declval solo se puede usar en contextos no decltype como decltype .

typedef typename decltype( std::declval<T>().toCPD() ) D;

Antes de C ++ 11, decltype era una extensión no estándar del compilador MSVC de Microsoft. Su comportamiento podría haber cambiado ligeramente por estandarización.

typeof es la extensión pre-C ++ 11 equivalente de GCC como decltype , que también se clonó en otros compiladores. Aquí está su documentación de GCC. Esa página no proporciona ninguna comparación entre las características, pero señala que typeof debe llamar __typeof__ cuando se usa un modo estándar ( -std=c++YY , que siempre se debe hacer), y está disponible tanto en C como en C ++.

En aras de la compatibilidad con C, __typeof__ no resolverá un tipo de referencia a partir de una expresión glvalue. Por lo tanto, solo es adecuado para C. Esto probablemente explica por qué la función C ++ no heredaba el nombre que se explica por sí mismo: GNU no estaba dispuesto a sacrificar la compatibilidad con versiones anteriores, mientras que a Microsoft le importa menos C y tal vez necesitaba menos cambios.

result_of es una result_of C ++ 11 (previamente estandarizada en la biblioteca ISO TR1 desde 2006). Es una plantilla que toma un tipo invocable (como una función int(void) , un puntero de función int(*)(void) , un operator() implementación de clase funtor operator() , o una función puntero-a-miembro &T::toCPD ) y una lista de tipos de argumentos para ese tipo, y proporciona el tipo de devolución si la llamada funcionaría.

Para usar result_of con un puntero a la función de miembro, debe incluir el tipo de objeto principal en la lista de argumentos como sustituto para this .

typedef typename std::result_of< decltype( & T::toCPD ) ( T * ) >::type D;

Sin embargo, esto es muy quebradizo porque &T::toCPD no se puede resolver si hay alguna sobrecarga, como una versión no const. ¡Esto es cierto a pesar del hecho de que T * o T const * deben escribirse explícitamente! En la mayoría de los casos, está mejor con decltype y declval .