gpt4 book ai didi

c++ - 如何在静态 constexpr 类成员中使用 make_tuple()?

转载 作者:搜寻专家 更新时间:2023-10-31 00:28:23 26 4
gpt4 key购买 nike

我正在尝试在 constexpr 中使用 make_tuple()。它在全局范围内工作。但它会为 static constexpr 类成员生成链接错误。

#include <iostream>
#include <tuple>

using namespace std;

class A
{
public:
static constexpr auto z = make_tuple(5, 3.0);
};

constexpr auto tp = make_tuple(6, 3.2);

int main()
{

cout << get<0>(tp) << " " << get<1>(tp) << endl; // OK

cout << get<0>(A::z) << " " << get<1>(A::z) << endl; // error: (.text+0x5a): undefined reference to `A::z'
// (.text+0x67): undefined reference to `A::z'

}

我检查了here make_tuple 本身不是 c++11 中的 constexpr。我想在这种情况下这不是问题所在。如果是,它将生成编译错误而不是链接错误。

我尝试按照 this answer 的建议在类之外定义 constexpr

class A
{
public:
static constexpr tuple<int, double> z;
};

constexpr tuple<int, double> A::z = make_tuple(5, 3.0);

但是,它会产生几个编译错误。根据 constexpr initializing static member using static function 的答案,这使得 sanse

static constexpr 类成员中使用 make_tuple 的正确方法是什么?

编译器:g++ 4.8.4clang 3.4-std=c++11

最佳答案

在 C++11/14 中,如果使用 ODR,static constexpr 变量必须在某处定义(ODR-used 的意思是“以需要它的方式使用”一个身份”。举个例子,拿一个真正的引用或指向它们的指针。这里的 ODR 意思是“一个定义规则”,而 ODR-used 意思是“在某种意义上使用,要求它有一个定义”,我将其缩写为“有一个身份”)。

Simply add:

constexpr tuple<int, double> A::z;

并且我们已经定义了它存在的位置。这需要正好在一个编译单元中。

在 C++17 中,添加了 inline 变量,我相信 constexpr 变量是隐式地内联的。我不是 C++17 专家,但是 it compiles and runs in C++1z mode没有定义,所以我的解释似乎至少对了一半。

(inline 变量,如 inline 函数,最终在编译器需要的任何地方创建定义。inline 函数通常由当有人获取它的地址时,在每个目标文件中都有一个带有特殊注释的定义,然后在链接时丢弃重复项,每个人都引用最后一个。我不知道 inline 变量往往以相同或不同的方式实现。)

如果您想在 C++11 中解决此问题,而不必将某些内容放入具有硬编码模板参数的 .cpp 文件中,change z to a constexpr function并在需要时调用它。


正如 SergyA 所提到的,ODR 在这里被触发是因为 get 返回一个 reference 到有问题的元组中的一个字段,并且该引用意味着身份必须存在字段,因此是整个元组。

理论上,精心设计的按值返回的 value_get 可以避免这种 ODR 用法,但这将取决于 tuple 的实现,因为它反过来不能调用 get

关于c++ - 如何在静态 constexpr 类成员中使用 make_tuple()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45466327/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com