C ++静态constexpr成员重新声明类外面 [英] C++ static constexpr member redeclaration outside of class

查看:241
本文介绍了C ++静态constexpr成员重新声明类外面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于下面的代码,为什么第一种情况在主工作正常没有重新声明Foo :: bar,而第二种情况下的函数需要它?

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.

推荐答案


我假设这是因为在第一种情况,编译器
只是在值中,而在第二种情况下,
函数需要一个地址,它不存在没有
重新声明。如果是这样,那么我说的是
声明实际上是一个定义?

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?

已经回答了问题。静态成员是在类之外定义的,所以你有一个定义。当你传递给函数时,地址是必需的,因此你需要定义静态成员。在第一种情况下,编译器只需用该值替换 Foo :: bar

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.

这个规则在C ++标准的3.2中:

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


一个变量x, - 评估表达式
ex是odr使用,除非x是满足要求的对象
出现在常量表达式(5.19)中,ex是元素
潜在结果集一个表达式e,其中
左值到右值转换(4.1)应用于e,或者e是一个
丢弃值表达式(第5条)。

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).

在上面的情况下,立即应用了左值到右值转换,因此它不是odr使用的(如标准所述),并且定义不是需要。简单来说,这意味着它可以使用值,不需要知道地址,但是当你使用一个引用类型(const int&)时,需要编译器知道对象在内存中的位置。

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.

这篇关于C ++静态constexpr成员重新声明类外面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆