【发布时间】:2016-06-25 23:16:26
【问题描述】:
我知道有很多类似的问题,但在某种程度上是不同的问题。大概是以下几种情况:
#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 设置到可执行程序中,以避免加载操作。但是,我不能直接从静态成员分配,得到错误
undefined reference to `MyClass<int>::ARRAY'
clang-3.7: error: linker command failed with exit code 1
这对我来说毫无意义,因为它可以通过另一个 constexpr 变量的中间步骤来完成。
所以我的问题是:为什么不能将类的静态 constexpr 成员分配给运行时变量?
注意:在我的 MWE 中,该类是一个模板类,不会影响错误。不过,我最初对这种特殊情况很感兴趣,我希望它能够像非模板类那样更通用。
(编译器是 clang++ 或 g++ 和 -std=c++11 - 它们给出相同的错误)
编辑:@Bryan Chen:忘记了输出行。现已添加。
【问题讨论】:
-
clang++有这个问题:coliru.stacked-crooked.com/a/e9698f2bb249e509。但是g++有效:coliru.stacked-crooked.com/a/5ef23fe29b0aaa28。 Clang 错误? -
VS2015 这么说:
in-class initialization for type 'const std::array<int,4>' is not yet implemented; static member will remain uninitialized at runtime but use in constant-expressions is supported。您可能会遇到类似的情况。 -
@Bryan:我不精确。我安装了 g++4.8.5,它还不支持 C++14。但我希望这已经适用于 C++11!?
-
我不知道
template是否会破坏这种特殊情况或更新的标准,但如果这是一个正常的class声明,您仍然需要定义 i>static成员,即使是常量(除非它是int或其他类似类型),不是吗? -
Similar question - 没有发布令人满意的答案
标签: c++ templates c++11 constexpr one-definition-rule