5

I am used to D coding and Python where the class definition also contains each method definiton. So it is my preferred style of coding.

I abhor having to switch to the .cpp file and use that long qualifier name.

So, since I rarely call a function more than 2-3 times, isn't it a good idea to inline most of my code? My code is not a library. It's a desktop application for mathematicians to use.

This makes sense to me. Is this okay to do? Thanks.

7
  • 5
    It doesn't sound to me like you know what inlining is. See geeksforgeeks.org/inline-functions-cpp Commented Sep 5, 2018 at 1:21
  • 3
    The description of inlining in your question does not match the description of inlining in the link I provided. You're going to have to find some way to resolve that discrepancy before we can proceed. Commented Sep 5, 2018 at 3:11
  • 2
    While you're working on that, the obvious answer to your question is "no, it's not a good idea." If it were a good idea to inline all of your methods, then C++ would already do that unconditionally, and you wouldn't need to do it yourself. Note that the inline keyword is not a mandate; it's a hint to the compiler that merely suggests inlining, the compile will inline if it decides that it makes sense to do so. It's seldom a smart idea to try and outwit the compiler nowadays anyway; it will make the right decision most of the time. Commented Sep 5, 2018 at 3:13
  • 2
    Robert is trying to tell you, you mixed up "inlining" with "header only". Though both concepts are connected, they are not the same. So are you asking if it is a good idea to write all your C++ code in headers? Or do you ask for inlining? Please clarify.
    – Doc Brown
    Commented Sep 5, 2018 at 7:33
  • 2
    It seems pretty obvious to me that the OP is asking whether he should define all his member functions inside the class body instead of having separate definitions, because he doesn't like the .h/.cpp separation and qualified name usage that this would imply. And yes, that's commonly called "inlining" too. Actually, more commonly IMO than putting inline on a definition; what is most commonly called "inlining" is what the compiler does, not what the programmer does. Commented Sep 5, 2018 at 8:07

3 Answers 3

17

When you're writing C++, don't write it as if it were Python or D or Java. Those are fundamentally different languages with different idioms.

When we are talking about inline functions in C++, we have to distinguish two related but distinct concepts:

  • inline functions in a header. Function definitions within a class declaration are implicitly inline. Templates are usually inline.

    An inline function (or variable) effectively disables the one-definition rule (ODR): If the linker sees multiple conflicting definitions for the same function in different compilation units the linker would usually show an error. But with inline functions, you are promising that all definitions are identical. Additionally, an inline function can only be called from the same compilation unit where it was defined.

  • inlining as a compiler optimization. The semantics of an inline function make inlining possible, but the inline keyword does not imply that a function will be inlined. For example, a member function that was defined inline cannot be inlined through indirect calls, such as virtual calls.

    • You can make inlining of non-inline functions possible by giving them internal linkage, either through the static keyword for free functions/variables (but not members!) or through the use of an anonymous namespace.

    • You can use compiler-specific attributes. For example, __attribute__ ((always_inline)) in GCC.

It is not advisable to define all your functions inline in a header.

  • This slows down compile times. By using multiple compilation units you can benefit from incremental compilation. This makes work on any but the most trivial C++ projects more enjoyable. But if you put unnecessary code into the header, it has to be parsed, compiled and optimized in its entirety every time. Because templates generally imply inline definitions in a header, these compile times are a reason why some projects try to limit the use of templates.

  • It leads to namespace pollution and a lack of encapsulation. Quite a lot of code tends to need some private helpers. In Python I'd add a underscore-function to the module, in C++ a static function or some code in an anonymous namespace so that they are restricted to the current compilation unit. But when everything is in the headers you only have a single compilation unit. All those helpers will be visible to all your code, and you effectively have no internal structure . This might also lead to name clashes.

  • Additionally, consider how you include headers. In the normal header–implementation split, headers that are only needed internally but not for the module's public interface can be included in the .cpp file. This limits the effects of that header, for example with any macros or global functions. This is especially important when interfacing with C libraries. This will also allow you to bridge between libraries that provide conflicting names. Not so when all your code is in the header. All included definitions will also be visible in all compilation units where your header is included.

  • Inline definitions only work when your dependencies can be linearized, but e.g. not for circular or recursive dependencies (such as a class that represents a tree node). Even if you put your code into a header, it might be necessary to use forward declarations or to define a method outside of the class declaration. If that method doesn't have to be inline, then you gain nothing from defining it in the header.

If you dislike having to switch between headers and implementation files often, I suggest you look into using an IDE that lets you jump between declarations and corresponding definitions more easily.

Yes, C/C++ can be super annoying languages with all their historic cruft. And yes, Java code tends to be nicer to read. But you will not get any benefits from trying to write C++ as if it were Java. You'd just be giving up the benefits that C++ can offer. Similarly, modern C++ avoids creating objects with new as that effectively gives up RAII.

3
  • "a member function that was defined inline cannot be inlined through indirect calls, such as virtual calls" Depends on whether the compiler can prove which function to call. Or which to call most of the time, to at least get some of the opportunities inlining gives for further optimization. Commented Sep 12, 2018 at 15:31
  • @Deduplicator I put that there as an example of a major restriction on inlining, another would be recursive functions. Virtual calls and function pointers are really hard to optimize away in most cases. Even JIT compilers which can gather detailed call site statistics often don't bother. However, I found out while researching another question that e.g. GCC does perform speculative inlining of virtual inline methods.
    – amon
    Commented Sep 12, 2018 at 15:44
  • Python and "high" languages are built upon C++ and assembler. You must remember that because of this it requires you to do a lot more thinking. This will be a double edged sword: certain things like garbage collection are now your business, but on the plus side you don't have to worry about GC hogging your task cycles, either. What people often get wrong is that Python and C++ are somehow interchangeable because they can both produce a 'hello world' program. But actually they are just a layering over C++. To put it simply: you can make fire with wood, but you can't make wood with fire. Commented 9 hours ago
5

If by inlining you mean use the inline function, you don't need to:

  • mainstream compilers now perform global optimisation and will do it automatically for you if it has a real performance advantage.
  • the wording of the standard shows that you won't influence much what the compiler will do:

    An implementation is not required to perform this inline substitution at the point of call

  • The main difference is if you define a function in a header. With the inline keyword, the compiler will allow the header to be included in several places, being understood it's the same function everywhere. Without inline, you might break the One Definition Rule (ODR) if the same header is included in different units.

If by inlining you mean putting the member function definition inside the class definition in the header, then this practice is not the recommended one. It will not break the ODR rule if the exact same sequence of tokens is used for the same class in each compilation unit. But there are a couple of things that are more difficult to do (especially if there are some mutual dependencies between two classes). Separating the class definition fro its implementation has the advantage of encouraging encapsulation.

1

I really like a well-documented header file, that only tells me what I want to know: class and method names, what the methods are spec’d to do. I don’t want to see your source code. It only makes it harder to read the stuff I want.

Swift does it nicely: you write the code the way you want it, the IDE generates header files if I want to see them, and they only contain things of interest (like no private methods or properties).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.