2015-05-20 18 views
5

Il seguente codice dovrebbe essere, che ne so, "Non dedotto contesto" (o no?)contesto non dedotta in funzione di modello variadic

template <class... X, class Y> 
void f(X... args, Y y) 
{ 

} 

int main() 
{ 
    f(12); 
    f<int, int, int>(1, 2, 3, 4); 
} 

ma g ++ 4.9 compila per entrambe le istanze di f in main. .. Qualcuno può spiegare?

+0

Le chiamate vengono ottimizzate? –

risposta

0

Questa regola si applica solo ai modelli di classe, non alle funzioni, poiché i modelli possono essere dedotti per le funzioni. Se si prova che su un modello di classe, si vedrà l'errore:

template <class... X, class Y> 
class C { // This won't compile. 
}; 

Per ulteriori informazioni, fare riferimento alla pagina 7 in http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2242.pdf:

If a template-parameter of a class template is a template parameter pack, it must be the last template-parameter. Note: This is not a requirementThese are not requirements for function templates because template arguments might be deduced (14.8.2)

0

La prima chiamata f(12) è malato -formed. Un parametro-pack che non appare al termine di un parametro di dichiarazione è un contesto non dedotta per [temp.deduct.type] /p5.7:

The non-deduced contexts are:

— [..]

A function parameter pack that does not occur at the end of the parameter-declaration-list

Inoltre in [temp.deduct.call ]/p1:

For a function parameter pack that occurs at the end of the parameter-declaration-list, the type A of each remaining argument of the call is compared with the type P of the declarator-id of the function parameter pack. Each comparison deduces template arguments for subsequent positions in the template parameter packs expanded by the function parameter pack. When a function parameter pack appears in a non-deduced context (14.8.2.5), the type of that parameter pack is never deduced.

[ Example:

template<class ... Types> void f(Types& ...); 
template<class T1, class ... Types> void g(T1, Types ...); 
template<class T1, class ... Types> void g1(Types ..., T1); 

void h(int x, float& y) { 
    const int z = x; 
    f(x, y, z); // Types is deduced to int, float, const int 
    g(x, y, z); // T1 is deduced to int; Types is deduced to float, int 
    g1(x, y, z); // error: Types is not deduced 
    g1<int, int, int>(x, y, z); // OK, no deduction occurs 
} 

— end example ]

Così il parametro pacchetto X... non può essere dedotta dagli argomenti della funzione e la deduzione modello argomento non. GCC accetta la prima chiamata invece di rifiutare il modello per non dedurre 12 in modo che sembri un bug.

La seconda chiamata, f<int, int, int>(1, 2, 3, 4), tuttavia, è ben formata in base a [temp.deduct]/p6. Gli argomenti del template esplicitamente specificati vengono immediatamente sostituiti per i parametri del modello del modello di funzione. Questo significa X = {int, int, int}. Template detrazione argomento procede poi con Y essere dedotta dalla tesi più a destra come int:

At certain points in the template argument deduction process it is necessary to take a function type that makes use of template parameters and replace those template parameters with the corresponding template arguments. This is done at the beginning of template argument deduction when any explicitly specified template arguments are substituted into the function type, and again at the end of template argument deduction when any template arguments that were deduced or obtained from default arguments are substituted.

Si noti che anche ([temp.deduct]/p2):

There must not be more arguments than there are parameters unless at least one parameter is a template parameter pack, and there shall be an argument for each non-pack parameter.

Clang non accetta l'ultima funzione chiama, ma GCC lo fa. Credo che questo sia un bug di Clang.


Si noti che non v'è un open CWG issue 1609 riguardanti l'uso di default-argomenti in seguito al verificarsi di un parametro-pack. C'è anche LLVM Bug 21774 che contesta il comportamento di Clang in quel contesto.

Problemi correlati