The following files are part of my C project.
// DpValue.h
class DpValue {
public:
class RElement {
public:
virtual bool operator==(RElement const &Other) const = 0;
};
};
template<class T>
class DpElement : public DpValue::RElement {
public:
virtual bool operator==(DpValue::RElement const &Other) const { ... }
};
// DpValue.cpp
#include <DpValue.h>
template<>
bool DpElement<DpValue>::operator==(DpValue::RElement const &Other) const { ... }
// DpType.cpp
#include <DpValue.h>
...
It compiles fine in Visual Studio 2015. I'm in the process of updating to Visual Studio 2022, and there I get the following linker error:
Code: LNK2005
Description: "public: virtual bool __cdecl DpElement<class DpValue>::operator==(class DpValue::RElement const &)const " (??8?$DpElement@VDpValue@@@@UEBA_NAEBVRElement@DpValue@@@Z) already defined in DpKernel64Dbg.lib(DpValue.obj)
Project: DpDiagram
File: DpKernel64Dbg.lib(DpType.obj)
From my understanding, the method is defined in DpValue.obj, which is correct. But then it is defined again in DpType.obj! What might cause this?
There are of course lots of other code and files in my project, but I've included everything that I think is relevant for the error here.
CodePudding user response:
I think the only thing you are missing is a declaration of the explicit specialization in the header file. It must appear before any point that would implicitly instantiate the class specialization (since the function is virtual
). In the presence of the explicit specialization declaration the implicit instantiation should be suppressed.
So add in DpValue.h
after the definition of DpElement
:
template<>
bool DpElement<DpValue>::operator==(DpValue::RElement const &Other) const;
It must follow the class template definition immediately to avoid accidental implicit instantiations of the class, which could also implicitly instantiate the virtual member function's definition.
See also Explicit specialization of member function template in source file.