gpt4 book ai didi

c++ - boost 模拟 C# 的 IEnumerable 的方式?

转载 作者:行者123 更新时间:2023-11-30 02:41:46 26 4
gpt4 key购买 nike

在 C# 中,我可以执行以下操作

class MyClass {
private List<int> lst;
public IEnumerable<int> Numbers { get { return lst; } }
}

这具有让公众只读访问 lst 的效果,而不会将 List 成员变量暴露给公众。例如,类的用户可以写

foreach (var n in myClass.Numbers) { /* do something with the values * / };

但他们不能更改列表或以相反的顺序遍历它。这使我有可能稍后更改实现,而无需使用该类破坏代码。

我想用 C++ 做一些类似的事情:

class MyClass {
std::vector<int> lst;
public:
/* ???? */ getNumbers () const { return /* ??? */ lst; }
};

// I want to be able to write the following
auto rng = myClass.getNumbers ();
auto b = begin (rng);
auto e = end (rng);
// now b and e should be readonly (!) forward (!) iterators

我不关心编译时依赖性,即我不想使用 any_range。但我这样做想在我的代码中明确表示我只保证只读转发行为。

最佳答案

你可以派生一个迭代器类型

template <typename Base>
struct const_forward_iterator : public Base {
using base_type = Base;
using iterator_type = const_forward_iterator;
using iterator_category = std::forward_iterator_tag;

const_forward_iterator& operator+=(typename Base::difference_type) = delete;
const_forward_iterator& operator-=(typename Base::difference_type) = delete;
const_forward_iterator operator+ (typename Base::difference_type) = delete;
const_forward_iterator operator- (typename Base::difference_type) = delete;

const_forward_iterator(base_type it) : base_type(it) {}
};

并以此为基础建立一个简单的范围

template <typename it>
struct range : std::pair<it,it> {
range(it b, it e) : std::pair<it,it>(b,e) {}

it begin() const { return this->first; }
it end() const { return this->second; }
};

利润:

using iterator_type = const_forward_iterator<std::vector<int>::const_iterator>;
range<iterator_type> getNumbers() const { return { lst.cbegin(), lst.cend() }; }

Live On Coliru

#include <vector>
#include <iterator>

namespace detail {
template <typename Base>
struct const_forward_iterator : public Base {
using base_type = Base;
using iterator_type = const_forward_iterator;
using iterator_category = std::forward_iterator_tag;

const_forward_iterator& operator+=(typename Base::difference_type) = delete;
const_forward_iterator& operator-=(typename Base::difference_type) = delete;
const_forward_iterator operator+ (typename Base::difference_type) = delete;
const_forward_iterator operator- (typename Base::difference_type) = delete;

const_forward_iterator(base_type it) : base_type(it) {}
};

template <typename it>
struct range : std::pair<it,it> {
range(it b, it e) : std::pair<it,it>(b,e) {}

it begin() const { return this->first; }
it end() const { return this->second; }
};
}

class MyClass {
std::vector<int> lst { 1, 3, 77, 42 };
public:

using iterator_type = detail::const_forward_iterator<std::vector<int>::const_iterator>;

detail::range<iterator_type> getNumbers() const { return { lst.cbegin(), lst.cend() }; }
};

#include <iostream>

int main()
{
MyClass o;

for (auto i : o.getNumbers())
std::cout << i << " ";

auto numbers = o.getNumbers();
//numbers.first += 2; error: use of deleted function
}

输出

1 3 77 42 

当然,您可以分解代码以便重用位,但这是作为一个独立的 PoC

关于c++ - boost 模拟 C# 的 IEnumerable 的方式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27713503/

26 4 0