3

I already asked a similar question but this one is a bit different

I don't want to write a .cpp file for every simple c++ class.

when I write a class definition and declaration in a single .hpp file, the linker complains about multiple definition of member functions which are not implemented inside the body of the class or defined with inline keyboard.

For example this will work but member functions will become inline :

// log.hpp file
#pragma once
#include<iostream>

class log {
  private:
    static int m_cnt = 0;
  public:
    void log();
};

inline void log::log() {
    std::cout << ++m_cnt << std::endl;
}

So I use templates to get rid of linker complaints and hope that member functions will not become inline(do they ?):

// log.hpp file
#pragma once
#include<iostream>

template<typename T>
class log_t {
  private:
    static int m_cnt = 0;
  public:
    void log();
};

template<typename T>
void log_t<T>::log() {
    std::cout << ++m_cnt << std::endl;
}

// some random type (int)
typedef log_t<int> log;

And then I can simply use log class in multiple .cpp files without linker complaints.

even when i use this method will member functions become inline ?

David G
  • 94,763
  • 41
  • 167
  • 253
amin
  • 3,672
  • 5
  • 33
  • 61
  • Why do use the inline keyword? – Ahmed Matar Mar 19 '14 at 10:01
  • 1
    "I don't want to write a .cpp file for every simple c++ class." Why? Do not use inline if you don't want to and anyway...it doesn't mean compiler won't do it if it it'll think it'll generate better code. – Adriano Repetti Mar 19 '14 at 10:02
  • if id don't when i use .hpp file in mutilpe .cpp files the linker complains about multiple definition of member functions . – amin Mar 19 '14 at 10:03
  • I used to be a C# developer and think that for some simple classes only one file enough . – amin Mar 19 '14 at 10:04
  • 1
    No, you can include definition in multiple files but function body should stay in .cpp (well for inline function it can't). It's pretty opinion based but IMO no. It doesn't matter if it's simple, or not, short or not. .H is for definition and .CPP for implementation. You have to put implementation in .H for templates or for inline functions but for everything else keep this distiction. – Adriano Repetti Mar 19 '14 at 10:05
  • is there a way to write a c++ class only in a header files without making every member funtion inline ? – amin Mar 19 '14 at 10:06
  • 1
    @amin Thinking like C# developer may not help while writing C++ code. – Pranit Kothari Mar 19 '14 at 10:06
  • 1
    Take a look at http://stackoverflow.com/questions/5431362/how-does-templates-work-are-they-always-inlined – manlio Mar 19 '14 at 10:07
  • You are right . but i just want to know if it is possible or not ? – amin Mar 19 '14 at 10:07
  • 1
    @amin: I don't understand what's your problem with `inline` in your example : do you really want to avoid typing 6 additional characters or do you have another concern? `inline` is just a hint so the compiler can inline when you didn't specify `inline` and it can generate a function call when you asked `inline`. – Antoine Mar 19 '14 at 10:11
  • I don't want every member function to become inline . – amin Mar 19 '14 at 10:12
  • 2
    `inline` is not a directive only a hint/annotation. The compiler decides for itself what to inline. Somtimes, the same function can be inlined at some call sites and not inlined at other, just let the compiler do its job. You can compile with `-Os` to do less inlining. – Antoine Mar 19 '14 at 10:16
  • Why are you so concerned with inline functions amin? – Jon Cage Mar 19 '14 at 10:16
  • I just wanted to know that is it :) . i think @Antoine comment helped a lot . – amin Mar 19 '14 at 10:19

2 Answers2

5

In general, having every implementation in header files is a BAD idea, since it can lead to very long compile times for larger projects. Using templates to avoid this is not really a good idea, either, since it does not change this fact.

inline is only a hint to the compiler; it may ignore it and inline your template code or not. In short: The answer to your question does not matter. The standard/best way would be to use .cpp files for the implementation, even if you want to avoid it.

anderas
  • 5,744
  • 30
  • 49
  • i just want to know if it is possible or not ? so if i use inline keyboard compiler may or may not inline the function ? – amin Mar 19 '14 at 10:09
  • 1
    "In general, having every implementation in header files is a BAD idea" -- Tell that to the `boost` library. – Shoe Mar 19 '14 at 10:11
  • 2
    Jefffrey, they are templating their stuff, so there is no other option ;-) (Well, there is, but it involves splitting up the headers into interface and implementation headers, and instantiating every commonly used combination of template arguments in a .cpp file...) – anderas Mar 19 '14 at 10:13
  • 3
    amin, it is possible. But `inline` is only a hint to the compiler. It may inline things that you did not declare as `inline`, or generate a separate function despite something being declared `inline`. – anderas Mar 19 '14 at 10:14
5

While it is in general bad practice to put everything in a single .h file, there are situations where it's more convenient to do so. Especially when defining small classes, and during prototyping phase where the code can change a lot quickly.

I really don't recommend using templates to solve the linking issue, since it's can slow down compilation and leads to confusion: it's like creating a function taking an argument when you except that argument to always have the same value. Anyway, typing inline is shorter than template<typename T> ;)

So you either have to define your methods in the class body or annotate them with inline if defined out of the body. This is equivalent, since C++ automatically adds inline to methods defined in the class body.

Your concern appears to be with the generated code, you probably wonder if the binary is going to grow too much. But everything's cool since regardless of inline annotations, the compiler looks at every function call and decides whether to inline it or generate a call. This means the same function may sometimes be inlined (if called in a loop) and sometimes be called.

Different compilers have different heuristics, but the inline keyword doesn't have a particularly strong influence on the compiler's decision. You can use things like __forceinline or __attribute__((always_inline)) to make ask more strongly to inline a function, but even then there's no guarantee all calls to the function will be inlined. On the contrary, you may be interested in __attribute__(noinline) for gcc which will (nearly) never inline the call:

inline __attribute__(noinline) void log::log() // gcc
{
    std::cout << ++m_cnt << std::endl;
}

If you want to really know what's happening in your code you can use -Winline to see when inline functions are not inlined.

You can also use -Os or -Oz optimization levels to change internal compiler thresholds, so that it will do less inlining.

Related questions which may interest you : here and here.

Community
  • 1
  • 1
Antoine
  • 13,494
  • 6
  • 40
  • 52