为什么 std::array 临时 constexpr 的 operator[] 不是?
Why isn't the operator[] of a std::array temporary constexpr?
我正在将一些值填充到 constexpr std::array
中,然后在我发现不能将元素用作 [=15] 时继续将编译时静态优点放入更多 constexpr
值中=] C++11 中的初始值设定项。
这是因为std::array::operator[]
实际上直到C++14才被标记为constexpr
:
编译器标志升级后,我现在可以使用 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!
我用 -std=c++14 从 clang++ 3.6 得到这个:
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
的 operator []
,因为与第一个 array
不同,第二个本身不是 constexpr
所以你试图用运行时值初始化 b
。
第二个示例中的临时 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[]
更 "agressive"。
(使用 clang 3.5
和 gcc 5.0
C++14 进行测试,应适用于 C++11)
另外,由于某些原因(与模板参数有关),ADL 在这里不起作用,所以不能只写 get<0>(std::array<int, 1>{{3}})
.
我正在将一些值填充到 constexpr std::array
中,然后在我发现不能将元素用作 [=15] 时继续将编译时静态优点放入更多 constexpr
值中=] C++11 中的初始值设定项。
这是因为std::array::operator[]
实际上直到C++14才被标记为constexpr
:
编译器标志升级后,我现在可以使用 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!
我用 -std=c++14 从 clang++ 3.6 得到这个:
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
的 operator []
,因为与第一个 array
不同,第二个本身不是 constexpr
所以你试图用运行时值初始化 b
。
第二个示例中的临时 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[]
更 "agressive"。
(使用 clang 3.5
和 gcc 5.0
C++14 进行测试,应适用于 C++11)
另外,由于某些原因(与模板参数有关),ADL 在这里不起作用,所以不能只写 get<0>(std::array<int, 1>{{3}})
.