Шаблон функции-члена шаблона класса не может найти определение, несмотря на явное наличие экземпляра. Не связывает

Редактировать: это не дубликат связанного вопроса, так как я использую явное создание экземпляров, и только определенный тип функций-членов не связывается (другие делают).

Следующий код компилируется, но не связывается, и я не понимаю, почему. Это явно создание Vector класс для ограничения количества возможных аргументов для T и поэтому скрывает определение Vector<T> в файле.cpp.

// fwd_decl.hpp
#pragma once
template<typename T>
struct Vector; // Forward declare Vector to be used in other headers

// Vector.hpp
#pragma once
#include "fwd_decl.hpp"

template<typename T>
struct Vector
{
    template<typename U> // To allow for other types than T to be used
    Vector operator+(const Vector<U> & other) const;
    T x;
    T y;

    // more stuff..
};

// Vector.cpp
#include "Vector.hpp"
template<typename T>
template<typename U>
Vector<T> Vector<T>::operator+(const Vector<U> & other) const
{
    return { static_cast<T>(x + other.x), static_cast<T>(y + other.y) };
}
template struct Vector<int>; // Explicitly instantiate Vector<T> with int

// main.cpp
#include "Vector.hpp"
int main()
{
    Vector<int> b = Vector<int>{ 2, 3 } + Vector<int>{ 4, 5 };
}

Я получаю ошибку:

1>main.obj : error LNK2001: unresolved external symbol "public: struct Vector<int> __thiscall Vector<int>::operator+<int>(struct Vector<int> const &)const " (??$?HH@?$Vector@H@@QBE?AU0@ABU0@@Z)

Я компилирую с VC++ 17 в VS 15.9.4.

Обратите внимание, что звонки членам Vector<int> которые не являются шаблонами функций, обычно связываются.

1 ответ

Решение

Вы должны использовать явный экземпляр метода template<typename T> template<typename U> Vector<T> Vector<T>::operator+(const Vector<U> & other) const (для всех возможных пар T а также U) в дополнение к явной реализации Vector<T> учебный класс:

template Vector<int> Vector<int>::operator+(const Vector<short> & other) const;

Также вы можете просто переместить определение Vector<T>::operator+ метод к файлу заголовка.

В C++11 extern template Директива была введена. Вы можете использовать его в заголовочном файле для Vector<T> класс (как StoryTeller предложил в комментариях):

extern template struct Vector<int>;

... чтобы предотвратить создание экземпляра компилятором Vector<T> класс в каждой единице перевода используются его специализации. Конечно то же самое extern template Директивы также могут быть использованы для всех Vector<T>::operator+ специализации явно созданы в .cpp файл.

Другие вопросы по тегам