Interface with BOOST Range

235 Views Asked by At

Motivation & Approach

I'm writing a small library which provides an AST structure & some algorithms to navigate over it. In simple, the AST has the following structure:

struct ASTNode;
using tBranch = std::vector<ASTNode>;
struct ASTNode
{
   /* some data */
   tBranch childs;
};
struct AST
{
   std::vector<tBranch> root;   // All branches
};

I would like to define algorithms as:

using tRange = boost::some_range_type<const tBranch::type>;   // which range type should I use?
tRange filter_by_type(tRange range, const eNodeType& type);

So the main representation of the AST branches & branches parts (in algorithms) are wrapped in boost::range-s. Consequently, all functions return ranges as well.


Example

The main question why am I asking is issues with conversions. Here is brief example what I'm trying to do:

using tVector     = std::vector<int>;
using tBoostRange = boost::iterator_range<const tVector::value_type*>;

tBoostRange make_range(tVector& v)
{
   return boost::make_iterator_range( &v[0], &v[v.size()] );
}

tBoostRange get_odd_range(tVector& v1, tVector& v2)
{
   auto r1 = make_range(v1);
   auto r2 = make_range(v2);
   auto r3 = boost::range::join(r1, r2);
   
   /*
    * This return causes to error:
    * error: no viable conversion from returned value of type
    * 'filtered_range<(lambda at prog.cc:22:43),
    * boost::range::joined_range<boost::iterator_range<const int *>,
    * boost::iterator_range<const int *> > >' to function return type
    * 'tBoostRange' (aka 'iterator_range<const int *>')
    */
   return r3 | boost::adaptors::filtered( [](const auto& i){ return i % 2 != 0; } );
}

int main()
{
   auto v1 = tVector{ 1, 2, 3 };
   auto v2 = tVector{ 4, 5, 6 };
   auto r  = get_odd_range(v1, v2);
   
   for( const auto& i : r )
   {
      std::cout << i << std::endl;
   }
}

Question

What type of boost::ranges should I use in my lib in order to keep consistency across all functions. Is it possible to convert any ranges type to some universal type as boost::range algorithms do (I guess)?

Thanks in advance!

1

There are 1 best solutions below

1
On

any_range (in the Boost.Range library) will allow you to hide the differences between different ranges over the same type.

However, this information hiding comes at a cost: each increment and indirection requires a virtual function call (or similar), which not only is expensive in itself but also an impediment to the optimizer. It would be a good idea to assess whether consistency in return types justifies this cost.