我想在我的类中隐藏一个矢量字段,但允许通过其元素轻松迭代,但没有别的。这样班级的客户就可以做到
for (auto element : foo.getElements()) { }
但不是
foo.getElements()[42];
是否有一些简单的方法可以实现此目的而不会创建新的混淆类型?
答案 0 :(得分:14)
我不能说什么是“新混淆型”。但这足以满足基于范围的for
:
template<typename Iter>
class iterator_range
{
public:
iterator_range(Iter beg, Iter end) : beg_(beg), end_(end) {}
Iter begin() const {return beg_;}
Iter end() const {return end_;}
private:
Iter beg_, end_;
};
范围TS增加了构成“范围”的复杂性,但这对于基于范围的for
来说已经足够了。所以你的foo.getElements
函数看起来像这样:
auto getElements()
{
return iterator_range<vector<T>::iterator>(vec.begin(), vec.end());
}
auto getElements() const
{
return iterator_range<vector<T>::const_iterator>(vec.begin(), vec.end());
};
答案 1 :(得分:5)
您可以使用高阶函数来仅显示迭代功能:
class something
{
private:
std::vector<item> _items;
public:
template <typename F>
void for_items(F&& f)
{
for(auto& i : _items) f(i);
}
};
用法:
something x;
x.for_items([](auto& item){ /* ... */ });
这种模式的优点是:
std::vector
更改为其他内容。要完全正确且迂腐,您必须公开for_items
的三个不同的 ref-qualified 版本。 E.g:
template <typename F>
void for_items(F&& f) & { for(auto& i : items) f(i); }
template <typename F>
void for_items(F&& f) const& { for(const auto& i : items) f(i); }
template <typename F>
void for_items(F&& f) && { for(auto& i : items) f(std::move(i)); }
以上代码确保const
- 正确性,并允许在something
实例为临时时移动元素。
答案 2 :(得分:3)
这是一种基于代理的方法(虽然我不确定新类型是否符合不混淆的要求)。
template<class Container> class IterateOnlyProxy {
public:
IterateOnlyProxy(Container& c) : c(c) {}
typename Container::iterator begin() { return c.begin(); }
typename Container::iterator end() { return c.end(); }
private:
Container& c;
};
代理用作getElements()
方法的返回类型,
class Foo {
public:
using Vec = std::vector<int>;
using Proxy = IterateOnlyProxy<Vec>;
Proxy& getElements() { return elementsProxy; }
private:
Vec elements{4, 5, 6, 7};
Proxy elementsProxy{elements};
};
并且客户端代码可以遍历底层容器,但是关于它。
Foo foo;
for (auto element : foo.getElements())
std::cout << element << std::endl;
foo.getElements()[42]; // error: no match for ‘operator[]’
答案 3 :(得分:0)
如果要在类中隐藏矢量字段但仍然基于for循环执行范围,则可以根据vector::iterator
添加自己的迭代器。
一个简单(不完整)的例子可能是:
#include <iostream>
#include <vector>
class Foo
{
public:
class iterator
{
public:
iterator(std::vector<int>::iterator n) : p(n) {}
bool operator==(iterator& rhs) { return p == rhs.p; }
bool operator!=(iterator& rhs) { return p != rhs.p; }
iterator& operator++() { p++; return *this; }
int& operator*() { return *p; }
private:
std::vector<int>::iterator p;
};
iterator begin() { return iterator(v.begin()); }
iterator end() { return iterator(v.end()); }
private:
std::vector<int> v {1, 2, 3, 4, 5};
};
int main() {
Foo foo;
for(auto y : foo) std::cout << y << std::endl;
return 0;
}