Home > database >  Definition of static data member without repeating its type
Definition of static data member without repeating its type

Time:04-02

When I have a class with a static const or constexpr data member, defining that variable reqires me to repeat stuff:

/// my_class.hpp
class my_class { constexpr static int x = 1; };
/// my_class.cpp
#include "my_class.hpp"
// auto my_class::x; // error: declaration of 'auto my_class::x' has no initializer
// decltype(auto) my_class::x; // error: declaration of 'decltype(auto) my_class::x' has no initializer
decltype(my_class::x) my_class::x; // ok

Of course I could do

#define DEFINE_STATIC_DATA_MEMBER(x) decltype(x) x
DEFINE_STATIC_DATA_MEMBER(my_class::x);

but I wonder if there’s a non-macro solution.

The question arose because both the type and the fully-qualified name of the static data member are lengthy and I’m likely to get more of these.

CodePudding user response:

You can make use of a typedef to not have to repeat the type when defining it.

my_class.hpp

class my_class
{
    // Declaration
    static const my_very_lengthy_type_name_I_dont_want_to_repeat x;

    // typedef
    using t = decltype(x);
};

my_class.cpp

#include "my_class.hpp"

// Initialization
my_class::t my_class::x = {};

CodePudding user response:

Starting from C 17 you don't need to separately define static constexpr variables.

Just class my_class { constexpr static int x = 1; }; is enough, without a .cpp file.

CodePudding user response:

defining that variable requires me to repeat stuff:

For static constexpr data member, the above statement is true only for Pre-C 17 standard.

From C 17 onwards, we're allowed to omit writing an out-of-class definition of a static constexpr data member. This is illustrated in the example given below.

C 11

class Foo
{
public:
    static constexpr int OUT_OF_BOUNDS_VALUE = -9999; //THIS IS A DECLARATION IN C  11 and C  14
    //other members here
};

In the above code snippet(which is for C 11,C 14), we have a declaration of the static data member OUT_OF_BOUNDS_VALUE inside the class. And so, in exactly one translation unit we have to provide a corresponding definition. Otherwise you'll get a linker error which can be seen here.

That is, in exactly one translation unit we should write:

constexpr int Foo::OUT_OF_BOUNDS_VALUE;  //note no initializer

After adding the above out of class definition with no initializer the program will work. Demo

C 17

But the out-of-class definition for static constexpr is no longer needed from C 17 onwards.

class Foo
{
public:
    static constexpr int OUT_OF_BOUNDS_VALUE = -9999; //THIS IS A DEFINITION IN C  17
    //other members here
};

In the above code snippet(which is for C 17) we have a definition of the static data member OUT_OF_BOUNDS_VALUE inside the class. So since C 17, we don't have to provide the definition of OUT_OF_BOUNDS_VALUE anywhere else since we already have a definition for it inside the class and thus the same program works without any linker error.

  • Related