为什么std::get针对ranges::subrange仅提供两个函数重载?
关于ranges::subrange的std::get重载缺失问题解答
为什么最初只有两个重载
ranges::subrange属于标准定义的类pair类型,最初设计std::get重载时是参考std::tuple、std::pair等传统类pair类型的通用语义:默认认为get操作是只读的,不需要修改原对象,因此只提供了const subrange&和subrange&&两个重载。
但ranges::subrange和其他类pair类型有本质区别:它的begin()存在针对不可拷贝迭代器的非const重载——当迭代器不满足copyable约束时,只能在非const的subrange对象上调用begin(),这个特性是其他类pair类型没有的,最初的标准设计没有考虑到这个特殊场景。
是否遗漏了另外两个重载
是的,C++20的初始标准版本确实遗漏了subrange&(非const左值引用)和const subrange&&(const右值引用)的std::get重载。你遇到的报错就是这个问题的典型表现:非const左值的subrange对象调用std::get<0>时,只能匹配到const subrange&的重载,而当迭代器不可拷贝时,const版本的begin()不满足约束,因此编译失败。
属于标准缺陷还是有意设计
这是明确的标准缺陷,对应的缺陷报告编号为LWG 3482,该问题已经在C++23标准中被修复,修复方案就是补充了缺失的两个std::get重载:
template<size_t N, class I, class S, subrange_kind K> requires (N < 2) constexpr auto get(subrange<I, S, K>& r); template<size_t N, class I, class S, subrange_kind K> requires (N < 2) constexpr auto get(const subrange<I, S, K>&& r);
补充重载后,非const左值的subrange会匹配到对应非const左值的重载,调用非const版本的begin(),示例代码就可以正常编译了。
内容的提问来源于stack exchange,提问作者康桓瑋
相关产品推荐
相关产品推荐

