1

What are the methods to achieve inline code in C++? I can only think about macros and inline functions. Are there more alternatives in C++11/17/20 (e.g. lambda) ? Advantages and disadvantages?

// do macros still make sense in modern C++ standards?
#define square(x) ((x)*(x))

// is this a good alternative to macros?
template <class T> inline T square(T x) { return x * x; }

EDIT: changed comment from "are macros still encouraged...?" to "do macros still make sense...?"

luca
  • 7,178
  • 7
  • 41
  • 55
  • 1
    see also https://stackoverflow.com/questions/1759300/when-should-i-write-the-keyword-inline-for-a-function-method – Caleth Feb 10 '21 at 11:00
  • 4
    *"are macros still encouraged"* When were macros encouraged? – Jarod42 Feb 10 '21 at 11:00
  • Now the compilers are good enough they can do a lot more inlining behind the scenes than you would imagine. Don't use macros unless you have absolutely no choice. – Vincent Fourmond Feb 10 '21 at 11:02
  • 1
    @Jarod42 probably you were seriuos, but you made me laugh :D encouraged might not be the right word, but in the inline code scenario they were the "standard" – luca Feb 10 '21 at 11:04
  • 1
    Macros were never meant to replace functions. Macros are not functions, and thinking of them like function leads to problems, *some* of which are detailed below – Caleth Feb 10 '21 at 11:07
  • 1
    I see MACRO as possible workarounds for missing C++ features (way to stringify variables/function (as no reflection), provide way to have source location (`__FILE__`, `__LINE__`) before `std::source_location`, configuration "selector" (`#if defined(NDEBUG) && defined(WIN32)`), ...). – Jarod42 Feb 10 '21 at 11:15

5 Answers5

4
// is this a good alternative to macros?
template <class T> inline T square(T x) { return x * x; }

Yes, this is the preferred way. (Although templates in general don't require inline, whereas explicit template specializations and instantiations do, it is ok to be consistent and write what one means).

Also note that constexpr functions and constructors are implicitly inline.

Also note that using final (where appropriate) in the context of virtual overloading can help inline even some virtual methods (check this post for some examples and explanation).

StPiere
  • 4,113
  • 15
  • 24
2

Macros have a big dis-advantage: They are namespace agnostic.

Imagine what happens if I extend your sample:

// are macros still encouraged in modern C++ standards?
#define square(x) ((x)*(x))

namespace My {

int square(int x) { return x * x; }

} // namespace My

So, IMHO, the answer is NO.

Remember that in C (where the preprocessor was introduced), there were no namespaces, and still have not been added until now.


Demo:

#define square(x) ((x)*(x))

namespace My {

int square(int x) { return x * x; }

} // namespace My

Preprocessed:

namespace My {

int ((int x)*(int x)) { return x * x; }

}

int main()
{
  std::cout << My::((10)*(10));
}

Demo on coliru

in opposition to:

#include <iostream>

template <typename T>
T square(T x) { return x * x; }

namespace My {

int square(int x) { return x * x; }

} // namespace My

int main()
{
  std::cout << My::square(10);
}

Output:

100

Demo on coliru

Scheff's Cat
  • 19,528
  • 6
  • 28
  • 56
2

Macros never were encouraged. Consider that the macro is not doing the same as the function eg here:

int foo() {
   static int x = 0;
   ++x;
   return x;
}

std::cout << square(foo());

And that is just one downside of the macro. If you want a function that takes a parameter and returns a value then that is not a macro.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
0

It smells like "opinion-based", some people tend to dislike macros more than others.

Usual disadvantages of macros:

  • they evaluate argument as many times as it is encountered (twice in your case)
  • more error prone (don't forget parentheses)
  • ignore program structure (don't belong to a namespace, and now you cannot have anything else named square, even as a class method

To mitigate the later one, name macros with ALL_CAPS, and don't name anything else like this.

The advantages of macros are:

  • C compatibility
  • Ability to have arbitrary pieces of code in macros, not just (inline) functions
Alex Guteniev
  • 12,039
  • 2
  • 34
  • 79
0

Macros should be the last resort in C++.
They're not inherently bad, but they're not checked by the compiler.

Macro expansion is a little more than text replacement done before compiling, therefore you're writing code that will be checked only after the expansion.
That means that if you make a mistake find the error could be harder, also debugging will be harder, because you won't be able to jump into the macro code. Also, you have to be careful with parentheses and with multiple evaluation.

Last but not least, all the other things pointed out by the other answers apply too.

Jack Lilhammers
  • 1,207
  • 7
  • 19