lundi 30 janvier 2017

Operator overloading on template: unresolved external when used in another project

In project X, I define the following:

// x.h - library X
template<typename T>
struct square
{
    DLL_API T operator()( T const& left, T const& right ) const;
};

// x.cpp - library X
template<typename T>
T square<T>::operator()( T const& left, T const& right ) const
{
    return ( left + right*right );
}

// macro
#ifdef DLL_EXPORTS      // DLL export macros
#define DLL_API __declspec(dllexport)
#define DLL_TEMPLATE
#else
#define DLL_API __declspec( dllimport )
#define DLL_TEMPLATE extern
#endif

Then I use it in another project, which links to the library with above definitions:

// y.cpp - library Y
std::accumulate( std::begin(x), std::end(x), 0.0, square<double>() );

Resulting in the unresolved external:

Error 2 error LNK2019: unresolved external symbol "__declspec(dllimport) public: double __cdecl square::operator()(double const &,double const &)" (__imp_??R?$square@N@QEAANAEBN0@Z) referenced in function "double __cdecl std::_Accumulate >(double *,double *,double,struct square)" (??$_Accumulate@PEANNU?$absolute@N@std@@YANPEAN0NU?$square@N@)

When I use the square<double>() within x.cpp, template function is being instantiated, and project Y builds fine and everything works OK.

I tried defining the operator inline and also forward declare it, but the linker error still remains.

What's the best way to resolve the error, assuming the operator is not being used in x.cpp file and, ideally, keeping the implementation in cpp file?

Aucun commentaire:

Enregistrer un commentaire