Przyjmijmy następujący kod:Nieoczekiwany przeciążenie wywoływana, gdy funkcja jest wywoływana z zmiennej liczbie argumentów szablonu konkretyzacji
#include <iostream>
template<typename... T>
void foo(const T &...);
template<unsigned N>
void foo(const char (&)[N])
{
std::cout << "char(&)[N]" << std::endl;
}
void foo(const char *)
{
std::cout << "const char *" << std::endl;
}
template<typename T>
void foo(const T &)
{
std::cout << "Single" << std::endl;
}
template<typename First, typename... T>
void foo(const First & first, const T &... rest)
{
std::cout << "Generic + " << sizeof...(T) << std::endl;
foo(first);
foo(rest...);
}
int main()
{
const char * c = "asdf";
char a[] = {'a', 'b', 'c', 'd'};
foo('f', c, a, 1);
foo(a);
}
Generic + 3
Single // fine; 'f' is `char` -> generic
Generic + 2
const char * // fine; c is `const char *`
Generic + 1
const char * // (!) not fine
Single
char(&)[N] // fine; a is char[4]
Ostatni telefon - foo(a)
, gdzie a
jest char[4]
- zwraca wersję jestem oczekiwanie - template<unsigned N> void foo(const char (&)[N])
. Ale dlaczego nie instancję szablonu variadic z foo
dzwoni foo(const char (&)[N]
, ale zamiast tego wywołuje foo(const char *)
? Jeśli nie było przeciążenia tablicy znaków, należy się tego spodziewać - ale dlaczego tak się dzieje? Czy nie powinien poprawnie przechwytywać typu tablicowego const First &
?
Jaki byłby najprostszy sposób, aby ogólna wersja variadic działała poprawnie z tablicami przekazanymi do niej?
Jak Matthieu M. zauważył w komentarzach, problem prawdopodobnie nie jest spowodowany przez szablony o zmiennej liczbie argumentów, ale indirection:
#include <iostream>
template <unsigned N>
void foo(const char (&)[N])
{
std::cout << "char(&)[N]" << std::endl;
}
void foo(const char *)
{
std::cout << "const char *" << std::endl;
}
template <typename T>
void goo(T const& t) {
foo(t);
}
int main()
{
char a[] = {'a', 'b', 'c', 'd'};
foo(a);
goo(a);
}
char(&)[N] const char *
Powiedział też, że może to być kompilator bug - chociaż kod daje dokładnie takie same wyniki zarówno w devie Clang 3.2, G ++ 4.6 i 4.7.
R. Martinho Fernandes zauważyć, że zmiana a
„s typu w poprzednim fragmencie do const char a[]
sprawia kodu dostarcza const char *
dwukrotnie.
Dlaczego '// dobrze; "afas" to const char *? Nie jest! http://ideone.com/4KewDe –
@ R.MartinhoFernandes, poprawiono. – Griwes
Udało mi się jeszcze bardziej zmniejszyć problem [tutaj] (http://liveworkspace.org/code/72b3963b4f0c2d00592b4ce00f08fc82). Najwyraźniej przyczyną jest ten problem, a variadic nie ma z tym nic wspólnego. Wciąż nie znalazłem prawdopodobnego wyjaśnienia ... To z pewnością wygląda na błąd kompilatora. –