C++:在抽象类中定义 begin() 和 end()

问题描述 投票:0回答:1

我在开发优化求解器时遇到了问题Uno
我定义了一个抽象类

Collection
,它表示一组可以迭代的整数:一个向量、一个数值范围(一组整数 {a, a+1, ..., b})、现有的符号串联整数集等
我有一个函数(例如)
get_bounded_variables()
,其返回类型为
const Collection&
,我可以使用自定义
for_each
函数对其进行迭代(请参阅此处):

problem.get_bounded_variables().for_each([&](size_t index) {
   ...
});

不同类型的问题对

get_bounded_variables()
的定义不同。

它确实有效,但我宁愿使用更经典的语法和基于范围的 for 循环。
现在,我的问题是,如果我想写这样的东西:

for (size_t index: problem.get_bounded_variables()) {
   ...
}

我需要为抽象

begin()
定义
end()
Collection
函数,但它的子类具有不同的迭代器类型。 所以在那一点上我陷入了困境,我不确定这是否可行。我刚刚读到有关使用自由函数
begin(const Collection&)
end(const Collection&)
,但我认为这对我没有帮助。
感谢您的帮助,

查理

c++ templates iterator abstract-class
1个回答
0
投票

您正在寻找的技术称为“类型擦除”。由于许多技术细节,STL 兼容的类型擦除迭代器的完整实现很长,但对于基于 for 的循环,实现

operator*
operator++
operator!=
就足够了。这是一个最小的例子:
class Iterator {
public:
    template<class It>
    Iterator(It it) : impl_(std::make_unique<Impl<It>>(it)) {}

    std::size_t operator*() const {
        return impl_->deref();
    }

    Iterator& operator++() {
        impl_->increment();
        return *this;
    }

    friend bool operator!=(const Iterator& it1, const Iterator& it2) {
        return !it1.impl_->equal(*it2.impl_);
    }

private:
    class Base {
    public:
        virtual ~Base() = default;

        virtual std::size_t deref() const = 0;
        virtual void increment() = 0;
        virtual bool equal(const Base&) const = 0;
    };

    template<class It>
    class Impl : public Base {
    public:
        Impl(It it) : it_(it) {}

        std::size_t deref() const override {
            return *it_;
        }

        void increment() override {
            ++it_;
        }

        bool equal(const Base& other) const override {
            return it_ == dynamic_cast<const Impl&>(other).it_;
        }

    private:
        It it_;
    };

private:
    std::unique_ptr<Base> impl_;
};

这是一个如何使用这个类型擦除迭代器的示例:

class Collection { public: // ... virtual Iterator begin() const = 0; virtual Iterator end() const = 0; }; class VecCollection: public Collection { public: // ... Iterator begin() const override { return vec_.begin(); } Iterator end() const override { return vec_.end(); } private: std::vector<std::size_t> vec_; }; void print(const Collection& c) { for (std::size_t i : c) std::cout << i << ' '; } int main() { VecCollection vc(std::vector<std::size_t>{1, 2, 3, 4, 5}); print(vc); }

演示

© www.soinside.com 2019 - 2024. All rights reserved.