0

In the beginning I had:

main.cpp

#include "something.h"
#include "util.h"

int main() {
    sth::something();
    utl::little_thing();
}

somehing.h

#ifndef SOMETHING_H
#define SOMETHING_H

namespace sth {

void something();

}
#endif

somehing.cpp

#include "something.h"

#include <string>
#include <iostream>

namespace sth {

void print_me(std::string txt) {
    std::cout << txt << std::endl;
}

void something() {
    std::cout << "this is something" << std::endl;
    print_me("optional");
}
}

util.h

#ifndef UTIL_H
#define UTIL_H

namespace utl {

void little_thing();

}
#endif

util.cpp

#include "util.h"

#include <iostream>
#include <string>

namespace utl {

void little_thing() {
    std::cout << "this is little thing" << std::endl;
}
}

Then I though it will be better to have print_me(std::string txt) out of sth namespace. And I put it on utl, declaration on .h file and definition on .cpp file.

At that point the lazy side of me said - would it be better to have it all in one file as was beofore. And I tried:

util.h

#ifndef UTIL_H
#define UTIL_H

#include <string>
#include <iostream>

namespace utl {

void little_thing();

void print_me(std::string txt) {
    std::cout << txt << std::endl;
}
}
#endif

something.cpp

#include "something.h"
#include "util.h"

#include <string>
#include <iostream>

namespace sth {

void something() {
    std::cout << "this is something" << std::endl;
    utl::print_me("optional");
}
}

So I got:

c++ -std=gnu++14 -g -Wall -O3  -c -o main.o main.cpp
c++ -std=gnu++14 -g -Wall -O3  -c -o util.o util.cpp
c++ -std=gnu++14 -g -Wall -O3  -c -o something.o something.cpp
c++ main.o util.o something.o  -o main
duplicate symbol __ZN3utl8print_meENSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE in:
    main.o
    util.o
duplicate symbol __ZN3utl8print_meENSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE in:
    main.o
    something.o
ld: 2 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [main] Error 1

Which makes sense to me, since util.h is included in main.cpp and something.cpp there are duplicate symbols, right?

Question, is it possible to be as lazy to have it all in the header? Or no way, have to split decalration and definition? I don't care (in this case) to hide the implementation in the .cpp, I just want to move it out of sth.

KcFnMi
  • 5,516
  • 10
  • 62
  • 136
  • 1
    `static inline` is your friend :) – hellow Aug 03 '18 at 09:12
  • 2
    Possible duplicate of [When should I write the keyword 'inline' for a function/method?](https://stackoverflow.com/questions/1759300/when-should-i-write-the-keyword-inline-for-a-function-method) – Alan Birtles Aug 03 '18 at 09:13
  • 1
    @hellow just `inline` in c++ see https://stackoverflow.com/questions/10876930/should-one-never-use-static-inline-function – Alan Birtles Aug 03 '18 at 09:15
  • print_me() definition inside util.h sound little odd to me. Definitions inside header files can result in duplicate symbol warnings. – seccpur Aug 03 '18 at 09:24
  • Dang it, you're right. I read to much C code, where you (are forced? to) use `static inline` :) – hellow Aug 03 '18 at 09:25

1 Answers1

-1

Maybe move the definition of print_me down to util.cpp and only leave a declaration of it in the util.h file.

Else you get a copy of it in every object file, and then the linker gets confused as they all have the same name (symbol).

Surt
  • 15,501
  • 3
  • 23
  • 39