1

Example:

SomeType bar::foo() const {
  SomeType retVal;
  for (auto i = 0u; i < 10; ++i) {
    retVal = boost::range::join(retVal, m_someDataContainer.equal_range(i));
  }
  return retVal;
}


Lets say, for simplicity, the m_someDataContainer and the bar class are defined as following:

typedef boost::multi_index_container<
    int, bmi::indexed_by<bmi::hashed_unique<bmi::tag<struct someTag>,
                                           bmi::identity<int>>>> Data;
class bar {
public:
  SomeType foo() const;

private:
  Data m_someDataContainer;
};

The questions are: How do I figure out the return type of foo() and how do I join these ranges without using boost::any_range

EDIT1: Looks like it is quite impossible, calling join in loop on previous joined value makes the result type a nested type of joined_range of joined_range of joined_range ... and so on, which, I guess cannot be deduced easily if at all

kreuzerkrieg
  • 3,009
  • 3
  • 28
  • 59
  • to some extent - VS2012 – kreuzerkrieg Feb 04 '15 at 16:31
  • I don't know how much C++11 does VS2012 support, but if it has trailing return type and `auto`, you're pretty much set. – jrok Feb 04 '15 at 16:33
  • And how I supposed to declare the retVal local variable? – kreuzerkrieg Feb 04 '15 at 16:35
  • 1
    `auto retVal = /* first boost::join call */ ;` Then adjust the loop accordingly. EDIT Nevermind, you're using `retVal` in the call itself. :/ – jrok Feb 04 '15 at 16:36
  • huh, quite ugly solution, but may work. EDIT: you damn right, thats the problem, the first call to join – kreuzerkrieg Feb 04 '15 at 16:38
  • Hehe. I [**knew** you would come to tackle this problem](http://stackoverflow.com/questions/27012395/appending-ranges-in-loop#comment42553452_27012781) for real once. Not three months :) – sehe Feb 05 '15 at 00:12
  • yeah, just wanted to update that question - any_range is no-no solution. and of course none of tests revealed the problem, it popped out of nowhere in production :) – kreuzerkrieg Feb 05 '15 at 04:00

1 Answers1

1

Since you have (or can generate) a range of ranges of the same type, you need a flattening range. Using Jesse Good's flatten from Iterating over a range of ranges:

return flatten(boost::irange(0, 10)
    | boost::adaptors::transform(
        [this](int i){ return m_someDataContainer.equal_range(i); }));

Unfortunately I think that this will probably leave the iterators dangling, so you should adapt the flatten there to copy the range into its return value; you can do this with multiple inheritance:

template<typename Cont> using FlatIteratorRange
    = boost::iterator_range<flattening_iterator<decltype(std::declval<Cont>().begin())>;

template<typename Cont>
struct FlatRange
    : private Cont
    , public FlatIteratorRange<Cont>
{
    explicit FlatRange(Cont const& c)
        : Cont(c)
        , FlatIteratorRange<Cont>(
            flat_iter(this->Cont::begin(), this->Cont::end()),
            flat_iter(this->Cont::end()));
    {}
}

template<typename Cont>
auto flatten(Cont const& c) -> FlatRange<Cont>
{
    return FlatRange<Cont>(c);
}
Community
  • 1
  • 1
ecatmur
  • 152,476
  • 27
  • 293
  • 366
  • sounds interesting, will check it tomorrow. I was hopping I'm missing something fundamental in joined_range usage and there is a simple solution. Looks like I was wrong. – kreuzerkrieg Feb 04 '15 at 18:45