constexpr begin of a std::array
constexpr begin of a std::array
我很难理解为什么 gcc-8.2.0 和 clang-7.0.0 都拒绝以下代码(这里的实时代码(:
#include <array>
int main() {
constexpr std::array<int,3> v{1,2,3};
constexpr auto b = v.begin(); // error: not a constexpr
return 0;
}
有错误
error: '(std::array<int, 3>::const_pointer)(& v.std::array<int,3>::_M_elems)'
is not a constant expression (constexpr auto b = v.begin();)
根据 en.cppreference.com,begin()
成员函数被声明为constexpr
。这是编译器错误吗?
因此,让我们避开std::array
,使这更容易一些:
template <typename T, size_t N>
struct array {
T elems[N];
constexpr T const* begin() const { return elems; }
};
void foo() {
constexpr array<int,3> v{{1, 2, 3}};
constexpr auto b = v.begin(); // error
}
constexpr array<int, 3> global_v{{1, 2, 3}};
constexpr auto global_b = global_v.begin(); // ok
为什么b
错误,但global_b
没问题?同样,如果我们宣布v
static constexpr
,为什么b
会变得没问题?问题从根本上在于指针。为了有一个作为指针的常量表达式,它必须始终指向一个已知的、常量的东西。这不适用于没有静态存储持续时间的局部变量,因为它们具有基本可变的地址。但是对于函数局部静力学或全局变量,它们确实有一个常量地址,因此您可以使用常量指针指向它们。
在标准语言中,来自 [expr.const]/6:
常量表达式是 glvalue 核心常量表达式,它引用作为常量表达式(定义如下(的允许结果的实体,或者是其值满足以下约束的 prvalue 核心常量表达式:
- 如果值是类类型的对象,[...]
- 如果值为指针类型,则它包含具有静态存储持续时间的对象的地址、超过此类对象末尾的地址 ([expr.add](、函数的地址或 null 指针值,以及
- [...]
b
在第二个项目符号中没有这些东西,所以这失败了。但是global_b
满足粗体条件 - 如果v
被宣布为static
b
也是如此.
相关文章:
- C++11 中不同类型的对象的 std::array 的替代方案
- constexpr begin of a std::array
- C++如果必须在编译时确定大小,std::array 有什么意义?
- 标准::unordered_map 中的 std::array 的值初始化
- 确保编译时的特定 std::array 位置
- std::array的长度有大小限制吗?
- 将 std::array 移动到另一个 std::array
- 为什么 std::shared_ptr 被认为是"heavy"和"expensive",但 std::array "same perfprmance as plain (c-style) arrays
- std::bind on statd::array 的运算符 []
- 检查输入 std::array 指针数据是否等于某个常量数组
- 如何读/写或遍历 std::array 中的特定元素范围?
- 是否可以使用 std::array 作为 POD 结构的数据容器?
- 如何在C++中传递一个大小未知的 std::array?
- 在现代C++中将 std::array<std:::array<T,N>> 转换为 std::vector<T>
- 在 C++ 中访问 std::array<std::array> 元素
- 将标量+std::array+std::tuple转换为一个大元组
- 如何初始化 std::array<std::array<T, 2>, 2> 的对象?
- 初始化 std::p air<double, std::array<std::p air<double, double>, 3> >
- 单独移动数组(raw array, std::array, std::vector)的每个元素
- 包装方法返回 c++ std::array<std::string, 4> in cython