Boost logo

Boost Users :

Subject: [Boost-users] [range] range metafunctions and reference types
From: Nathan Ridge (zeratul976_at_[hidden])
Date: 2011-07-29 19:13:18


The range metafunctions currently do not work on range reference types.

For example, the following:

#include <vector>
#include <boost/range/metafunctions.hpp>

typedef boost::range_iterator<std::vector<int>&>::type iter_t;

Fails with the errors:

In file included from lib/boost/boost/range/iterator.hpp:23:0,
                 from lib/boost/boost/range/metafunctions.hpp:18,
                 from test4.cpp:2:
lib/boost/boost/mpl/eval_if.hpp: In instantiation of 'boost::mpl::eval_if_c<false, boost::range_const_iterator<std::vector<int>&>, boost::range_mutable_iterator<std::vector<int>&> >':
lib/boost/boost/range/iterator.hpp:72:63:   instantiated from 'boost::range_iterator<std::vector<int>&>'
test4.cpp:4:49:   instantiated from here
lib/boost/boost/mpl/eval_if.hpp:60:31: error: no type named 'type' in 'boost::mpl::eval_if_c<false, boost::range_const_iterator<std::vector<int>&>, boost::range_mutable_iterator<std::vector<int>&> >::f_ {aka struct boost::range_mutable_iterator<std::vector<int>&>}'

This behaviour is OK when you are doing things like this:

template <typename Range>
typename range_iterator<Range>::type some_function(const Range& r) { ... }

because when called with a "const vector<T>&" argument, template argument deduction
will deduce "Range" to be just "vector<T>", and this is what we call the metafunction

Likewise, if some_function has a non-const version that takes a "Range&" argument,
it works fine too.

But in C++0x, rvalue references allow us to kill two birds with one stone and have
just one function that accepts both const and non-const references:

template <typename Range>
typename range_iterator<Range>::type some_function(Range&& r) { ... }

However, the template argument deduction rules for rvalue references are different:
if the function is called with a "const vector<T>&" parameter, "Range" will be
deduced as "const vector<T>&", i.e. the reference is preserved.

But now range_iterator gives an error as indicated above, so we have to do something
awkward and verbose like this:

template <typename Range>

typename range_iterator<typename remove_reference<Range>::type>::type some_function(Range&& r) { ... }

Could the range metafunctions be modified to accept range reference parameters and
remove the reference themselves?


Boost-users list run by williamkempf at, kalb at, bjorn.karlsson at, gregod at, wekempf at