C ++ основной шаблон вопроса - PullRequest
4 голосов
/ 15 июля 2010

Я немного запутался со специализацией шаблонов.

У меня есть классы Vector2, Vector3, в которых есть operator+= (которые определены следующим образом).

   Vector2& operator+=(const Vector2& v) {

      x() += v.x(), y() += v.y();

      return *this;
   }

Теперь я хочу добавить общее поведение сложения и сказать что-то вроде:

template <typename V> const V operator+(const V& v1, const V& v2) {
   return V(v1) += v2;
}

Это прекрасно компилируется и работает как для Vector2, так и для Vector3. Но, скажем, я хочу иметь более эффективную операцию "+" для моей Vector2 и хочу, чтобы она действовала следующим образом ( с использованием шаблона специализации) :

template<> const Vector2 operator+(const Vector2& v1, const Vector2& v2) {
   return Vector2(v1.x() + v2.x(), v1.y() + v2.y());
}

Это выглядит хорошо для меня, но, к сожалению, размещение этих двух частей кода сразу после друг друга приводит к сбою компиляции

(компоновщик сообщает об ошибке LNK2005: "Vector2 const operator+<Vector2>(Vector2 const &,Vector2 const &)" (??$?HVVector2@core@lf@@@core@lf@@YA?BVVector2@01@ABV201@0@Z) already defined in ...)

В чем моя ошибка и где я ошибся?

Спасибо.

Ответы [ 3 ]

7 голосов
/ 15 июля 2010

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

Обратите внимание, что вам на самом деле не нужен шаблонспециализация здесь;простая перегрузка сделает то же самое.

3 голосов
/ 15 июля 2010

Я не совсем уверен, что вы хотите пойти по этому пути.operator+, который вы определили как шаблон, будет соответствовать любому и всем типам, возможно создавая конфликты.Почему бы вам не предоставить простой не шаблонный operator+ для каждого из ваших векторов?

Есть и другие проблемы со стилем:

Vector2& operator+=(const Vector2& v) {
   x() += v.x(); // you don't need operator, here and it might
                 // be confusing if you don't have operator, priorities clear
   y() += v.y();
   return *this;
}

Также:

// This should not be a template!!!
template <typename V> const V operator+(V v1, const V& v2) {
   return v1 += v2;
}

В некоторых случаях компилятор может исключить копию, если operator+ определено, как указано выше (если первый аргумент является временным), в то время как он не может исключить копию с вашим определением.

Проблема сoperator+ Как вы определили, компилятор попытается использовать его с любым типом:

struct non_sumable {};
int main() {
   non_sumable a,b;
   a + b;           // matches the template, tries to instantiate
                    // compiler error says that non_sumable does not 
                    // have operator+=, which might be confusing
}
3 голосов
/ 15 июля 2010

положить это

template<> const Vector2 operator+(const Vector2& v1, const Vector2& v2);

в вашем заголовке файла и

template<> const Vector2 operator+(const Vector2& v1, const Vector2& v2) {
   return Vector2(v1.x() + v2.x(), v1.y() + v2.y());
}

в файле .cpp .

...