Ошибка компиляции спецификации шаблона в g ++ - PullRequest
2 голосов
/ 05 августа 2011

У меня есть контейнерный объект, который шаблонизируется. Я пытаюсь сделать специализированный конструктор для float версий. Проблема в том, что когда компилятор пытается скомпилировать второй объект, который использует версию float, я получаю ошибку multiple definition of.

ПРИМЕЧАНИЯ: Весь класс в файле h. Файл упакован с определением (#ifndef, #define и #endif). g ++ версия 3.4.6. Это прекрасно компилируется с другими компиляторами, например Микросхема Intel.

Код похож на следующий:

template <typename T>
class Container {
public:
   Container();
   virtual ~Container() {}
private:
   std::vector<T> data;
   // other members
};

template <> Container<float>::Container() {
   // do something special
}

template <typename T> Container<T>::Container() {
   // do default initialization
}

Есть идеи? Спасибо!

РЕДАКТИРОВАТЬ Скомпилированные объекты также собираются в отдельные общие объекты, не уверенные, имеет ли это какое-либо отношение к этому.

Ответы [ 4 ]

4 голосов
/ 05 августа 2011

Специализации по-прежнему должны соблюдать правило одного определения, как и любой другой не шаблонный метод.Либо пометьте его как встроенное, либо определите тело метода в исходном файле (не в своем заголовке).

1 голос
/ 05 августа 2011

Это сложно.Проблема в том, что ваша специализация - это не шаблон, а фактическое определение функции.И поскольку он находится в заголовке, вы получаете несколько определений, когда вы включаете его дважды.Что-то вроде:

template<> Container<float>::Container();

в заголовке и реализация в одном исходном файле.

1 голос
/ 05 августа 2011
template <> Container<float>::Container() {
   // do something special
}

является определением специализации. Специализация должна быть объявлена ​​ в каждой используемой единице компиляции:

template <> Container<float>::Container();

и определено в только одном CU. Таким образом, у вашего .h должна быть декларация, и вы должны найти адекватное (возможно, новое) .cpp для определения. (Как отмечает Марк Б, включение специализации в строку также является способом, позволяющим поместить определение во все единицы компиляции, где это необходимо).

0 голосов
/ 05 августа 2011

вы можете использовать typeid:

template <typename T> Container<T>::Container() {
   if(typeid(T)==typeid(float)) {
      // do something special
   }
   else {
      // do default initialization
   }
}

недостаток: вы не можете использовать список инициализации для вашего особого случая. РЕДАКТИРОВАТЬ: Когда я писал этот ответ, я все еще предполагал, что ошибка была вызвана компилятором, а не кодом OP (не слишком много изучал). Однако этот подход typeid является абсолютно верным C ++ (см. Ссылку ниже), и это очень хороший обходной путь, если шаблоны действительно не будут работать правильно с вашим конкретным компилятором, и его можно легко заменить решением на основе шаблонов, если однажды вы сможете переключиться на лучший компилятор.

демонстрация: пример @ ideone

...