2016-07-28 21 views
6

Poniższy kod kompiluje się i działa poprawnie.Zestaw parametrów szablonu funkcji nie znajduje się na końcu listy parametrów

void foo() { 

} 

template <typename T, typename... Args> 
void foo(T x, Args... args) { 
    cout << x << endl; 
    foo(args...); 
} 

// inside main() 
foo(1,1,1); 

Ten drugi kod nie kompilacji:

void foo() { 

} 

template <typename... Args, typename T> 
void foo(Args... args, T x) { 
    foo(args...); 
    cout << x << endl; 
} 

// inside main() 
foo(1,1,1); 

Kompilator mówi, że nie ma pasującej funkcji dla wywołania do foo(1,1,1) i mówi, że foo(Args... args, T x) jest kandydatem, ale szablon argumentu odliczenie/substytucja nie powiodła się, ponieważ kandydat oczekuje 1 argumentu, ale 3 zostały dostarczone.

Czy istnieje jakaś niejednoznaczność w tej sytuacji, której nie poradzi sobie żaden kompilator? Ten błąd kompilacji wydaje mi się nielogiczny. Być może nie jest to zgodne, celowo, ze standardem C++?

Odpowiedz

5

Interesującym z Clang's error message jest:

main.cpp:11:6: note: candidate template ignored: couldn't infer template argument 'T' 

void foo(Args... args, T x) { 
    ^

Problemem jest to, że opakowanie parametr Args... występuje przed do T.

Args... jest "chciwy", więc nie ma parametrów do kompilacji, aby wywnioskować T, a więc nie powiedzie się.

Cytowanie standardowego (kopalni nacisk)

[temp.param]/11

Opakowanie parametr wzór matrycy funkcji nie następuje innego parametru szablonu , chyba że ten parametr szablonu może być wydedukowany z listy parametrów typu szablonu funkcji lub ma domyślny argument . [Przykład:

... 
// U can be neither deduced from the parameter-type-list nor specified 
template<class... T, class... U> void f() { } // error 
template<class... T, class U> void g() { } // error 

- przykład end]

+0

To jest po prostu "kompilacja nie implementująca standardu poprawnie" sytuacji? – matheuscscp

+0

@matheuscscp, Nie, standard też na to nie zezwala. – chris

+0

Dziękuję wam! – matheuscscp

3

(odpowiedzi na podstawie @JohannesSchaub-litb's comments)

Zgodnie z normą, parametr szablon paczka jest wywnioskować, czy jest ona wykorzystywana w opakowaniu parametrów funkcji nie na końcu listy parametrów.

$14.8.2.1/1 Deducing template arguments from a function call [temp.deduct.call]: nie

Po pojawieniu się pakietu parametr funkcji w nie wynikają kontekście ([temp.deduct.type]), rodzaju wspomnianego opakowania Parametr ten jest określany.[Przykład:

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

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

- przykład end]

I o braku wyprowadzona kontekście $14.8.2.5/5 Deducing template arguments from a type [temp.deduct.type]:

Opakowanie parametrów funkcji, które nie występują na końcu parameter- lista zgłoszeń.

więc bezpośrednią przyczyną foo(1,1,1); nieudanej to, że parametr szablonu Args nie jest wywnioskować, co jest konieczne, aby funkcja powołując ważny.

Aby wyjaśnić komunikat o błędzie, pakiet parametrów nie wywnioskowany zostanie wywnioskowany do pustej sekwencji argumentów szablonu [1], oznacza to, że zostanie on pominięty. Wtedy nie powiodło się foo(1,1,1);, ponieważ liczba argumentów nie jest zgodna, na co skarżył się kompilator.

Tak jak w przykładzie z pokazanego standardu, można jawnie określić argument szablonu, aby uniknąć potrącenia typu, nawet jeśli nie spełnia on pierwotnej intencji kodu. Takich jak:

template <typename T, typename... Args> 
void foo(Args... args, T x) { 
} 

int main() { 
    // inside main() 
    foo<int, int, int>(1, 1, 1); 
} 

Here - kilka dodatkowych informacji.


[1] Nie mogę znaleźć bezpośredniego wyrażenia na ten temat w standardzie. Najbliżej jest this, "Opóźniony pakiet parametrów szablonu ([temp.variadic]), który inaczej nie został wywnioskowany, zostanie wyprowadzony do pustej sekwencji argumentów szablonu."

Powiązane problemy