0

I am struggling with my library design. I want to create a library to be used in my future projects (header only for now...)

I have this file structure:

C:\Libs\MYLIB
   - Tools.hpp
   - Tools.cpp

The code looks like this:

Tools.hpp

#pragma once
    class Tools
    {
        public:
            Tools();
            ~Tools();
    };

Tools.cpp

#include "Tools.hpp"

inline Tools::Tools()
{
}

inline Tools::~Tools()
{
}

And then there is is another project, in a totally different folder including this file:

#include <MYLIB/Tools.hpp>

int main()
{
    Tools t;

    return 0;
}

But I always get this error:

undefined reference to Tools::Tools()' undefined reference toTools::~Tools()'

When I create a .hpp file only with inline implementation inside my class, like this:

#pragma once
class Tools
{
    public:
        Tools(){};
        ~Tools(){};

        void DoSomething(){};
};

it works (so my include paths are correct), but I don't want to bloat my .hpp file (I want to use doxygen later on, and keep my declaration from implementation).

I know using inline can be ignored by the compiler, I guess this is what happens here?! So what is the best way to create a private header only library

My specs: Win 10 with CodeLite MinGW (g++)

Another question: Should this line in Tools.cpp

#include "Tools.hpp"

better be like this:

#include <MYLIB/Tools.hpp>
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
DoubleVoid
  • 777
  • 1
  • 16
  • 46
  • 5
    Header only libraries have all of there code in the header files. Since you are using .cpp files for the implementation this is not a header only library. – NathanOliver Jan 15 '16 at 19:42
  • Mhh okay ... so there is no way around to achieve this, besides a dynamic library project?! – DoubleVoid Jan 15 '16 at 19:43
  • 9
    You can move the inline functions to the header file. That's what makes it "header only". :-) But it only works if they are `inline`. – Bo Persson Jan 15 '16 at 19:44
  • Okay, makes sense :D But commenting the code with doxygen and stuff, will bloat the hpp file someday :/ Is there any way to separate declaration and implementation without much trouble?! – DoubleVoid Jan 15 '16 at 19:45
  • Not if you want it to be header only. – NathanOliver Jan 15 '16 at 19:45
  • mhh okay, so I guess I have to figure out how to create a static/dynamic library I guess... – DoubleVoid Jan 15 '16 at 19:46
  • 2
    The inline functions can be below the class, leaving the class declaration clean for documenation at the top. – pticawr Jan 15 '16 at 19:46
  • 1
    @DoubleVoid You can still provide another implementation file (best not with the `.cpp` extension but something like `.inl`), and include that one in your _header only_. – πάντα ῥεῖ Jan 15 '16 at 19:48
  • @pticawr ... okaay, wow ... that's a good idea and it works :D – DoubleVoid Jan 15 '16 at 19:48
  • @πάντα ῥεῖ: That's a good idea too! Thanks :) – DoubleVoid Jan 15 '16 at 19:48
  • @DoubleVoid Sure, it's a pretty common technique where template classes force you to provide header only code: [Why can templates only be implemented in the header file?](http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file). – πάντα ῥεῖ Jan 15 '16 at 19:51
  • Including the inline functions below the declaration will only work once. That is, when your project grows and two different source files include your Tools header, you will then have two copies of the implementation, and the build will fail to link. – donjuedo Jan 15 '16 at 19:51
  • 2
    No, that's how inline works, @donjuedo. – Ulrich Eckhardt Jan 15 '16 at 19:52
  • @donjuedo ... the use of the inline keywords allows you to avoid this problem. – pticawr Jan 15 '16 at 19:53
  • @pticawr, I would test to be sure. My understanding of `inline` is that each call to an inline function gets a copy of the coded implementation. But writing two copies of the coded implementation is not the same thing. – donjuedo Jan 15 '16 at 19:54
  • I just created a new class "Something.hpp", which includes my Tools.hpp (with inline implementation). Main includes Something.hpp and Tools.hpp .... no compile error – DoubleVoid Jan 15 '16 at 20:00
  • Without the inline keyword it fails with "Tools.hpp:12: first defined here" ... – DoubleVoid Jan 15 '16 at 20:01
  • @DoubleVoid That's good. Want to try adding a Something2 class and see if it still works? – donjuedo Jan 15 '16 at 20:01
  • 2
    This may explain the behaviour of the inline keyword ... [link](http://stackoverflow.com/questions/5057021/why-are-c-inline-functions-in-the-header) – pticawr Jan 15 '16 at 20:01
  • 1
    @pticawr The answer at the link is a good explanation of inline. I learned something today. Can I go home now? ;-) – donjuedo Jan 15 '16 at 20:04
  • 1
    @donjuedo: Added a Something2 class => No problem ... main.cpp includes Tools.hpp, Something.hpp and Something2.hpp ... both Something classes include Tools.hpp ... no problem at all :) – DoubleVoid Jan 15 '16 at 20:05
  • 1
    @pticawr _"Can I go home now? ;-) "_ No, not as long you're staying in class and participate or still leave comments ;-) ... – πάντα ῥεῖ Jan 15 '16 at 20:16

1 Answers1

0

You can use an ad-hoc static lib, which is convenient for libraries that are small and/or change often and thus don't provide much benefit compared to the overhead of versioning/compiling/distributing separately. The idea is that you separate headers/sources as normal, but you just #include the .cpp file in one translation unit. Be aware that this technique has its benefits, but also limits!

Ulrich Eckhardt
  • 16,572
  • 3
  • 28
  • 55
  • This could work, but this way I may have some troubles with compile times and referencing issues, if my project grows bigger, right? – DoubleVoid Jan 15 '16 at 19:54
  • Compile times: Whenever the lib changes, you have to recompile it. Whenever the translation unit including the lib changes, you have to recompile it, too. You can adjust to that by only including it in a seldom-changed sourcefile. Referencing issues: You obviously must not include the lib more than once or you have to give the contents internal linkage (`static`, anonymous namespace). – Ulrich Eckhardt Jan 15 '16 at 20:05