2014-07-27 20 views
9

Perché decltype non può essere aggiunto implicitamente a un'espressione quando era previsto il tipo?Perché decltype non è implicito?

template <class X, class Y, class Z> 
auto foo(X x, Y y, Z z){ 
    std::vector<decltype(x+y*z)> values; // valid in c++11/c++14 
    //std::vector<x+y*z> values;   // invalid 
    values.push_back(x+y*z); 
    return values;      // type deduced from expression - OK 
} 

In C++ 14 i compilatori saranno in grado di dedurre il tipo di ritorno della funzione in base alle espressioni di ritorno. Perché questo non può essere esteso a nessuna conversione di 'espressione -> tipo'?

Lo stesso si applica a declval, perché devo scrivere:

std::vector<decltype(declval<X>() + declval<Y>() * declval<Z>())> values; 

invece di:

std::vector<X+Y*Z> values; 
+0

'decltype' è davvero così fastidioso da digitare in cambio di essere chiaramente un tipo invece di prendere un momento per capire se un'espressione è un tipo o un valore? – chris

+3

Sono abbastanza sicuro che possa introdurre un parsing ambiguo ... – Jarod42

+3

... per pochissimi benefici. C'è già un sacco di cose implicite in corso in C++. Esplicito = buono, implicito = cattivo. – jrok

risposta

11

Se implicita aggiunta di decltype sarebbe stato permesso, alcuni modelli molto comune sarebbe diventato ambiguo, o addirittura impossibile da esprimere.


consideri il seguente esempio:

struct tp 
{ 
    template<typename T> 
    void foo() { cout << "Type parameter\n"; } 

    template<int Value> 
    void foo() { cout << "Value parameter\n"; } 
}; 

int main() 
{ 
    const int x = 1; 
    const int y = 2; 
    const int z = 3; 

    tp t1; 
    t1.foo<x*y+z>(); 
    t1.foo<decltype(x*y+z)>(); // Oops ! different version of foo() 
    t1.foo<int>(); 

    return 0; 
} 

uscita:

parametro Valore

parametro Type

parametro Type

Se decltype viene implicitamente aggiunto t1.foo<x*y+z>();, la versione sbagliata di foo() si chiama.

  • C++ politica per esprimere ciò che si fa ed evitare quando possibile qualsiasi lavoro implicito del compilatore IMHO è una cosa molto buona. Rende le cose più facili da leggere, da capire e da mantenere.
  • Dopo tutto, decltype è solo 8 lettere

Live demo here.

+0

Per prima cosa, il tuo esempio è malformato perché x, y, z non sono constexpr. In secondo luogo questo mi può uno dei rari casi in cui decltype sarà davvero necessario. – p2rkw

+7

@ p2rkw Non sono * constexpr *, ma sono espressioni costanti. – jrok

+0

Esempi di "cose ​​implicite fatte dal compilatore": default + copy + move ctor, copy + move assignment-operator, ... – Deduplicator

Problemi correlati