条件是:
// A hierarchy
struct Base {
virtual void everyone_has_this() = 0;
};
struct DA : Base {
void everyone_has_this() override {...}
};
struct DB : Base {
void everyone_has_this() override {...}
void only_db_has_this() {...}
};
// And some vectors
vector<DA> das (3);
vector<DB> dbs (2);
我希望能够使用类似的东西:
// Foreach all of them in one loop
for(Base& o : view_as_one<Base>(das, dbs)) {
o.everyone_has_this();
}
// Or just several types of them
for(DB& o : dbs) {
db.only_db_has_this();
}
问题是:有可能吗?
如果没有,一个循环的其他方法是什么,而不是每个容器?
重要的是,我不想摆脱隔离和存储的重要性。
如果我使用单个基本指针容器,那么dynamic_cast就可以工作,但是它会涉及在每次迭代时检查类型,目标是将所有对象存储在有名的存储中。
编辑:替代解决方案如果提升不是选项或视图不够的话 虽然我喜欢m.s.的解决方案,因为他完全实现了我要求的界面,我发现我想要的这个界面实际上并不灵活(不能使用擦除 - 删除)。 所以这是一个不同的方法:
for_each_in_tuple(std::tie(das, dbs), [](auto& cont){
for(auto& obj : cont) {
// do what you want
}
// or even
cont.erase(std::remove_if(begin(cont), end(cont), [](auto& obj) {
// also do what you want
}, end(cont));
});
auto&
)。<tuple>
=&gt;没有提升&amp;编译得更快。答案 0 :(得分:1)
可以使用boost::transform_iterator
和boost::join
来实现。
以下代码使用Luc Dantons variadic join实现:
#include <vector>
#include <tuple>
#include <iostream>
#include <utility>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/range/join.hpp>
#include <boost/range/iterator_range.hpp>
namespace ns {
// for ADL purposes
using std::begin;
using std::end;
struct join_type {
template<class C>
auto operator()(C&& c) const
-> decltype(boost::make_iterator_range(begin(c), end(c)))
{
return boost::make_iterator_range(begin(c), end(c));
}
template<typename First, typename Second, typename... Rest>
auto operator()(First&& first, Second&& second, Rest&&... rest) const
-> decltype( (*this)(boost::join(boost::make_iterator_range(begin(first), end(first)), boost::make_iterator_range(begin(second), end(second))), std::forward<Rest>(rest)...) )
{
return (*this)(boost::join(boost::make_iterator_range(begin(first), end(first)), boost::make_iterator_range(begin(second), end(second))), std::forward<Rest>(rest)...);
}
};
constexpr join_type join {};
} // ns
template <typename T>
struct ReturnTRef
{
T& operator()(T& x) const { return x;};
};
template <typename T, typename Tuple, std::size_t... Indices>
auto view_as_one_impl(Tuple&& tuple, std::index_sequence<Indices...>)
{
ReturnTRef<T> returnTRef;
return ns::join(boost::make_iterator_range(boost::make_transform_iterator(begin(std::get<Indices>(tuple)), returnTRef), boost::make_transform_iterator(end(std::get<Indices>(tuple)), returnTRef))...);
}
template <typename B, typename... Args>
auto view_as_one(Args&&... args)
{
return view_as_one_impl<B>(std::forward_as_tuple<Args...>(args...), std::index_sequence_for<Args...>{});
}
struct Base {virtual ~Base(){}; virtual void talk() = 0;};
struct DA : Base {void talk() override { std::cout << "DA" << std::endl;} };
struct DB : Base {void talk() override { std::cout << "DB" << std::endl;} };
int main()
{
std::vector<DA> das(3);
std::vector<DB> dbs(2);
for(Base& x : view_as_one<Base>(das, dbs))
{
x.talk();
}
}
<强>输出强>
DA
DA
DA
DB
DB
答案 1 :(得分:0)
是的,有可能。只需编写一些代码即可。
只需实现view_as_one
即可满足C ++库容器的要求;或至少实现此功能所需的最低要求。它的构造函数存储对成分,底层容器的引用。将其iterator
类实现为按顺序迭代每个组成容器。实施view_as_one<T>::begin()
和view_as_one<T>::end()
。完成。
我希望将此作为典型的高级C ++&#34;中的家庭作业。编程课。