mar*_*lam 8 c++ templates one-definition-rule constexpr c++11
我知道有很多类似的问题,但不知何故有不同的问题.这是关于以下情况:
#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;
}
Run Code Online (Sandbox Code Playgroud)
据我所知constexpr,编译时常量.所以编译器可以做一些计算,例如计算VALUE.此外,我可以明确定义一个constexpr std::array<,>,我可以从中将值分配给运行时变量.我希望编译器已经设置value = 4为可执行程序,以避免加载操作.但是,我不能直接从静态成员分配,得到错误
undefined reference to `MyClass<int>::ARRAY'
clang-3.7: error: linker command failed with exit code 1
Run Code Online (Sandbox Code Playgroud)
这对我没有意义,因为它可以通过另一个constexpr变量的中间步骤来完成.
所以我的问题是:为什么不能将类的静态constexpr成员分配给运行时变量?
注意:在我的MWE中,类是模板类,不会影响错误.但是,我最初对这个特殊情况感兴趣,对于非模板类,我希望它更通用.
(编译器是clang++或g++与-std=c++11- 他们给出相同的错误)
编辑:@Bryan Chen:忘了输出线.现在加入.
这undefined reference是一个链接器错误.规则是如果变量使用了odr,那么它必须有一个定义.这甚至适用于constexpr变量.
与大多数ODR规则一样,违反它是未定义的行为,无需诊断(这可以解释为什么您没有看到对该值的某些用途的诊断).
要修复错误,请在类外添加定义:
template<typename T> constexpr std::array<T,4> MyClass<T>::ARRAY;
Run Code Online (Sandbox Code Playgroud)
因为它是一个模板,你实际上可以把它放在标题中,而不是通常情况下定义恰好在一个.cpp文件中.
这里的主要问题是ARRAY[0]计算是否使用.根据这篇详细的文章,在C++ 11和C++ 14中,对数组进行索引确实算作odr-use,但是对于C++ 14提交的DR 1926改变了这种情况.
然而,这是在讨论内置数组.IDK是否适用相同的理由std::array,我发现[basic.def.odr]/3的文字难以理解.根据cppreference的非正式定义,std::array::operator[]会导致数组使用odr,因为它的返回值绑定了对数组的引用.
| 归档时间: |
|
| 查看次数: |
894 次 |
| 最近记录: |