C ++: Evitando el error del enlazador de símbolos duplicados

Estoy recibiendo un error de vinculador:

duplicate symbol __ZN5ENDF64FileILNS_7MF_enumE1EE4readEv in: Read.cpp.o Material.cpp.o 

donde el nombre del símbolo duplicado es:

 $ c++filt __ZN5ENDF64FileILNS_7MF_enumE1EE4readEv ENDF6::File::read() 

Sé que no puedo definir la misma función en varios lugares, eso es lo que puede causar este error de vinculador. (He visto esta pregunta: ld: símbolo duplicado ) No creo que tenga la función read() definida en varios lugares, pero el vinculador ( clang++ ) dice que sí.

¿Dónde estoy duplicando el símbolo de read() ?

Mi estructura de código se ve así:

 //MFs.hpp #ifndef MFS_HPP #define MFS_HPP enum class MF_enum { ... } #endif //File.hpp #ifndef FILE_HPP #define FILE_HPP #include "MFs.hpp" // Definition of class File template class File { ... } // Definition of File::read() function template  void File::read() { std::cout << "Reading into MF=1"<< std::endl; } #endif 

No hay File.cpp porque la clase File tiene una plantilla. Todas las definiciones (y declaraciones) están en File.hpp

 // Material.cpp #include "File.hpp" ... // Material.hpp #ifndef MATERIAL_HPP #define MATERIAL_HPP #include "File.hpp" ... #endif 

Finalmente el código del conductor:

 // Read.cpp #include "Material.hpp" #include "File.hpp" int main (){ ... } 

Las especializaciones (completas) de una plantilla no son plantillas en sí mismas. Si está especializando la función, necesita declararla en el encabezado y proporcionar la implementación en una sola unidad de traducción, o bien hacer la definición en línea:

 // Header [1] template  class File { // ... void open(); }; template <> void File<1>::open(); // just declaration // Single .cpp template <> void File<1>::open() { ... } 

Alternativamente:

 // Header [2] template  class File { // ... void open(); }; template <> inline void File<1>::open() { ... }