2011-10-01 13 views
11

Acabo de ver this really nice talkRock Hard: C++ Evolucionando por Boris Jabes. En la sección de la conversación acerca de orden superior-programación genérica dice que el siguiente es un ejemplo de una función que es más genérico en cuanto a su tipo de retorno y reduce el número de función de plantilla sobrecargasUso esclarecedor de C++ 11 decltype

template <typename Func> 
auto deduce(const Func & f) -> decltype(f()) 
{..} 

Este sin embargo se puede realizar usando sintaxis de la plantilla normal de la siguiente manera

template <typename Func> 
Func deduce(const Func & f) 
{..} 

así que supongo que el ejemplo elegido no realmente muestran el poder único de decltype. ¿Alguien puede dar un ejemplo de más que ilumine el uso de de decltype?

+7

No. El primer ejemplo significa que '' 'deducir (f)' '' devuelve el tipo de '' 'resultado de Func'''. El segundo ejemplo significa que '' 'deduce (f)' '' devuelve '' 'Func'''. ¿Ves la diferencia? –

+0

Aah, lo siento, extrañé el '()' extra en el argumento para 'decltype'. Mi error. –

Respuesta

25

Sus sospechas son incorrectas.

void f() { } 

Ahora deduce(&f) tiene por tipo void, pero con su reescritura, que tiene por tipo void(*)(). En cualquier caso, en cualquier lugar que desee obtener el tipo de una expresión o declaración, utilice decltype (tenga en cuenta la sutil diferencia entre estos dos. decltype(x) no es necesariamente lo mismo que decltype((x))).

Por ejemplo, lo más probable es que su implementación de la biblioteca estándar contiene algún lugar líneas como

using size_t = decltype(sizeof(0)); 
using ptrdiff_t = decltype((int*)0 - (int*)0); 
using nullptr_t = decltype(nullptr); 

Averiguar el tipo de retorno correcto de add ha sido un problema difícil a través del pasado de C++. Este es ahora un ejercicio fácil.

template<typename A, typename B> 
auto add(A const& a, B const& b) -> decltype(a + b) { return a + b; } 

poco conocido es que se puede utilizar decltype antes :: y en un nombre de pseudo destructor

// has no effect 
(0).~decltype(0)(); 

// it and ite will be iterators into an initializer list 
auto x = { 1, 2, 3 }; 
decltype(x)::iterator it = x.begin(), ite = x.end(); 
+1

¿Podría explicar esto un poco: '(0). ~ Decltype (0)();'? Me temo que no lo entiendo –

1
std::for_each(c.begin(), c.end(), [](decltype (c.front()) val){val*=2;}); 

Autodeducting la value_type del recipiente c no se puede hacer sin decltype.

+1

No se puede hacer solo si está usando lambdas, dado que no son polimórficos (aún así, esperemos que estén en C++ y). Si estaba utilizando un objeto de función polimórfica, se deducirá automáticamente. –

0

Un lugar que lo uso, es donde tengo que hacer una variable que debe tener el mismo tipo de de otra variable. pero no estoy seguro si en el futuro el tipo se mantendrá igual o no.

void foo(int a)//maybe in future type of a changed 
{ 
    decltype(a) b; 
    //do something with b 
}