2013-07-05 21 views
11

Nel codice seguenteinferenza con 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 può dedurre con auto ma non con template.

Perché C++ lo proibisce?

+1

Probabilmente perché '{0}' viene trattato come una sorta di "inizializzazione letterale" e intuitivamente si puo' t spostarsi da un valore letterale (o avere un riferimento di rvalue a uno da cui si potrebbe passare). –

+1

Ti manca '#include ', a proposito. – chris

+0

@chris - hai ragione. Modificherò –

risposta

9

Credo che questo sia dovuto al 14.8.2.1/1:

[...] un argomento lista di inizializzazione fa sì che il parametro da considerare un contesto non-dedotta (14.8.2.5). [Esempio: [...]

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

- esempio end]

Ora si potrebbe pensare che è solo auto modello detrazione argomento, ma per le liste imbracciò auto riceve un trattamento speciale in 7.1.6.4/6:

sostituzione di occorrenze di auto con una nuova invente d digitare il parametro del modello U o, se l'inizializzatore è un controverso-init-list (8.5.4), con std::initializer_list<U>. [...] [Esempio:

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

- esempio end]

+0

ci deve essere qualche caso strano che rende il comitato dare il trattamento speciale solo per auto –

+1

@ a.lasram: Suppongo che non fa male a consentire 'auto x = {1, 2, 3};' , quindi potresti anche averlo. D'altra parte, probabilmente * sarebbe * offeso per consentire la deduzione degli argomenti del template (sto pensando ai costruttori). –