C ++ static constexpr member redeclaration outside class

For the following code, why is the first case in the main work fine without re-writing Foo :: bar, while the second case with the function requires it?

struct Foo{ static constexpr int bar = 30; }; //Declaration of Foo::bar outside of struct constexpr int Foo::bar; int returnconstexpr(const int& x) { return x; } int main() { //Ok without declaration outside of struct std::cout << Foo::bar << std::endl; //Requires declaration outside of struct std::cout << returnconstexpr(Foo::bar) << std::endl; //Here static constexpr works as a definition static constexpr int x = 2; std::cout << returnconstexpr(x) << std::endl; return 0; } 

I assume that this is because in the first case, the compiler literally just sticks to the value, while in the second case, the function requires an address that does not yet exist without rewriting. If so, is that what I am saying is this announcement, really a definition? I am confused by this because the initializer is provided in the class, but it does not make it a definition. For example, the third case works fine.

+1
c ++ struct definition static constexpr
source share
1 answer

I assume that this is because in the first case the compiler literally sticks to the value, while in the second case the function requires an address that does not yet exist without redefinition. If so, is that what I am saying is this declaration really a definition?

You have already answered the question. Static members are defined outside the class, so you have a definition. When you pass this to a function, an address is needed, so you need to define a static member. Although in your first case, the compiler simply replaces Foo::bar with a value.

Now replace the function signature as follows:

 int returnconstexpr(int x) { return x; } 

In the above case, you no longer need a definition.

The rule for this in 3.2 of the C ++ standard:

The variable x whose name is displayed as a potentially evaluated expression ex is used by odr if x is not an object that satisfies the requirements for displaying in constant expression (5.19), and ex is an element of the set of potential results of expression e, where either lvalue-to-rvalue conversion (4.1) applied to e or e is the expression of the reset value (section 5).

In the above case, the lvalue-rvalue conversion is immediately applied, and therefore it is not used by odr (as specified in the standard), and no definition is required. In simple words, this means that it can simply use the value and does not need to know the address, however, when you use the reference type (const int &), it requires the compiler to know where the object is in memory.

+1
source share

All Articles