Why are there no inline variables?

5.2k views Asked by At

The inline keyword in C++ allows functions to be defined in headers so that the compiler can either actually inline them or leave only one copy of the function. This allows reducing the number of compilation units by defining the functions directly in headers, with the advantage of often several times faster compilation time and possibly faster execution.

Why can't this same pattern be applied to namespace-scope variables, while functions in C++ actually are namespace-scope variables when viewing them as a special pointer?

What I can think of is using a static local variable of an inline function.

inline std::string& Hello__() { //Edit: Added the &
    static std::string hello("Hello");
    return hello;
}

#define Hello (Hello__())

Edit: I'd like to clarify my question as below.

I'm using the term 'inline' as what the compiler understands. It lets the same definition with the same name be in multiple compilations units, allowing the definition in the header. The main advantage of 'inline' is not the performance benefit as a macro function would have but the shorter compilation time from the reduced number of compilation units. It can possibly be several times shorter.

I did come out with a solution to let a variable work like an inline function. But I am still finding for a better way to do this.

To state again clearly, what I want to achieve is defining a namespace-scope variable in the header like an inline function, in order to make the build process as simple and fast as possible.


Edit2: Thank you for the link in the comment by dyp. I've just read the proposal, and that is exactly what I am thinking of. What is the current status of that proposal?

Quoted from the proposal:

However, it is not uncommon to desire the existence of a globally­ unique object without having to pick a single translation unit in which to define it. As a practical matter, making this choice generally requires either the use of non­trivial preprocessor macros, separately compiled libraries, or both. However, one strength of C++ is its ability to support the development of header­only libraries. In this vein, the lack of the ability to define an inline variable poses a significant constraint on library design.

4

There are 4 answers

0
bipll On

Variables actually can be inlined, but they would not be globally the same then.

zzz.h:

#ifndef ZZZ_H_b6e267bb76401a0cd6502e426a702e41d792a853
#define ZZZ_H_b6e267bb76401a0cd6502e426a702e41d792a853

namespace {
    int omg;
}

static int hello;

// int thisWouldBreakCompilationSoIsCommentedOut;

#endif

xxx.cpp:

#include "zzz.h"

zzz.cpp:

#include "zzz.h"

int main() {}

Let's see if it compiles altogether:

$ g++ xxx.cpp zzz.cpp
$
0
cmaster - reinstate monica On

Your "inlined variable" Hello behaves exactly like a global variable would. The only difference is that, in addition to its declaration in a header, a global variable also requires a definition in a single compilation unit while Hello does not need that.

I guess, the reason why there is no language support for "inlined variables" is simply that global variables are rightly considered evil anyway. You simply don't use them in modern code. As such, languages should not add complexity to their syntax to support something that's not used anyway.

2
Uri Brecher On

Here is a short experiment I did with your suggestion:

file a.cpp:

inline int& get_inline_int() {
    static int my_inline_int = 0;
    return my_inline_int;
}

void set_me(int x) {
    get_inline_int() = x;
}

file b.cpp:

#include <iostream>

inline int& get_inline_int() {
    static int my_inline_int = 0;
    return my_inline_int += 2;
}

void show_me() {
    std::cout << get_inline_int() << std::endl;
}

file main.cpp:

void set_me(int);
void show_me();

int main() {
    set_me(7);
    show_me();
    set_me(8);
    show_me();
    return 0;
}

I cheated a little and gave two different implementations to the same function. Without inline the linker will complain about duplicate symbol, but I get away with it with the inline in use.

I have to admit that the result surprised me. I tried it with both g++ and clang++ and got similar results:

clang++ a.cpp b.cpp main.cpp -o runme

will output

7
8

clang++ b.cpp a.cpp main.cpp -o runme

will output

9
10

So, I consider this a misuse of the language because the compilation result is unpredictable and usually not what you meant it to be. If a committee will be able to define a behaviour that is predictable I would use these so called "inline" variables myself.

1
gnzlbg On

C++17 has inline variables, see: N4424.