Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Definition different from declaration for constexpr static member [duplicate]

Consider the code

#include <iostream>

struct Foo
{
    constexpr static int n = 42;
};

const int Foo::n; // note const, NOT constexpr

int main()
{
    std::cout << Foo::n;
}

The definition of the static member is different from the in-class declaration, i.e. const is used instead of constexpr. Is the code above legal, and if yes, why? It compiles with both gcc and clang. It also compiles if we interchanged const and constexpr in the definition and declaration, respectively. I know that constexpr implies const on variables, but not the other way around.

like image 927
vsoftco Avatar asked Dec 03 '15 04:12

vsoftco


People also ask

Why constexpr instead of define?

#define directives create macro substitution, while constexpr variables are special type of variables. They literally have nothing in common beside the fact that before constexpr (or even const ) variables were available, macros were sometimes used when currently constexpr variable can be used.

What is the difference between const and constexpr?

The primary difference between const and constexpr variables is that the initialization of a const variable can be deferred until run time. A constexpr variable must be initialized at compile time.

Does constexpr need to be static?

A static constexpr variable has to be set at compilation, because its lifetime is the the whole program. Without the static keyword, the compiler isn't bound to set the value at compilation, and could decide to set it later. So, what does constexpr mean?

Where is constexpr defined?

constexpr stands for constant expression and is used to specify that a variable or function can be used in a constant expression, an expression that can be evaluated at compile time. The key point of constexpr is that it can be executed at compile time.


1 Answers

My two cents, while looking at some documentation like that one.

Actually, it could be valid.

In fact, the difference between constexpr and const mainly relies into their purposes, but the former implies the latter as a side effect.

There is also a more subtle difference: constexpr is a specifier, while const is a type qualifier.

In particular:

const’s primary function is to express the idea that an object is not modified through an interface

On the other side:

constexpr’s primary function is to extend the range of what can be computed at compile time, making such computation type safe and also usable in compile-time contexts

Or even more concise from here:

constexpr - specifies that the value of a variable or function can appear in constant expressions

Anyway it happens that:

constexpr in front of a variable definition [...] implies const

So, even though the reason for which one should use constexpr instead of const is clear, and everybody tends to remember that:

constexpr is not a general purpose replacement for const (or vice versa)

It's a fact that using constexpr you are actually saying that this member is implicitly const (also you have a set of more specific constraints on how that member can be defined).

Anyway, once defined, the member is nothing more than a data member having the const type qualifier (which can be used in constant expressions), that is what you are declaring out of your class.

like image 150
skypjack Avatar answered Oct 24 '22 01:10

skypjack