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
.