2011-10-01 17 views
11

Ho appena visto this really nice talkRock Hard: C++ Evolvente di Boris Jabes. Nella sezione del discorso riguardante di ordine superiore programmazione generica dice che il seguente è un esempio di una funzione che è più generico per quanto riguarda il tipo di ritorno e porta a meno funzione template SovraccarichiUtilizzo illuminante di C++ 11 decltype

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

Questo tuttavia può essere realizzata utilizzando la sintassi modello di pianura come segue

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

quindi credo che l'esempio scelto non significa davvero mostrano il potere unico di decltype. Qualcuno può dare un esempio di più illuminante dell'uso di decltype?

+7

No. Il primo esempio significa che '' 'dedurre (f)' '' restituisce il tipo di risultato '' 'di Func'''. Il secondo esempio significa che '' 'deduce (f)' '' restituisce '' 'Func'''. Vedi la differenza? –

+0

Aah, mi dispiace di aver perso l'extra '()' dentro l'argomento di 'decltype'. Errore mio. –

risposta

25

I tuoi sospetti non sono corretti.

void f() { } 

Ora deduce(&f) ha digitare void, ma con il vostro riscrittura, ha digitare void(*)(). In ogni caso, ovunque si desideri ottenere il tipo di un'espressione o di una dichiarazione, si utilizza decltype (notare la sottile differenza tra questi due. decltype(x) non è necessariamente uguale a decltype((x))).

Per esempio, è probabile che l'implementazione della libreria standard contiene qualche linee come

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

Scoprire il tipo di ritorno corretto di add è stato un problema difficile per tutto passato C++. Questo è ora un esercizio facile.

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

poco conosciuto è che è possibile utilizzare decltype prima :: e in un nome di pseudo distruttore

// 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

Puoi spiegarlo un po ': '(0). ~ Decltype (0)();'? Ho paura di non capirlo. –

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

Autodeducting la value_type del contenitore c non può essere fatto senza decltype.

+1

Non può essere fatto solo se stai usando lambda, dato che non sono polimorfici (eppure speriamo che siano in C++ y). Se si stesse utilizzando un oggetto funzione polimorfico, verrà dedotto automaticamente. –

0

Un posto che lo uso, è dove ho bisogno di fare una variabile che deve avere lo stesso tipo di un'altra variabile. ma non sono sicuro se in futuro il tipo rimarrà lo stesso o no.

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