Аргумент шаблона по умолчанию не может быть указан в определении члена шаблона класса вне класса
template<typename Tp, class C = std::vector<Tp>>
struct A {
C s{};
void change(const C&);
};
template<typename Tp, class C = std::vector<Tp>> //Ошибка (активный) E0953
void A<Tp, C>::change(const C& seq) {/*...*/ }
Очевидно, что при определении члена класса, нет смысла указывать аргумент шаблона по умолчанию. Но вопрос в том, почему компилятор это считает ошибкой? (Может плохо смотрел, но кажется не было похожего вопроса).
Ответы (1 шт):
http://eel.is/c++draft/temp.param#12
A default template-argument shall not be specified in the template-parameter-lists of the definition of a member of a class template that appears outside of the member's class.
Почему так сделано?
Например, в следующем примере
template <class T = int>
struct A {
T foo();
};
int main() {
auto a = A{};
}
мы можем использовать дефолтный аргумент и не определять/инстанцировать функцию foo, потому что она не используется. А если бы можно было указывать дефолтные аргументы вне класса
template <class T>
struct A {
T foo();
};
template <class T = int>
T A<T>::foo() {
return T{};
}
int main() {
auto a = A{};
}
то, для того чтобы узнать дефолтный аргумент, необходимо было бы искать определение функции, которая нам не нужна.
Теоретически можно сохранить возможность повторного определения точно такого же аргумента, как у вас в примере
template <class T = int>
struct A {
T foo();
};
template <class T = int>
T A<T>::foo() {
return T{};
}
int main() {
auto a = A{};
}
но это не имеет смысла, потому что нет плюсов (по крайней мере я не вижу, для чего это может использоваться), но есть минус – дополнительная нагрузка на компиляторы для проверки равенства аргументов.