C++ 初始化结构内的静态constexpr变量和类

C++ 初始化结构内的静态constexpr变量和类,c++,struct,constexpr,C++,Struct,Constexpr,以下是我的工作代码示例: #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>

以下是我的工作代码示例:

#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;
}
如果我不使用上面的代码,我会得到
undefined
参考错误。其中int已经很好了,只需执行以下操作即可访问:

static constexpr int y = x;    

我担心为什么我不必再转发声明了

static constexpr成员在初始化时在
类{}
范围内有一个值,但在
类{}
外部定义之前,它在内存中没有位置(地址)。原因是您可能决定在链接库中包含其部分或全部专门化(例如,
.o
.so
),或者默认情况下是否为专门化提供有效的内联链接

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


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

< P>因为C++ 17引入静态内联变量,并使静态COSTEXPR变量隐式内联,所以您的问题的答案现在变得更简单。因此,在您的示例中,您可以简单地使用以下内容,而无需在类外声明变量
bee
(尽管出于兼容性原因仍然允许):

如果静态数据成员声明为constexpr,则它是隐式内联的 并且不需要在命名空间范围内重新声明。这 无初始值设定项的重新声明(以前要求[…]) 仍然允许,但已弃用


啊,那么,即使它们被定义了,它们在一开始也没有被正确分配?@CarloBrew根据官方标准术语,从技术上讲,它是“用初始值设定项声明”的,但不是“定义”为对象的。课外声明就是定义。啊,我明白了,谢谢!你所说的constexpr是什么意思?我应该如何避免呢?我没有说作为constexpr进行计算,我说的是作为常量表达式进行计算……并避免将
constexpr
放在只能在运行时执行的函数上。
constexpr
说明符表示函数在编译时是安全的,至少对于某些参数值是安全的。Oooo因为
cout
只在运行时计算?
static constexpr int y = x;    
template<int x>
struct A {
    static constexpr b<int> bee = x;
};
struct X
{
    inline static int n = 1;
};