[range] range metafunctions and reference types
Hello, 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 on. 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? Thanks, Nate.
Den 30-07-2011 01:13, Nathan Ridge skrev:
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?
This is indeed annoying. I guess we could do the following for all meta-functions: template< class T > struct meta<T&> : meta<T> {} -Thorsten
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?
allthough we should probably be careful here; maybe its better just to say template< class R > auto some_fun( R&& r ) -> decltype(boost::begin(r)); -Thorsten
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?
allthough we should probably be careful here; maybe its better just to say
template< class R > auto some_fun( R&& r ) -> decltype(boost::begin(r));
What do we need to be careful about? IMO this is a case where writing out the return type (range_iterator<R>::type) is more readable than using decltype. Regards, Nate
participants (2)
-
Nathan Ridge
-
Thorsten Ottosen