如何正确使用constexpr std::rotate?编译期使用问题咨询
C++17中constexpr rotate的可用场景解析
先明确C++17的核心限制
C17对constexpr函数的约束比C20严格不少:
- constexpr对象默认是const的,它的非const成员函数没法在constexpr上下文中调用(STL容器的修改操作基本都是非const成员)
- 非constexpr变量不属于常量表达式求值范畴,没法在constexpr初始化过程中修改它
你遇到的两个错误本质
- 操作非constexpr变量初始化constexpr变量:常量表达式要求整个初始化流程里的所有操作都必须是常量表达式,非constexpr变量不在这个上下文里,自然不能碰。
- constexpr容器只读无法赋值:constexpr容器自带const属性,修改元素需要调用非const成员函数,这在C17的constexpr规则里是不允许的(C20放宽了这个限制)
不止右值容器这一种场景
虽然受限,但还有几种可行的用法:
1. 操作constexpr数组(或std::array)
数组是聚合类型,C++17允许在constexpr函数内修改局部数组或std::array的元素,只要它们是在常量表达式求值过程中创建的:
constexpr auto rotate_array() { int arr[] = {1,2,3,4}; const int shift = 1; // 手动实现左移一位的rotate逻辑 int temp = arr[0]; for (size_t i = 0; i < sizeof(arr)/sizeof(arr[0]) - 1; ++i) { arr[i] = arr[i+1]; } arr[sizeof(arr)/sizeof(arr[0]) - 1] = temp; return arr; } constexpr auto rotated_arr = rotate_array(); // 合法,结果是{2,3,4,1}
对于std::array也一样,它在C++17里支持constexpr修改:
constexpr auto rotate_std_array() { std::array<int,4> arr = {1,2,3,4}; int temp = arr[0]; for (size_t i = 0; i < arr.size()-1; ++i) { arr[i] = arr[i+1]; } arr.back() = temp; return arr; } constexpr auto rotated_std_arr = rotate_std_array(); // 合法
2. 自定义带mutable constexpr成员的容器
如果你自己实现简单容器,把修改操作标记为constexpr mutable,可以在constexpr函数内修改constexpr左值容器的拷贝:
template<typename T, size_t N> struct ConstBuf { T data[N]; // mutable允许在const对象上调用这个constexpr函数 constexpr mutable void rotate_left() { T temp = data[0]; for (size_t i = 0; i < N-1; ++i) { data[i] = data[i+1]; } data[N-1] = temp; } }; constexpr ConstBuf<int,4> original = {{1,2,3,4}}; constexpr auto rotated = []{ auto copy = original; // 拷贝constexpr对象 copy.rotate_left(); return copy; }(); // 合法,rotated的data是{2,3,4,1}
不过这种方式只能用自定义容器,STL在C++17里没有提供这类成员函数。
3. 处理constexpr函数内的局部临时容器
只要是在constexpr函数内部创建的临时容器(且类型支持C++17 constexpr操作),都可以修改后返回,这其实和你用右值的方式类似,但范围更广——比如直接在函数内创建容器并修改,而不是外部传右值。
总结
C++17里constexpr rotate的可用场景确实有限,但绝非只有右值容器这一种。核心原则是:
- 只修改常量表达式求值上下文内的自动对象(局部变量、临时对象)
- 避免直接修改const限定的constexpr左值对象(除非用自定义mutable容器)
- 优先使用数组、std::array这类C17支持constexpr修改的类型,避开std::vector这类需要动态分配内存的容器(C20才支持constexpr动态内存)
内容的提问来源于stack exchange,提问作者cmannett85
相关产品推荐
相关产品推荐

