C++中用于基于范围的for循环的虚拟范围初始化器

编程语言 2026-07-10

我想要一个抽象类范围初始化器,可以在基于范围的for循环中使用。这种东西真的可能吗?目前我只看到可以用非抽象类来实现。类 TestRange 充当迭代器。TestRangeBTestRangeC 的内部行为不同。

#include <array>
#include <iostream>

class A {
public:
    class TestRange {
    public:
        friend bool operator==(const TestRange& lhs, const TestRange& rhs) {
            return lhs.getId() == rhs.getId();
        }
        friend bool operator!=(const TestRange& lhs, const TestRange& rhs) {
            return !(lhs == rhs);
        }
        virtual int operator*() = 0;
        int index = 0;
        virtual int getId() const = 0;
    };
    class TestRangeInitializer {
    public:
        virtual TestRange* begin() = 0;
        int end() { return -1; }
    };
    virtual TestRangeInitializer* getTestRangeInitializer() = 0;
};

class B : public A {
    class TestRangeB : public TestRange {
    public:
        int getId() const override {
            return index < data.size() ? data[index] : -1;
        }
        int operator*() override { return getId(); }
    private:
        std::array<int, 3> data = {1, 3, 5};
    };
    class TestRangeInitializerB : public TestRangeInitializer {
        TestRange* begin() override {
            return new TestRangeB();
        }
    };
    TestRangeInitializer* getTestRangeInitializer() {
        return new TestRangeInitializerB();
    };
};

// Class C : public A;

要使用的地方:

int main() {
    A* obj = new B();
    for (int i : obj->getTestRangeInitializer()) {
        std::cout << i << ' ';
    }
}

https://godbolt.org/z/z4M9cEEsx

解决方案

你不能合理地从 beginend 返回指针,因为你不能为两种指针类型提供 == 的重载,也不能从这样的指针解引用得到一个 int,而 for 被定义为使用。

如果你有子类 BC,它们使用不同的容器,你可以在 A 中为 virtual boost::any_range<int> getTestRangeInitializer() = 0 提供实现。不过,可能更快的做法是把值拷贝到一个 std::vector<int>,然后返回那个。

class A {
public:
virtual std::vector<int> getTestRangeInitializer() = 0;
};

class B : public A {
std::list<int> data;
public:
std::vector<int> getTestRangeInitializer() override {
    return { std::from_range, data };
}
};

class C : public A{
std::set<int> data;
public:
std::vector<int> getTestRangeInitializer() override {
    return { std::from_range, data };
};
};
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章