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

C++20自定义容器迭代器无法适配std::ranges算法问题排查

问题描述

我编写了如下简化代码,实现了一个整数范围容器,希望配合各类std标准算法使用。目前我正尝试升级代码以使用C++20的ranges版本算法,从而省略所有显式的begin()和end()调用。在下方代码中,std::any_of可正常配合我的自定义容器和迭代器运行,但std::ranges::any_of却无法通过编译。

#include <iostream>
#include <algorithm>

class Number_Iterator {
    public:
        using iterator_category = std::input_iterator_tag;
        using value_type = int;
        using difference_type = int;
        using pointer = int*;
        using reference = int&;

        Number_Iterator(int start) noexcept : value(start) {}
        Number_Iterator& operator++() noexcept { ++value; return *this; }
        bool operator==(const Number_Iterator& other) const noexcept = default;
        int operator*() const noexcept { return value; }

    private:
        int value;
};

class Numbers {
    public:
        Numbers(int begin, int end) noexcept : begin_value(begin), end_value(end) {}
        Number_Iterator begin() const noexcept { return {begin_value}; }
        Number_Iterator end() const noexcept { return {end_value}; }

    private:
        int begin_value;
        int end_value;
};

int main() {
    const auto set = Numbers(1, 10);
    const auto multiple_of_three = [](const auto n) { return n % 3 == 0; };

    // Compiles and runs correctly
    if(std::any_of(set.begin(), set.end(), multiple_of_three)) {
        std::cout << "Contains multiple of three.\n";
    }

    // Does not compile
    if(std::ranges::any_of(set, multiple_of_three)) {
        std::cout << "Contains multiple of three.\n";
    }

    return 0;
}

我在开启/std:c++20编译选项的Visual Studio 2019(16.11.15版本)中编译上述代码,得到如下报错信息:

Source.cpp(42,21): error C2672: 'operator __surrogate_func': no matching overloaded function found
Source.cpp(42,7): error C7602: 'std::ranges::_Any_of_fn::operator ()': the associated constraints are not satisfied
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\algorithm(1191): message : see declaration of 'std::ranges::_Any_of_fn::operator ()'

我尝试查阅std::ranges::_Any_of_fn::operator()的声明定义,反而对此更加困惑。
请问我还需要补充哪些实现,才能让std::ranges系列算法正常适配我的自定义容器?


补充说明:我实际需要迭代的对象是国际象棋棋盘上的格子,这类对象通过整数表示,和上述示例代码的逻辑差异极小。

问题原因

你的自定义迭代器不符合C++20 ranges对输入迭代器的概念约束。传统std::any_of没有严格的编译期概念校验,只要调用的接口存在就能编译运行,但ranges算法会在编译期严格校验迭代器是否满足对应概念要求,不满足就会直接报约束不满足的错误。核心问题有两个:

  • 缺失后置自增运算符operator++(int):C++20输入迭代器概念明确要求同时实现前置、后置自增,你的迭代器只实现了前置版本。
  • 类型定义与实际行为不匹配:你的operator*直接返回int纯右值,但内部定义的reference类型是int&,二者不一致,导致迭代器的可间接读取约束校验失败。
修复方案

方案1:修正迭代器定义,适配ranges概念要求

针对你的迭代器场景(解引用返回整数纯右值,不需要修改元素),补全缺失接口、修正错误的类型定义即可,不需要修改Numbers容器的代码:

class Number_Iterator {
    public:
        // C++20迭代器通过iterator_concept标识迭代器类别
        using iterator_concept = std::input_iterator_tag;
        using value_type = int;
        using difference_type = int;
        // 解引用返回int纯右值,reference不要定义为不存在的int&
        using reference = int;
        using pointer = const int*;

        Number_Iterator(int start) noexcept : value(start) {}
        // 前置自增
        Number_Iterator& operator++() noexcept { ++value; return *this; }
        // 补全ranges要求的后置自增
        Number_Iterator operator++(int) noexcept {
            auto temp = *this;
            ++value;
            return temp;
        }
        bool operator==(const Number_Iterator& other) const noexcept = default;
        int operator*() const noexcept { return value; }

    private:
        int value;
};

修改完成后std::ranges::any_of即可正常编译运行。你实际场景中的棋盘格迭代器如果也是解引用返回值类型,按同样逻辑修改即可。

方案2:直接使用标准库提供的范围工具,无需自定义迭代器

你的需求本质是遍历连续整数区间,C++20已经提供了现成的std::views::iota视图可以直接实现相同功能,不需要自行编写迭代器和容器:

#include <iostream>
#include <algorithm>
#include <ranges>

int main() {
    // 生成[1,10)的整数序列视图
    auto set = std::views::iota(1, 10);
    const auto multiple_of_three = [](const auto n) { return n % 3 == 0; };

    if(std::ranges::any_of(set, multiple_of_three)) {
        std::cout << "Contains multiple of three.\n";
    }
    return 0;
}

内容的提问来源于stack exchange,提问作者Mark H

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 19:27:26