为什么 std::array 的运算符 [] 不是临时的 constexpr?
Why isn't the operator[] of a std::array temporary constexpr?
当我发现不能在c++ 11中使用元素作为constexpr
初始化器时,我正在将一些值填充到constexpr std::array
中,然后继续将编译时的静态优点填充到更多的constexpr
值中。
这是因为std::array::operator[]
实际上直到c++ 14才被标记为constexpr
: https://stackoverflow.com/a/26741152/688724
在编译器标志升级后,我现在可以使用constexpr std::array
的元素作为constexpr
的值:
#include <array>
constexpr std::array<int, 1> array{{3}};
// Initialize a constexpr from an array member through its const operator[]
// that (maybe?) returns a const int & and is constexpr
constexpr int a = array[0]; // Works in >=C++14 but not in C++11
但有时我想在constexpr
计算中使用临时数组,这不起作用。
// Initialize a constexpr from a temporary
constexpr int b = std::array<int, 1>{{3}}[0]; // Doesn't work!
我从clang++ 3.6中得到-std=c++14:
prog.cc:9:15: error: constexpr variable 'b' must be initialized by a constant expression
constexpr int b = std::array<int, 1>{{3}}[0]; // Doesn't work!
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~
prog.cc:9:19: note: non-constexpr function 'operator[]' cannot be used in a constant expression
constexpr int b = std::array<int, 1>{{3}}[0]; // Doesn't work!
^
/usr/local/libcxx-3.5/include/c++/v1/array:183:41: note: declared here
_LIBCPP_INLINE_VISIBILITY reference operator[](size_type __n) {return __elems_[__n];}
^
1 error generated.
我索引的两个变量之间有什么区别?为什么我不能使用直接初始化的临时std::array
的operator[]
作为constexpr
?
第二个示例中的临时array
本身不是const
,因此最终调用非const
的operator[]
过载,而不是constexpr
。如果您先将array
转换为const
,则可以使代码正常工作。
constexpr int b = static_cast<std::array<int, 1> const&>(std::array<int, 1>{{3}})[0];
现场演示
对于@Praetorian的解决方案,您可以使用std::get(std::array)
#include<array>
int main(){
constexpr int b =
// std::array<int, 1>{{3}}[0]; // Doesn't work!
// static_cast<std::array<int, 1> const&>(std::array<int, 1>{{3}})[0]; // long but Works!
std::get<0>(std::array<int, 1>{{3}});// Works!
}
我认为std::get
在生产constexpr
方面比operator[]
更"激进"。
(测试clang 3.5
和gcc 5.0
c++ 14,应该工作在c++ 11)
另外,由于某些原因(与模板参数有关),ADL在这里不起作用,因此不可能只写get<0>(std::array<int, 1>{{3}})
.
我相信你不能使用第二个array
的operator []
,因为,不像第一个array
,第二个本身不是constexpr
,所以你试图用运行时值初始化b
。
- constexpr 函数中的非文字(通过 std::is_constant_evaluated)
- 为什么std::isnan 不是 constexpr?
- constexpr上下文中std::initializer_list的验证
- constexpr begin of a std::array
- 是否已经有一个 constexpr std::bit_cast 与 g++ 一起使用
- C++ standard: ODR and constexpr std::string_view
- 是否可以以编程方式初始化 constexpr std::array 成员
- 架构x86_64的未定义符号链接constexpr std :: array
- 带有constexpr std :: string_view vs用std :: string实例化枚举的枚举
- 是否可以将constexpr std :: array变成std :: integer_sequence
- constexpr std :: initializer_list的编译时验证
- 将constexpr std ::对阵列置换
- 静态初始化包含功能指针的对象的constexpr std ::数组
- 初始化一个constexpr std ::数组,其大小的n维std ::数组
- constexpr std ::可选的可能实现
- Constructing a constexpr std::weak_ptr
- 是否可以在编译时使用`constexpr std::initializer_list`,但不能使用ODR
- constexpr std::array with static_assert
- 这个代码怎么可能是constexpr?(std::chrono)
- 不能创建constexpr std::vector