问题
Edit: This is not a duplicate of the linked question since I am using explicit instantiation and only a specific type of member functions do not link (others do).
The following code compiles but doesn't link and I don't understand why.
It is explicitly instantiating the Vector
class to limit the number of possible arguments for T
and therefore hides the definition of Vector<T>
in a .cpp file.
// 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 };
}
The error I'm getting is:
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)
I'm compiling with VC++ 17 in VS 15.9.4.
Note that calls to members of Vector<int>
that are not function templates do link normally.
回答1:
You should use the explicit instantion of the method template<typename T> template<typename U> Vector<T> Vector<T>::operator+(const Vector<U> & other) const
(for all possible pairs of T
and U
) in addition to the explicit instantion of the Vector<T>
class:
template Vector<int> Vector<int>::operator+(const Vector<short> & other) const;
Also you may simply move the definition of the Vector<T>::operator+
method to the header file.
In C++11 the extern template
directive was introduced. You may use it in the header file for Vector<T>
class (as @StoryTeller suggested in the comments):
extern template struct Vector<int>;
...to prevent the compiler from instantiating the Vector<T>
class in every translation unit its specializations are used. Of course the same extern template
directives may also be used for all Vector<T>::operator+
specializations explicitly instantiated in the .cpp
file.
来源:https://stackoverflow.com/questions/54081512/member-function-template-of-class-template-cant-find-definition-despite-explici