What are the benefits of using boost :: any_range?

advertisements

What are the benefits of using boost::any_range? Here is an example:

typedef boost::any_range<
    int
  , boost::forward_traversal_tag
  , int
  , std::ptrdiff_t
> integer_range;

void display_integers(const integer_range& rng)
{
    boost::copy(rng,
                std::ostream_iterator<int>(std::cout, ","));

    std::cout << std::endl;
}

int main(){
    std::vector<int> input{ ... };
    std::list<int> input2{ ... };
    display_integers(input);
    display_integers(input2);
}

But the same functionality with more efficiency can be achieved with a template parameter, which satisfies the ForwardRange concept:

template <class ForwardRange>
void display_integers(const ForwardRange& rng)
{
    boost::copy(rng,
                std::ostream_iterator<int>(std::cout, ","));

    std::cout << std::endl;
}

So I am searching for scenarios when it is worth to use any_range. Maybe I am missing something.


This technique is called Type Erasure. There is full article describing pros and cons on example of any_iterator: On the Tension Between Object-Oriented and Generic Programming in C++.


It is possible to hide implementation/defintion of

void display_integers(const integer_range& rng)

in separate file/library.

But in case of

template <class ForwardRange>
void display_integers(const ForwardRange& rng)

you have to provide source code to users (or at least make explicit instantiations somewhere).


Moreover, in first case display_integers will be compiled only once, but in second - it will be compiled for every type of passed range.


Also, you may have

integer_range rng;

somewhere. And during lifetime of rng - you may assign ranges of different types to it:

vector<int> v;
list<int> l;
integer_range rng;
rng = v;
rng = l;


The biggest disadvantage of type erasure is runtime cost - all operations are virtual, and can not be inlined (easily).


P.S. another famous example of type erasure is std::function