将静态constexpr类成员分配给运行时变量 [英] Assign static constexpr class member to runtime variable

查看:278
本文介绍了将静态constexpr类成员分配给运行时变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道有很多类似的问题,但有些不同的问题。它是关于以下情况:

I know there are a lot of similar questions, but somehow different questions. It is about the following situation:

#include <iostream>
#include <array>

template<typename T> class MyClass
{
public:
    static constexpr std::array<T,4> ARRAY {{4, 3, 1, 5}};
};

int main()
{
    constexpr std::array<int, 4> my_array(MyClass<int>::ARRAY); // works fine -> can use the ARRAY to initialize constexpr std::array

    constexpr int VALUE = 5*MyClass<int>::ARRAY[0]; // works also fine

    int value;
    value = my_array[0]; // can assign from constexpr
    value = MyClass<int>::ARRAY[0]; // undefined reference to `MyClass<int>::ARRAY

    std::cout << VALUE << std::endl;
    std::cout << value << std::endl;

    return 0;
}

据我所知 constexpr 用于编译时常量。所以编译器可以做一些计算,例如计算 VALUE 。另外,我可以明显定义一个 constexpr std :: array<,> ,从中可以将值分配给运行时变量。我希望编译器将 value = 4 设置为可执行程序,以避免加载操作。但是,我不能直接从静态成员赋值,得到错误

As far as I understand constexpr is for compile-time constants. So the compiler can do already some calculation, for example to calculate the VALUE. Also I can obviously define a constexpr std::array<,>, from which I can assign the values to runtime variables. I would expect the compiler to set already value = 4 into the executable program, to avoid a loading operation. However, I cannot assign directly from the static member, getting the error

undefined reference to `MyClass<int>::ARRAY'
clang-3.7: error: linker command failed with exit code 1

因为它可以通过另一个 constexpr 变量的中间步骤完成。

which makes no sense to me, because it can be done with an intermediate step of another constexpr variable.

所以我的问题是:为什么类的静态constexpr成员不能分配给运行时变量?

So my question is: Why can a static constexpr member of a class not be assigned to a runtime variable?

注意:在我的MWE中,类是一个模板类,不会影响错误。但是,我最初对这种特殊情况感兴趣,我希望对于非模板类更普遍。

Note: In my MWE the class is a template class, which does not affect the error. However, I was originally interested in this particular case, which I expect to be more general as for a non-template class.

(编译器 clang ++ g ++ -std = c ++ 11

编辑:@Bryan Chen:忘记输出行。

@Bryan Chen: Forgot the output lines. Are added now.

推荐答案

未定义的引用是链接器错误。规则是,如果变量是 odr-used ,那么它必须有一个定义。这也适用于 constexpr 变量。

The undefined reference is a linker error. The rule is that if a variable is odr-used then it must have a definition. This applies even for constexpr variables.

与大多数ODR规则一样,违反它是未定义的行为,

Like most ODR rules, violating it is undefined behaviour with no diagnostic required (which could explain why you saw no diagnostic for some of your uses of the value).

要修复错误,请在类外添加一个定义:

To fix the error, add a definition outside the class:

template<typename T> constexpr std::array<T,4> MyClass<T>::ARRAY;

因为它是一个模板,你可以把它放在标题中,该定义恰好在一个 .cpp 文件中。

Since it is a template you can actually put this in the header, as opposed to the usual case where the definition goes in exactly one .cpp file.

这里的主要问题是 ARRAY [0] 是否计为 odr-use 。根据此详细的帖子,在C ++ 11和C + +14,索引数组的计数为 odr-use ,但是更改了 DR 1926 针对C ++ 14提交,不是 odr使用

The main issue here is whether ARRAY[0] counts as odr-use. According to this detailed post, in C++11 and C++14, indexing an array does count as odr-use , but this was changed by DR 1926 filed against C++14 to not be odr-use.

>但,这是在谈论内置数组。 IDK是否相同的理由适用于 std :: array ,我发现[basic.def.odr] / 3的文本很难理解。根据 cppreference 的非正式定义, std :: array :: operator [] 会导致数组的 odr-use ,因为它的返回值绑定了对数组的引用。

However, that is talking about builtin arrays. IDK whether the same rationale applies to std::array, I find the text of [basic.def.odr]/3 hard to understand. According to the informal definition on cppreference, std::array::operator[] would cause odr-use of the array because its return value binds a reference to the array.

这篇关于将静态constexpr类成员分配给运行时变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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