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

Действительно ли С++ реализует методы класса шаблонов по-разному для разных типов без использования синтаксиса специализации?

Я просматриваю код кода коллег и нашел это:

Заголовочный файл:

template<class T>
class MyClass
{
  void Execute();
}

Файл Cpp:

void MyClass<int>::Execute()
{
  // something
}

void MyClass<string>::Execute()
{
  // something else
}

Код специализируется на функции, но без использования синтаксиса специализации шаблона. Я думаю, он работает нормально, но действительно ли это?

4b9b3361

Ответ 1

Это старый синтаксис для явной специализации. Но я удивлен, что вы используете компилятор, который все еще принимает его (g++ остановился около 4.0). Чтобы соответствовать требованиям, вам необходимо префикс специализации template <>.

Ответ 2

Да, он отлично подходит для специализации методов класса шаблона.

Но ваш синтаксис ошибочен, это должно быть: (извините, не видел, что вы сначала не указали template<>. Предполагалось, что он был там и думал, что вы спрашиваете о специализации функции-члена.)

template<>
void MyClass<int>::Execute()
{
  // something
}
template<>
void MyClass<string>::Execute()
{
  // something else
}

Вам нужно объявить их только в заголовке. Если вы также реализуете их в заголовке, вам нужно пометить их inline, чтобы предотвратить множественное определение.

При вызове метода вызывается версия, которая больше всего подходит для вызова. В противном случае - по умолчанию.

В вашем случае, если вы специализируетесь на шаблоне с классом X и пытаетесь вызвать Execute, вы получите ошибку компоновщика, потому что вы не предоставили реализацию по умолчанию или специализацию для Execute для X.

Ответ 3

Вопрос уже ответил, но позвольте мне обратить внимание на тонкие различия между тремя случаями.

Случай 1: Специализация

Заголовок:

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() - это то, что предусмотрено. Наличие специализации в заголовке предупреждает каждую потребляющую единицу перевода, что нужно искать отдельный символ, а не использовать шаблон.


Случай 2: Определение

Заголовок:

template <typename T> struct Foo
{
    void f();
};

Источник:

template <> void Foo<int>::f() { /* ... */ }

В этом случае можно использовать только Foo<int>::f(); все остальное вызовет ошибку компоновщика. Поскольку в шаблоне нет определения функции, каждое использование шаблона приведет к выходу нового символа, и только единица для Foo<int>::f() предоставляется показанной единицей перевода.


Случай 3: ошибка с флагом

Заголовок:

template <typename T> struct Foo
{
    void f() { /* stuff */ }
};

Источник:

template <> void Foo<int>::f() { /* ... */ }

Это нарушение правила одного определения, поскольку теперь существует несколько определений Foo<int>::f().

Ответ 4

Чтобы ответить на вопрос в названии, как изначально написано: абсолютно. Это также справедливо для того, чтобы иметь полностью не связанный набор членов в специализации.

Чтобы ответить на вопрос в коде: выглядит как ошибка компилятора. Требуется template <>.