为何使用std::views::chunk编译时出现‘无法分解不可访问成员’错误?
为什么
std::views::iota('a', 'g'+1)配合chunk视图编译失败,但直接遍历却正常? 正常编译的代码
#include <ranges> #include <iostream> int main() { const auto r = std::views::iota('a', static_cast<char>('g' + 1)); for(const auto& [start, end] : r | std::views::chunk(3u)) { for(auto it = start; it != end; ++it) { std::cout << *it << " "; } std::cout << "\n"; } return 0; }
输出:
a b c d e f g
修改后编译失败的代码
将r的定义改为:
const auto r = std::views::iota('a', 'g' + 1);
GCC 13报错:
chunk.cpp:13:21: error: cannot decompose inaccessible member ‘std::ranges::take_view<std::ranges::subrange<std::ranges::iota_view<char, int>::_Iterator, std::ranges::iota_view<char, int>::_Sentinel, std::ranges::subrange_kind::unsized> >::_M_base’ of ‘const std::ranges::take_view<std::ranges::subrange<std::ranges::iota_view<char, int>::_Iterator, std::ranges::iota_view<char, int>::_Sentinel, std::ranges::subrange_kind::unsized> >’ 13 | for(const auto& [start, end] : r | std::views::chunk(3u)) { | ^~~~~~~~~~~~ In file included from chunk.cpp:1: /usr/include/c++/13/ranges:2153:11: note: declared private here 2153 | _Vp _M_base = _Vp(); | ^~~~~~~
奇怪的对比:直接遍历却正常
下面的代码可以正常编译运行:
#include <ranges> #include <iostream> int main() { const auto r = std::views::iota('a', 'g' + 1); for(const auto& val : r) { std::cout << val << " "; } std::cout << "\n"; return 0; }
原因解析
- 参数类型差异导致
iota_view的特性变化'g'是char类型,'g' + 1会触发整数提升,结果是int类型。因此std::views::iota('a', 'g'+1)生成的是std::ranges::iota_view<char, int>——这个视图的起始类型是char,终止类型是int,属于非 Sized 范围(无法直接计算总元素个数)。
而强转成static_cast<char>('g'+1)后,iota_view的起始和终止类型都是char,属于Sized 范围。
chunk视图对不同范围的处理逻辑不同
- 当输入是Sized 范围时,
chunk会将范围分割为多个std::ranges::subrange对象,subrange支持结构化绑定(它有公开的可分解成员),所以你可以用[start, end]直接分解。 - 当输入是非 Sized 范围时,
chunk无法预先知道总长度,只能每次生成一个std::ranges::take_view对象来取N个元素。而GCC实现的take_view内部的核心成员_M_base是私有属性,C++的结构化绑定会尝试分解对象的所有成员,访问私有成员时就触发了编译错误。
- 直接遍历不受影响的原因
直接遍历iota_view<char, int>时,只需要它的迭代器和哨兵,不需要计算总长度,也不需要分解任何视图对象,因此不会触发对私有成员的访问,自然可以正常编译运行。
内容的提问来源于stack exchange,提问作者Alberto Santini
相关产品推荐
相关产品推荐

