说我有
class Value;
class Key;
class MyClass {
private:
std::map<Key,Value> my_map;
....
}
在myclass方法的内部,我有一种非常方便的方法来通过my_map的值迭代
来迭代 for( auto& value: my_map | boost::adaptors::map_values) {
...
}
但是,我想拥有一种基本上输出的myllass方法 my_map |boost ::适配器:: map_values并允许MyClass方法以外的方便价值迭代。如何声明这种方法?我需要实现某种伪容器和相应的迭代器还是有快捷方式?
基本上,您有两个不错的选择。您可以通过使用BOOST的any_range
为用户提供良好的脱钩界面,否则,如果需要最佳性能,则可以使用C 11声明类型为客户端直接访问适用的范围。在第一种情况下,如果您更改实施,则客户将不必更改,但这是以额外的重定向代价的。
使用any_range
:
#include <boost/range.hpp>
#include <map>
#include <boost/range/adaptor/map.hpp>
#include <boost/range/any_range.hpp>
class Foo
{
std::map<int, int> my_map;
boost::any_range<int, boost::forward_traversal_tag, int&, std::ptrdiff_t> Values()
{ return my_map | boost::adaptors::map_values; }
};
给予直接访问(尴尬的语法是因为您需要VS2013,该VS2013不支持类范围内未评估的上下文中的成员变量):
#include <boost/range.hpp>
#include <map>
#include <boost/range/adaptor/map.hpp>
class Foo
{
std::map<int, int> my_map;
auto Values() -> decltype(my_map | boost::adaptors::map_values)
{ return my_map | boost::adaptors::map_values; }
};
使用伪容器或迭代器适配器,例如boost :: iterator_range。尽管使用适当的适配器(例如iterator_range)在理论上会更正确和通用,并且不会违反最少知识的原理,但您可能会因为额外的间接而避免使用它,或者因为您的迭代器通常仅仅是因为您的迭代器通常是仅仅是因为单通行范围而不是前向范围。
因此,如果您想直接使用改编范围,则可以使用decltype
推断适配器已经返回的迭代器类型:
#include <iostream>
#include <map>
#include <boost/range/adaptor/map.hpp>
class A {
std::map<int,int> my_map = { {0, 1}, {2, 3} };
public:
decltype(my_map | boost::adaptors::map_values)
values() { return my_map | boost::adaptors::map_values; }
};
int main() {
for (const auto& v : A().values())
std::cout << "v = " << v << std::endl;
return 0;
}
/* Output:
v = 1
v = 3
*/
,如果您希望暴露值是const成员函数,则略微复杂:
class A {
...
decltype(const_cast<const std::map<int,int>&>(my_map) | boost::adaptors::map_values)
values() const { return my_map | boost::adaptors::map_values; }
}