Почему аргумент по умолчанию не может быть указан для явной специализации шаблона? - PullRequest
24 голосов
/ 29 октября 2010

Приведенный ниже код не может пройти компиляцию. Какова причина этой ошибки компилятора?

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

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

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

Ответы [ 3 ]

25 голосов
/ 29 октября 2010

Я думаю, что обоснование этой ошибки связано с тем, что аргументы по умолчанию в шаблоне функции также применимы к его специализации, и вам не разрешено определять аргумент по умолчанию более одного раза в C ++.

Обратите внимание на следующее:

#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>();
}
15 голосов
/ 29 октября 2010

C ++ 98 §12.7 / 21 «Аргументы функции по умолчанию не должны указываться в ... явной специализации шаблона функции».

Обоснование Я думаю, что это всегда связано с вызовомразрешается против основного шаблона.Вызов, в котором отсутствует аргумент, требуемый основным шаблоном, не может быть решен без изменения правил поиска.

2 голосов
/ 29 октября 2010

Конкретный используемый экземпляр шаблона определяется типом аргумента функции.Таким образом, в этом случае явная специализация выбирается с помощью аргумента char;только в этот момент вступает в действие аргумент по умолчанию, где он теперь избыточен.

Имеет смысл предоставлять аргументы по умолчанию только в самом объявлении шаблона.Недостатком является то, что вы должны сами указать соответствующую специализацию, а именно f<char>(), что устраняет некоторые преимущества при использовании аргумента по умолчанию.

Чтобы добиться поведения, которое, я полагаю, вамхотите, используйте следующее:

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

template<> void f<char>(char c) {}

void f() { f('a'); }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...