In generale, per la deduzione per il successo, l'argomento deve avere la stessa forma generale del parametro. Esistono alcune eccezioni in cui è possibile ricavare(selezionando T = U &
), ma in questo caso non è stata specificata alcuna eccezione.
14.8.2.5, dedurre argomenti del template da un tipo [temp.deduct.type]
8 Un tipo di modello argomento T
, un argomento template TT
o un argomento di template non i
tipo possono essere dedotto se P
e A
avere una delle seguenti forme:
[...]
T&
T&&
[...]
Non è esattamente chiaro, ma questo richiede P
(parametro) e A
(l'argomento) per entrambi hanno la stessa forma. Devono essere entrambi del modulo T&
o entrambi del modulo T&&
.Le eccezioni, le circostanze in cui T &&
desumibile dalla U &
, sono fatte modificando T &&
al normale T
prima l'abbinamento avviene, in circostanze limitate:
10 Allo stesso modo, se P
ha una forma che contiene (T)
, allora ogni tipo di parametro Pi
del rispettivo parametro -type-list di P
viene confrontato con il corrispondente tipo di parametro Ai
del corrispondente parametro di tipo-list di A
. Se P
e A
sono tipi di funzione originati dalla deduzione quando si prende l'indirizzo di un modello di funzione (14.8.2.2) o quando si deducono gli argomenti del modello da una dichiarazione di funzione (14.8.2.6) e Pi
e Ai
sono parametri di livello superiore parametro di tipo-list di P
e A
, rispettivamente, Pi
viene regolata se è un riferimento rvalue ad un parametro di modello cv-qualificato ed Ai
è un riferimento assegnabile, nel qual caso il tipo di Pi
è cambiato per essere il modello tipo di parametro (ad esempio, T&&
viene modificato in T
). [...]
e
14.8.2.1 Dedurre argomenti di template da una chiamata di funzione [temp.deduct.call]
3 [...] Se P
è un riferimento di rvalore a un parametro di modello cv-non qualificato e l'argomento è un lvalue, il tipo "riferimento di lvalue a A
" viene utilizzato al posto di A
per la deduzione di tipo. [...]
ma nessuna eccezione simile si applica al tuo scenario.
E 'lo stesso principio che rende
template <typename T> struct S { };
template <typename T> void f(S<const T>) { }
int main() { f(S<void()>()); }
non valida: const T
non può essere dedotto dal void()
, anche se T = void()
darebbe esattamente questo risultato, e chiamando f<void()>
sarebbe successo.
risposta cancellato di Invernomuto ha dimostrato che è possibile utilizzare
template <typename... Types> // vv-- change here
void print_tuple(const std::tuple<Types...>& value)
invece: questo permette Types
a dedurre come riferimenti lvalue, come riferimenti rvalue, o come non-riferimenti, a seconda del tipo di value
.
Non è nemmeno necessario catturare una tupla in modo specifico. Perché non semplicemente 'modello void print_tuple (Tuple && value)'? –
0x499602D2
Dato che non era chiaro ad almeno due persone: la tua definizione 'print_tuple' * fa * consente la chiamata se gli argomenti del template sono esplicitamente specificati come 'print_tuple'. È una buona domanda perché il compilatore deduca i primi 'Tipi 'in modo diverso. –
hvd
@hvd Potrebbe essere perché una stringa letterale è un lvalue e viene inoltrata come tale. – 0x499602D2