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