Ответ 1
Это старый синтаксис для явной специализации. Но я удивлен, что вы используете компилятор, который все еще принимает его (g++ остановился около 4.0). Чтобы соответствовать требованиям, вам необходимо префикс специализации template <>
.
Я просматриваю код кода коллег и нашел это:
Заголовочный файл:
template<class T>
class MyClass
{
void Execute();
}
Файл Cpp:
void MyClass<int>::Execute()
{
// something
}
void MyClass<string>::Execute()
{
// something else
}
Код специализируется на функции, но без использования синтаксиса специализации шаблона. Я думаю, он работает нормально, но действительно ли это?
Это старый синтаксис для явной специализации. Но я удивлен, что вы используете компилятор, который все еще принимает его (g++ остановился около 4.0). Чтобы соответствовать требованиям, вам необходимо префикс специализации template <>
.
Да, он отлично подходит для специализации методов класса шаблона.
Но ваш синтаксис ошибочен, это должно быть: (извините, не видел, что вы сначала не указали template<>
. Предполагалось, что он был там и думал, что вы спрашиваете о специализации функции-члена.)
template<>
void MyClass<int>::Execute()
{
// something
}
template<>
void MyClass<string>::Execute()
{
// something else
}
Вам нужно объявить их только в заголовке. Если вы также реализуете их в заголовке, вам нужно пометить их inline
, чтобы предотвратить множественное определение.
При вызове метода вызывается версия, которая больше всего подходит для вызова. В противном случае - по умолчанию.
В вашем случае, если вы специализируетесь на шаблоне с классом X
и пытаетесь вызвать Execute
, вы получите ошибку компоновщика, потому что вы не предоставили реализацию по умолчанию или специализацию для Execute
для X
.
Вопрос уже ответил, но позвольте мне обратить внимание на тонкие различия между тремя случаями.
Заголовок:
template <typename T> struct Foo
{
void f() { /* stuff */ }
};
template <> void Foo<int>::f();
Источник:
template <> void Foo<int>::f() { /* ... */ }
В этом случае Foo<T>::f()
можно вызвать для любого T
. Определение для общего случая автогенерируется из шаблона; определение Foo<int>::f()
- это то, что предусмотрено. Наличие специализации в заголовке предупреждает каждую потребляющую единицу перевода, что нужно искать отдельный символ, а не использовать шаблон.
Заголовок:
template <typename T> struct Foo
{
void f();
};
Источник:
template <> void Foo<int>::f() { /* ... */ }
В этом случае можно использовать только Foo<int>::f()
; все остальное вызовет ошибку компоновщика. Поскольку в шаблоне нет определения функции, каждое использование шаблона приведет к выходу нового символа, и только единица для Foo<int>::f()
предоставляется показанной единицей перевода.
Заголовок:
template <typename T> struct Foo
{
void f() { /* stuff */ }
};
Источник:
template <> void Foo<int>::f() { /* ... */ }
Это нарушение правила одного определения, поскольку теперь существует несколько определений Foo<int>::f()
.
Чтобы ответить на вопрос в названии, как изначально написано: абсолютно. Это также справедливо для того, чтобы иметь полностью не связанный набор членов в специализации.
Чтобы ответить на вопрос в коде: выглядит как ошибка компилятора. Требуется template <>
.