Я недавно создал этот пример кода, чтобы проиллюстрировать использование функции шаблона C ++ 11.
template <typename Head, typename... Tail> void foo (Head, Tail...);
template <typename... Tail> void foo (int, Tail...);
void foo () {}
template <typename... Tail>
void foo (int x, Tail... tail)
{
std :: cout << "int:" << x;
foo (tail...);
}
template <typename Head, typename... Tail>
void foo (Head x, Tail... tail)
{
std :: cout << " ?:" << x;
foo (tail...);
}
foo (int (123), float (123)); // Prints "int:123 ?:123.0"
Если первые две строки, которые объявляют вперед foo
, опущены, вместо этого выводится int:123int:123
. Это удивило некоего опытного и знающего программиста на С ++.
Он был убежден, что предварительные декларации не должны быть необходимыми, поскольку тело не будет создано до второй фазы двухфазного поиска. Он думает, что компилятор (gcc 4.6) содержит ошибку.
Я считаю, что компилятор прав, потому что две foo
являются различными функциями базового шаблона , и выбор базового шаблона должен быть заблокирован на первом этапе, иначе вы можете нарушить одно- определение правила путем создания экземпляра foo
до того, как будут определены все его версии, а затем еще раз (рассмотрим, как компоновщик предполагает, что определения избыточных шаблонных функций идентичны, взаимозаменяемы и отбрасываются).
Итак, кто прав?
Приведенный выше GOTW хорошо объясняет, как и почему шаблоны функций не частично специализируются, но существование функций вариабельных шаблонов, кажется, добавляет путаницу - интуиция, что foo<int,Tail...>
должна быть частичной специализацией foo<Head,Tail...>
сильнее, чем эта интуиция для невариантных функций, по крайней мере, для меня.