c++buildsymbols

Duplicate symbols with header only implementation


I have a C++ class that is declared and implemented in a header file. I chose this because one cannot easily move between Debug and Release builds due to _GLIBCXX_DEBUG and precompiled libraries. For example, if I define _GLIBCXX_DEBUG, Boost will crash due to ABI changes in the source files.

The header only implementation has created a problem with duplicate symbols. For example, in the class below operator== and non-member swap will produce multiply defined symbols.

// Foo.hpp
namespace Bar
{
  template
  class Foo
  {
    ...
  };

  bool operator==(const Foo& a, const Foo& b) {
    ..
  }
}

namespace std
{
  template <>
  void swap(Bar::Foo& a, Bar::Foo& b)
  {
    a.swap(b);
  }
}

When declaration and implementation were split, the files (Foo.hpp and Foo.cpp) compiled and linked OK.

What is the trick to get this to compile and link properly?


Solution

  • inline bool operator==(const Foo& a, const Foo& b) {
        ..
      }
    

    Member functions are implicit inline provided they are defined inside their class. The same stuff is true for them true: If they can be put into the header without hassle, you can indeed do so.

    Because the code of the function is put into the header and visible, the compiler is able to inline calls to them, that is, putting code of the function directly at the call site (not so much because you put inline before it, but more because the compiler decides that way, though. Putting inline only is a hint to the compiler regarding that). That can result in a performance improvement, because the compiler now sees where arguments match variables local to the function, and where argument doesn't alias each other - and last but not least, function frame allocation isn't needed anymore.