Почему аргумент по умолчанию нельзя указать для конкретной специализированной специализации?
Приведенный ниже код не смог передать компиляцию, что учитывает эту ошибку компилятора?
template<class T> void f(T t) {};
template<> void f<char>(char c = 'a') {}
Сообщение об ошибке: аргументы по умолчанию не допускаются при явной специализации шаблона функции
Ответы
Ответ 1
Я думаю, что обоснование этой ошибки связано с тем, что аргументы по умолчанию в шаблоне функции применяются также к его специализации, и вам не разрешено определять аргумент по умолчанию более одного раза в С++.
Рассмотрим следующее:
#include <iostream>
template<class T> void f(T t = 'a') {}
template<> void f<char>(char c)
{
std::cout << c << std::endl;
}
int main(int argc, char **argv)
{
f<char>();
}
Это напечатает a
, что означает, что специализация вызывается с аргументом по умолчанию, определенным в основном шаблоне.
Если для каждой специализации вам нужен другой аргумент по умолчанию, вы можете использовать описанный ниже подход:
#include <iostream>
template<class T>
struct default_arg
{
static T get() { return T(); }
};
template<class T> void f(T t = default_arg<T>::get()) {}
template<>
struct default_arg<char>
{
static char get() { return 'a'; }
};
template<> void f<char>(char c)
{
std::cout << c << std::endl;
}
int main(int argc, char **argv)
{
f<char>();
}
Ответ 2
С++ 98 §12.7/21 "Аргументы функции по умолчанию не должны указываться в... явной специализации шаблона функции".
Что касается обоснования, я думаю, что это связано с тем, что вызов всегда разрешается против основного шаблона. Вызов, который оставляет аргумент, требуемый основным шаблоном, не может быть разрешен с изменением правил поиска.
Ответ 3
Выбор конкретного экземпляра шаблона для использования основан на типе предоставленного параметра. Таким образом, выбор явной специализации производится путем предоставления аргумента char - только в этот момент будет введен аргумент по умолчанию (как вы кодифицировали) (где он является избыточным).
Имеет смысл только предоставить аргументы по умолчанию в самом объявлении шаблона. Недостаток заключается в том, что вам нужно самостоятельно определить соответствующую специализацию (что устраняет некоторые преимущества использования аргумента по умолчанию в первую очередь).
Чтобы выполнить поведение, которое (я считаю) вам нужно, используйте следующее.
template<class T> void f(T t) {}
template<> void f<char>(char c) {}
void f() { f('a'); }