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.