2013-07-05 31 views
11

Im folgenden CodeTypinferenz mit rvalue initializer_list

#include <initializer_list> 
#include <utility> 

template<typename T> void f(T&& x) {} 
template<typename T> void g(std::initializer_list<T> x) {} 

int main() 
{ 
    auto x = {0}; // OK 
    auto&& y = {0}; // OK 
    g(x); // OK 
    g(std::move(x)); // OK 
    g({0}); // OK 
    f(x); // OK 
    f(std::move(x)); // OK 
    f({0}); // failure 
    return 0; 
} 

rvalue initializer_list mit auto aber nicht mit template abgeleitet werden.

Warum verbietet C++ das?

+1

Wahrscheinlich, weil '{0}' wird als eine Art "wörtlichen initializer" behandelt und intuitiv können Sie‘ t Bewegen Sie sich von einem Literal (oder haben Sie eine Referenz auf einen Wert, aus dem Sie sich bewegen könnten). –

+1

Sie vermissen '#include ', nebenbei bemerkt. – chris

+0

@chris - du hast Recht. Ich werde bearbeiten –

Antwort

9

Ich glaube, dies zu 14.8.2.1/1 Ursachen zurückzuführen ist:

[...] ein Initialisiererliste Argument bewirkt, dass der Parameter einen nicht-abgeleitete Kontextes (14.8.2.5) in Betracht gezogen werden. [Beispiel: [...]

template<class T> void g(T); 
g({1,2,3});     // error: no argument deduced for T 

- Ende Beispiel]

Jetzt können Sie denken, dass auto nur Template-Argument Abzug, aber für verspannt Listen auto erhält eine besondere Behandlung in 7.1.6.4/6:

Ersetzen der Vorkommen von auto mit einem neuen Invente d Geben Sie den Vorlagenparameter U ein, oder, wenn der Initialisierer eine stained-init-Liste (8.5.4) ist, mit std::initializer_list<U>. [...] [Beispiel:

auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int> 

- Ende Beispiel]

+0

gibt es einige seltsame Fall, der das Komitee gibt die spezielle Behandlung nur auf Auto –

+1

@ a.lasram machen: Ich nehme an, es tut nicht weh zu erlauben 'auto x = {1, 2, 3};' , also könntest du es genauso gut haben. Auf der anderen Seite würde es * wahrscheinlich * weh tun, Template-Argumentabzug zuzulassen (ich denke Konstruktoren). –