在结构内部初始化静态constexpr变量和类 [英] Initializing static constexpr variables and classes inside a struct

查看:86
本文介绍了在结构内部初始化静态constexpr变量和类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的工作代码示例:

Here is my working code example:

#include <iostream>

template<typename B>
class b {
public:
    int y;

    constexpr b(int x) : y(x) {

    }

    constexpr void sayhi() {
        std::cout << "hi" << std::endl;
    }
};



template<int x>
struct A {
    static constexpr b<int> bee = x;
    static constexpr int y = x;         // this one is fine and usable already, I don't have to do something like what I did on member bee

    inline static void sayhi() {
        std::cout << y << std::endl;
    }
};

template<int x>
constexpr b<int> A<x>::bee;        // why do I have to do something like this, it will cause errors if I don't.

int main(int argc, char** argv) {
    A<30>::bee.sayhi();             // works fine
    A<30>::sayhi();                 // works fine

    return 0;
}

我的代码很简单,我有模板结构 A 具有两个静态变量,即静态constexpr int y 静态constexpr b< int>蜜蜂= x; 。我的模板结构 A 将获取参数的值,该参数将由 x 从template参数复制。我的问题是:关于类,为什么要这样做呢?

What my code does is simple, I have template struct A that has two static variables, namely a static constexpr int y and a static constexpr b<int> bee = x;. My template struct A will get the value of the argument which will be copied by x from the template parameter. My question is: how come when it comes to classes, I have to initialize the class by doing something like this:

template<int x>
constexpr b<int> A<x>::bee; 

如果我不使用上面的代码,则会得到 undefined 参考错误。其中int已经可以通过以下操作完成:

If I don't use the code above, I get the undefined reference error. Wherein the int is already fine and accessible just from doing something like:

static constexpr int y = x;    

我担心为什么我不再需要转发它了。

I am concerned why I don't have to forward declare it anymore.

推荐答案

静态constexpr 成员在内部初始化时具有一个值 class {} 范围,但是在 class {} 。原因是您可能决定在链接库中包含其某些或全部专长(例如 .o .so ),或者默认情况下是否将有效的内联链接赋予专业化。

A static constexpr member has a value upon its initialization inside the class { } scope, but it does not have a location in memory (an address) until it is defined outside the class { }. The reason is that you may decide to include some or all of its specializations in a link library (e.g. .o or .so), or whether to give effectively-inline linkage to specializations by default.

如果曾经使用对象的地址,则需要类外定义,这意味着它必须作为全局变量存在。另一方面,如果只希望 constexpr 成员仅在编译时存在,禁止全局存储分配,则省略定义是一个不错的选择。

The out-of-class definition is required if the address of the object is ever used, which implies that it must exist as a global variable. On the other hand, if you want the constexpr member only to exist at compile time, prohibiting global storage allocation, then omitting the definition is a good choice.

顺便说一句,不允许将 constexpr 说明符放在永远不能被视为常量表达式的函数上,例如 sayhi 打印到 std :: cout 。这是一条无需诊断(NDR)规则,这意味着编译器现在可能不会抱怨,但下一版本的编译器可能会抱怨。

By the way, it's not allowed to put the constexpr specifier on a function that can never be evaluated as a constant expression, such as sayhi which prints to std::cout. This is a "no diagnostic required (NDR)" rule, meaning that the compiler might not complain now but the next compiler version might.

这篇关于在结构内部初始化静态constexpr变量和类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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