Ну, конечно, есть. Разыменование итераторов, естественно, приведет к boost::variant<...>
ссылке или константной ссылке.
Однако это означает, что остальная часть кода должна учитывать варианты. И особенно используйте boost::static_visitor
для выполнения операций над вариантами.
EDIT
Легко!
struct Printer: boost::static_visitor<>
{
template <class T>
void operator()(T const& t) const { std::cout << t << std::endl; }
};
std::for_each(bag.begin(), bag.end(), boost::apply_visitor(Printer());
Обратите внимание, что при написании посетителя автоматически получается предикат для алгоритмов STL, миам!
Теперь для выдачи возвращаемого значения:
class WithReturn: boost::static_visitor<>
{
public:
WithReturn(int& result): mResult(result) {}
void operator()(Foo const& f) const { mResult += f.suprise(); }
void operator()(Bar const& b) const { mResult += b.another(); }
private:
int& mResult;
};
int result;
std::for_each(bag.begin(), bag.end(), boost::apply_visitor(WithReturn(result)));
РЕДАКТИРОВАТЬ 2:
Это легко, но на самом деле нужно немного потренироваться:)
Во-первых, отметим, что есть 2 разные операции: !=
и operate
struct PropertyCompare: boost::static_visitor<bool>
{
template <class T, class U>
bool operator()(T const& lhs, U const& rhs)
{
return lhs.property() == rhs.property();
}
};
struct Operate: boost::static_visitor<result_type>
{
result_type operator()(Foo const& lhs, Foo const& rhs);
result_type operator()(Foo const& lhs, Bar const& rhs);
result_type operator()(Bar const& lhs, Bar const& rhs);
result_type operator()(Bar const& lhs, Foo const& rhs);
};
for(it=list.begin(); it!=list.end();++it) {
for(it_2=list.begin(); it_2!=list.end();++it_2) {
if( !boost::apply_visitor(PropertyCompare(), *it, *it_2) ) {
result = boost::apply_visitor(Operate(), *it, *it_2));
}
}
}
Ибо здесь не все так хорошо, из-за этого if
. Это сработало бы, если бы вы могли как-то учесть if
в operate
.
Также обратите внимание, что я передаю не итераторы, а ссылки.