Load operator "<<" by separating the declaration(.h) from the definition(.cpp)

Asked

Viewed 155 times

0

I’m trying to separate the definition of the class implementation into separate files, but I’m getting Undefined Ference on the operator <<.

What I’ve already tried:

Change the order of objects at link time:
only generates one more Undefined Ference in the class builder

Move the setting to the same file where the main::
compile, link and run smoothly

Makefile executes 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 file. h:

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 file.cpp:

_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 obtained when I put the implementation in 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 merely for studies (hobby)

  • Is this the whole file? There’s no #include? Curiously without the file main.cpp complicates a little, the error may be in it too.

  • @bigown sorry for omitting these snippets of code, I will try to be clearer on the next question, I did not put it because I thought it was implicit when I said that changing the order of objects generated error in the constructor, so #include should be correct.

  • It is not good practice to use '_' and uppercase initiator identifiers (e.g.: _LOG) as these identifiers are reserved by the default language and library.

  • The funny thing is that everything in capital letters is exactly what I hate about WIN_API, everything looks like a macro, and I ended up doing it here

1 answer

0


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

Template functions should have their implementation declared on the same build unit where they are used, it is a language limitation. That’s why it works for you to put the implementation in the main.

What is usually done is to implement these functions directly in the . h file where they are declared, either inside or outside a class. This way all build drives (cpp files) that include your class will have access to the template implementation.

This is necessary because of the way templates are implemented. Every time you call a template function with different types, it’s as if the compiler created a new version of that function for you 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 statement of the template function, but without the implementation of it, the compiler never had the opportunity to instantiate the template, because he only had the statement.

This can be problematic at times, mainly by exposing implementation details in a header file. In some cases this can be solved by dividing the template function into parts, causing it to call non-template functions with the code that is not to be exposed. It is also one of the big culprits for C++ compilation time being so high.

It is possible that multiple copies of the function implementation are generated for the same types in different compilation units, but Linker can later resolve this and only one (for each set of types) is added to the final executable.

  • @c-e-gesser First thank you. We always see that there is no implementation in the header files, do this will not create several copies of the implementation, one in each file where it is used, generating a bloated binary? Once again I’m surprised by something counterintuitive in the language ^^

  • C++ is a tricky beast sometimes, hehe. I added one more paragraph to the answer, to try to clarify why you have to do this with templates.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.