Cheok Yan Cheng
Cheok Yan Cheng

Reputation: 42828

Global function definition in header file - how to avoid duplicated symbol linkage error

I have the following code in a header only file.

#pragma once

class error_code {
public:
    unsigned __int64 hi;
    unsigned __int64 lo;    
};

std::ostream& operator<< (std::ostream& o, const error_code& e) {
    return o << "[" << e.hi << "," << e.lo << "]";
}

I get linkage error, when there are 2 cpp in the project include this header file.

error LNK2005: "class error_code __cdecl operator|(class error_code const &,class ViTrox::error_code const &)" (??U@@YA?AVerror_code@0@ABV10@0@Z) already defined in xxx.obj

I know I can resolve this problem, if I move the definition of operator<< to a cpp file, or to a DLL file.

However, I just would like to have them in a SINGLE header file. Is there any technique to achieve so? Or must I separate the definition to another file?

Upvotes: 10

Views: 6903

Answers (4)

Timo
Timo

Reputation: 5176

You can make the function static. It specifies internal linkage, so the linker won't care if the function is already defined in other translation units.

Or, as already mentioned, you can make it inline. It still has external linkage, but the standard allows external inline functions to have a definition in multiple translation units.

Upvotes: 3

wilhelmtell
wilhelmtell

Reputation: 58715

Either make the function inline:

inline std::ostream& operator<< (std::ostream& o, const error_code& e) {
    return o << "[" << e.hi << "," << e.lo << "]";
}

or make it a template function:

template<class Ch, class Tr>
std::basic_ostream<Ch,Tr>& operator<< (std::basic_ostream<Ch,Tr>& o,
                                       const error_code& e) {
    return o << "[" << e.hi << "," << e.lo << "]";
}

Upvotes: 7

Sarfaraz Nawaz
Sarfaraz Nawaz

Reputation: 361762

Define this function in .cpp file (not in .h file)

//yoursource.cpp
#include "yourheader.h"

std::ostream& operator<< (std::ostream& o, const error_code& e) {
    return o << "[" << e.hi << "," << e.lo << "]";
}

Upvotes: 0

Logan Capaldo
Logan Capaldo

Reputation: 40346

Use the inline keyword.

inline std::ostream& operator<< (std::ostream& o, const error_code& e) {
    return o << "[" << e.hi << "," << e.lo << "]";
}

Upvotes: 18

Related Questions