специализация функции-члена шаблонного класса

#c #template-specialization

#c #шаблон-специализация

Вопрос:

там:

Каков результат следующих кодов?

foo.h

 #include <iostream>

template<class _Tp>
struct Foo
{
   void print() { std::cout << "foon"; }
};
  

foo.cxx

 #include "foo.h"

template<>
void Foo<int>::print()
{
   std::cout << "foo<int>n";
}
  

main.cxx

 #include "foo.h"

int main()
{
   Foo<double>().print();
   Foo<int>().print();
   return 0;
 }
  

Результаты разные:

  1. при соблюдении MSVC,

     foo
    foo
      
  2. при компиляции с помощью g ,

     foo
    foo<int>
      

Я хотел бы получить второй результат независимо от компиляторов. Что я должен сделать дополнительно для достижения? Если возможно, не могли бы вы дать мне объяснение базовых стандартов или механизма. Спасибо!

Комментарии:

1. «Результат следующих кодов» является ошибкой компиляции в foo.cxx, поскольку он не содержит допустимого кода C .

2. Я изменил неправильно введенный: void Foo<int>::void print() —> void Foo<int>::print() Не могли бы вы увидеть еще раз, спасибо.

3. Вам просто нужно объявить специализацию в заголовочном файле, чтобы она была видна во всех единицах перевода. Добавьте template<> void Foo<int>::print(); объявление в файл заголовка.

Ответ №1:

Ваша программа имеет неопределенное поведение.

Существует две реализации Foo<int>::print() : встроенное определение, полученное из определения шаблона класса, и нестрочное определение в foo.cxx. Компилятор волен выбирать либо.

Компилятор не требуется для диагностики этого как проблемы. Многие из них (по-видимому, включая g и MSVC) выбирают этот маршрут для определения шаблонов классов и их функций-членов.

Чтобы убедиться, что оба компилятора выбирают реализацию в foo.cxx, объявите функцию в foo.h .

 #include <iostream>

template<class _Tp>
struct Foo
{
   void print() { std::cout << "foon"; }
};

template<> void Foo<int>::print();
  

Комментарии:

1. Спасибо, но есть ошибки ссылки: неразрешенные внешние символы в MSVC, где, как это нормально в g .

2. @DongikShin, моя первая реакция заключается в том, что, возможно, foo.cxx не является частью сборки. Если foo.cxx является частью сборки, я не могу объяснить ошибку компоновщика.

Ответ №2:

Это интересно. Я знаю, что шаблоны интерпретируются во время компиляции, а не во время компоновки. Итак, на мой взгляд, шаблон специализации должен реализовываться в каждом cpp-файле. Какая у вас версия g ?

Ответ №3:

Если foo.h выглядит следующим образом, оба компилятора выдают одинаковые результаты. Но я не знаю почему.

 #include <iostream>


template<class _Tp>
struct Foo
{
   void print();
};

template<class _Tp>
void Foo<_Tp>::print()
{
   std::cout << "foon";
}

template<> void Foo<int>::print();