Make operator overload by separating statement (.h) from definition (.cpp)

0

I'm trying to separate the class implementation definition into separate files, however I'm getting undefined reference in ; operator.

What I've tried:

Change the order of objects at link time:
only generates an undefined reference in the class constructor

Move the definition to the same file where the main is: compiles, links and runs smoothly

Makefile performs the following:

g++ -c -I. -std=gnu++0x -Wfatal-errors log.cpp
g++ -c -I. -std=gnu++0x -Wfatal-errors main.cpp
g++ -o main.app log.o main.o

log.h file:

class _LOG
{
public:
    _LOG(int level,std::string file,int line);

    template<typename T> 
    _LOG& operator<<(T t);

    static int last_log;
    static std::ostream * out;
};

log.cpp file:

_LOG::_LOG(int level,std::string file,int line){
    // implementacao do construtor omitido
}

template<typename T>
_LOG& _LOG::operator<<(T t)
{
    *out << t;
    return *this;
}

The final result I get when I put the implementation into main is that I can use it as follows after using a macro:

#define LOG_INFO _LOG(LOG_I,__FILE__,__LINE__)
LOG_INFO  << "Bla bla bla" << " outro bla";

ps: this code is for studies only (hobby)

    
asked by anonymous 29.09.2016 / 18:41

1 answer

0

You get this linkage error because your function is a template function.

Template functions must have their implementation declared in the same compilation unit where they are used, it is a limitation of the language. So it works from you put the implementation in main.

What you do, in general, is to implement these functions directly in the .h file where they are declared, either inside or outside a class. In this way all compilation units (cpp files) that include your class will have access to the template implementation.

This is required by the way templates are implemented. Each time a template function is called with different types it is as if the compiler creates for you a new version of that function with those types. These versions of the function will be linked in the final executable. In his case, in the compilation unit that only included the declaration of the template function, but without the implementation of it, the compiler never had the opportunity to instantiate the template, because it had only the declaration.

This can be problematic at times, especially for exposing implementation details in a header file. In some cases this can be solved by splitting the template function into parts, causing it to call non-template functions with the code you do not want to expose. It's also one of the big culprits for compile time in C ++ to be so high.

It is possible for multiple copies of the function implementation to be generated for the same types in different build units, but the linker can then resolve this and only one (for each type set) is added to the final executable.

    
29.09.2016 / 18:50