You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何使用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;
}

原因解析

  1. 参数类型差异导致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 范围。

  1. chunk视图对不同范围的处理逻辑不同
  • 当输入是Sized 范围时,chunk会将范围分割为多个std::ranges::subrange对象,subrange支持结构化绑定(它有公开的可分解成员),所以你可以用[start, end]直接分解。
  • 当输入是非 Sized 范围时,chunk无法预先知道总长度,只能每次生成一个std::ranges::take_view对象来取N个元素。而GCC实现的take_view内部的核心成员_M_base是私有属性,C++的结构化绑定会尝试分解对象的所有成员,访问私有成员时就触发了编译错误。
  1. 直接遍历不受影响的原因
    直接遍历iota_view<char, int>时,只需要它的迭代器和哨兵,不需要计算总长度,也不需要分解任何视图对象,因此不会触发对私有成员的访问,自然可以正常编译运行。

内容的提问来源于stack exchange,提问作者Alberto Santini

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 21:53:18