Chris
Chris

Reputation: 31206

C++, Clang: #including associated header with cpp does not compile

I have a main method,

main.cpp:

#include "MyStruct.h"

MyStruct.h:

#ifndef MYPROJ_MYSTRUCT_H
#define MYPROJ_MYSTRUCT_H
#include <vector>
#include <unordered_map>

bool function1(std::vector<std::string> label){ 
    // actual implementation     
}
bool function2(...){ ... }

struct MyStruct{ ... }
#endif

This compiles. However, when I add the cpp file to contain the function definitions,

main.cpp: 

#include "MyStruct.h"

MyStruct.h:

#ifndef MYPROJ_MYSTRUCT_H
#define MYPROJ_MYSTRUCT_H
#include <vector>

bool function1(...){ ... }
bool function2(...){ ... }

struct MyStruct{ ... }
#endif

MyStruct.cpp:

#include "MyStruct.h"

// and that's it

Just by including the header file, I get linker errors as if I am importing the header multiple times;

Here is the CMakeLists:

cmake_minimum_required(VERSION 3.8)
set(CMAKE_CXX_STANDARD 17)

set(SOURCE_FILES main.cpp MyStruct.cpp)
add_executable(my_proj ${SOURCE_FILES})

The errors consist of all duplicate symbol errors. I am not sure how to get this to work, as this is something I do all the time using make and g++ without running into issues; I also don't seem to have this problem when I use CMake with g++ on Cygwin/Windows (this is on MacOSX).


Next, when I transition all functions to the .cpp file, and only declarations are present in the header, I eliminate most of the duplicate symbols except for :

duplicate symbol __Z8get_uvidv in:
    CMakeFiles/main.cpp.o
    CMakeFiles/MyStruct.cpp.o
duplicate symbol _uvid in:
    CMakeFiles/main.cpp.o
    CMakeFiles/MyStruct.cpp.o
ld: 2 duplicate symbols for architecture x86_64

Updated Source


// header: MyStruct.h

#ifndef MYPROJ_MYSTRUCT_H
#define MYPROJ_MYSTRUCT_H

#include <unordered_map>
#include <vector>
#include "AnotherStruct.h"

bool add_item(std::pair<std::string,float> & item);
void insert_item(std::vector<AnotherStruct> & A, std::pair<std::string,float> element);
...

struct MyStruct {
    std::unordered_map<std::string,int> labels;
    std::vector<AnotherStruct> data;

    MyStruct(std::vector<char *> inputs);

    void GetData();
    void SortData(bool (*compare)(AnotherStruct &,AnotherStruct &);
    //...
}
#endif

And the .cpp:

#include "MyStruct.h"

// implement everything declared in .h 
bool add_item(...){
    ...
}
bool insert_item(...){
    ...
} 

MyStruct::MyStruct(...){
    ...
}
void MyStruct::GetData(...){
    ...
}
void MyStruct::SortData(...){
    ...
}

And the main:

#include "MyStruct.h"

The errors:

duplicate symbol __Z8get_uvidv in: 
    main.cpp.o
    MyStruct.cpp.o
duplicate symbol _uvid in:
    main.cpp.o
    MyStruct.cpp.o

I have no idea what __Z8get_uvidv could possibly be, nor _uvid, so I assumed there was something going on with the std imports, or underneath the hood with respect to the compiler.

Bearing in mind that everything compiles when I copy it over to the main method, or leave all definitions in the header file, I am stumped.

Upvotes: 0

Views: 330

Answers (1)

Hatted Rooster
Hatted Rooster

Reputation: 36483

You have included MyStruct.h in both main.cpp and MyStruct.cpp.

Include basically does a copy-paste, leaving you with 2 translation units (main.cpp and MyStruct.cpp) that both contain a definition for function1 and function2 (because you included the header file in both).

Solution:

Only declare the functions in the header file and define them in one translation unit only.

Upvotes: 2

Related Questions