说我有
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) {
...
}
但是我希望有一个基本上输出的MyClass方法 my_map |提高::适配器:: map_values 并允许在MyClass方法之外进行方便的值迭代。我该如何申报这样的方法?我是否需要实现某种伪容器和相应的迭代器或者有一个快捷方式?
答案 0 :(得分:1)
基本上,你有两个不错的选择。您可以使用boost any_range
为用户提供一个很好的解耦接口,否则如果您需要最佳性能,您可以使用c ++ 11 decltypes让客户直接访问适应范围。在第一种情况下,如果更改实现,客户端将不必更改,但这需要额外的重定向。
使用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,它不支持类范围内未评估上下文中的成员变量):
#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; }
};
答案 1 :(得分:1)
使用伪容器或迭代器适配器(例如boost :: iterator_range)并非绝对必要。虽然理论上使用适当的适配器(如iterator_range)会更加正确和通用,并且不会违反应用于对象的principle of least knowledge,但您可能希望避免它因为额外的间接,或者可能因为您的迭代器通常只有单程范围,而不是前进范围。
因此,如果您希望直接使用适应范围,只需使用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; }
}