Duplicate Symbols Error - Am I doing my includes right?

1.3k views Asked by At

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?

inclusion structure

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
2

There are 2 answers

2
Sam Varshavchik On BEST ANSWER

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.

3
phoebe.mu On
  1. make sure you use #ifdef XXX_H_ in a header
  2. you cannot define a variable in header, only can you declare.