c++c++17inline-variable

How do inline variables work?


At the 2016 Oulu ISO C++ Standards meeting, a proposal called Inline Variables was voted into C++17 by the standards committee.

In layman's terms, what are inline variables, how do they work and what are they useful for? How should inline variables be declared, defined and used?


Solution

  • The first sentence of the proposal:

    The ​inline specifier can be applied to variables as well as to functions.

    The ¹guaranteed effect of inline as applied to a function, is to allow the function to be defined identically, with external linkage, in multiple translation units. In practice that means defining the function in a header, that can be included in multiple translation units. The proposal extends this possibility to variables.

    So, in practical terms the (now accepted) proposal allows you to use the inline keyword to define an external linkage const namespace scope variable, or any static class data member, in a header file, so that the multiple definitions that result when that header is included in multiple translation units are OK with the linker – it just chooses one of them.

    Up until and including C++14 the internal machinery for this has been there, in order to support static variables in class templates, but there was no convenient way to use that machinery. One had to resort to tricks like

    template< class Dummy >
    struct Kath_
    {
        static std::string const hi;
    };
    
    template< class Dummy >
    std::string const Kath_<Dummy>::hi = "Zzzzz...";
    
    using Kath = Kath_<void>;    // Allows you to write `Kath::hi`.
    

    From C++17 and onwards I believe one can write just

    struct Kath
    {
        static std::string const hi;
    };
    
    inline std::string const Kath::hi = "Zzzzz...";    // Simpler!
    

    … in a header file.

    The proposal includes the wording

    ​An inline static data member can be defined in the class definition and may s‌​pecify a ​brace­-or­-equal­-initializer. If the member is declared with the constexpr specifier, it may be redeclared in namespace scope with no initializer (this usage is deprecated; see‌​ D.X). Declarations of other static data members shall not specify a ​brace­-or­-equal­-in‌​itializer

    … which allows the above to be further simplified to just

    struct Kath
    {
        static inline std::string const hi = "Zzzzz...";    // Simplest!
    };
    

    … as noted by T.C in a comment to this answer.

    Also, the ​constexpr​ specifier implies  inline for static data members as well as functions.


    Notes: ¹ For a function `inline` also has a hinting effect about optimization, that the compiler should prefer to replace calls of this function with direct substitution of the function's machine code. This hinting can be ignored.