C++ static constexpr member redeclaration outside of class

那年仲夏 提交于 2019-12-24 02:58:08

问题


For the following code, why does the first case in main work fine without the redeclaration of Foo::bar, whereas 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 am assuming this is because in the first case, the compiler literally just sticks in the value, whereas in the second case the function requires an address which doesn't yet exist without the redeclaration. If that is so, then is the the thing I'm saying is declaration actually a definition? I am confused by this because an initialiser is provided in the class, but it doesn't make it a definition. For example, the third case works just fine.


回答1:


I am assuming this is because in the first case, the compiler literally just sticks in the value, whereas in the second case the function requires an address which doesn't yet exist without the redeclaration. If that is so, then is the the thing I'm saying is declaration actually a definition?

You've already answered the question. Static members are defined outside of the class, so what you have is a definition. When you pass that to the function, the address is required and therefore you need to define the static member. While in your first case the compiler simply replaces Foo::bar with the value.

Now change the function signature to the following:

int returnconstexpr(int x) { return x; }

In the above case you will no longer need the definition.

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

A variable x whose name appears as a potentially-evaluated expression ex is odr-used unless x is an object that satisfies the requirements for appearing in a constant expression (5.19) and ex is an element of the set of potential results of an expression e, where either the lvalue-to-rvalue conversion (4.1) is applied to e, or e is a discarded-value expression (Clause 5).

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



来源:https://stackoverflow.com/questions/22027228/c-static-constexpr-member-redeclaration-outside-of-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!