Подтвердить что ты не робот

Почему аргумент по умолчанию нельзя указать для конкретной специализированной специализации?

Приведенный ниже код не смог передать компиляцию, что учитывает эту ошибку компилятора?

template<class T> void f(T t) {};

template<> void f<char>(char c = 'a') {}

Сообщение об ошибке: аргументы по умолчанию не допускаются при явной специализации шаблона функции

4b9b3361

Ответ 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'); }