Enlico
Enlico

Reputation: 28416

inline const(expr) variables vs functions returning static const(expr) variables - Is there any reason to prefer one or the other approach?

Several times I've seen code like this in a header

IMPORTOREXPORT std::string const& foo();
IMPORTOREXPORT std::string const& bar();
IMPORTOREXPORT std::string const& baz();

and the following corresponding code in a cpp file

std::string const& foo() {
  static std::string const s{"foo"};
  return s;
}
std::string const& bar() {
  static std::string const s{"bar"};
  return s;
}
std::string const& baz() {
  static std::string const s{"baz"};
  return s;
}

where IMPORTOREXPORT is a macro to deal with linkage, so yes, I'm talking of a multi-module code, where different translation units are compiled independently and then linked together.

Is there any reason why I should prefer the above solution to simply have these in the header?

inline std::string const foo = "foo";
inline std::string const bar = "bar";
inline std::string const baz = "baz";

I found this related question, but I'm not sure it entirely answers this. For instance, the accepted answer contains this (part of a) statement

for different modules would be different addresses

but this doesn't seem to be inline with what read on cppreference (emphasis mine):

  1. An inline function or variable (since C++17) with external linkage (e.g. not declared static) has the following additional properties:

    1. It has the same address in every translation unit.

Upvotes: 2

Views: 380

Answers (1)

Brian Bi
Brian Bi

Reputation: 119174

As you note, the inline variable approach guarantees that the variable has a unique address, just like the static local variable approach.

The inline approach is certainly easier to write, but:

  1. It doesn't work on pre-C++17 compilers.
  2. It's more expensive to build:
    1. Every translation unit that odr-uses the inline variable must emit a weak definition for that variable, and the linker must discard all but one of these symbols so that the variable has a unique address.
    2. If the variable has dynamic initialization, then every translation unit that odr-uses it also needs to emit a piece of code to dynamically initialize it, and again, the linker must discard all but one copy.
    3. Every translation unit that includes the header that defines the inline variable is forced to have a compile-time dependency on the header that defines the variable's type, even if there are no uses of the variable besides the definition itself.

Upvotes: 1

Related Questions