I am working on a project with several modules and I'm getting a lot of duplicate symbols errors. I've tried to create a stripped-down version of my project to diagnose the error.
I have the code and dependency structure below. Every .hpp and .tpp file has header guards, but I'm getting duplicate symbols errors from MyClass.cpp and main.cpp.
Is my inclusion structure ok, and any ideas how I can go about fixing the error?
CMakeLists.txt
cmake_minimum_required(VERSION 3.18.0)
project("duplicate symbols" LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
add_executable(main main.cpp MyClass.cpp)
Base.hpp
#pragma once
template <typename T>
struct Base { void hello_base() const; };
#include "Base.tpp"
#include "BaseSpec.hpp"
Base.tpp
#pragma once
#include <iostream>
template <typename T>
void Base<T>::hello_base() const { std::cout << "hello base" << std::endl; }
BaseSpec.hpp
#pragma once
template <>
struct Base<int> { void hello_base() const; };
#include "BaseSpec.tpp"
BaseSpec.tpp
#pragma once
#include <iostream>
void Base<int>::hello_base() const
{
std::cout << "Hello base int" << std::endl;
}
MyClass.hpp
#pragma once
#include "Base.hpp"
struct MyClass
{
void hello_myclass() const;
};
MyClass.cpp
#include "MyClass.hpp"
void MyClass::hello_myclass() const
{
std::cout << "hello myclass" << std::endl;
}
main.cpp
#include "MyClass.hpp"
int main() {}
The error message is:
duplicate symbol 'Base<int>::hello_base() const' in:
CMakeFiles/main.dir/main.cpp.o
CMakeFiles/main.dir/myclass.cpp.o
Both of the .cpp
files include, indirectly, BaseSpec.tpp
which defines:
void Base<int>::hello_base() const
That's your violation of the One Definition Rule, that results in a duplicate symbol link failure.
Removing BaseSpec.tpp
, and replacing it with a .cpp
file, with the same contents, should make the linkage error go away.