Boost logo

Boost :

Subject: Re: [boost] [Range] begin/end ADL issues in C++0x range-based for
From: Michel MORIN (mimomorin_at_[hidden])
Date: 2010-12-17 20:29:55


Dave Abrahams wrote:
> First, Michel, thanks for addressing this important matter. 2nd, I'm
> a wee bit worried about ODR issues. At first it looks like you're
> saying to define has_begin in namespace boost. Then your code seems
> to imply it's in namespace range_detail. I think the latter is
> probably OK, but not the former. The key thing is that the definition
> of boost::begin should not itself alter the result of has_begin for
> any given type.

Ah! It's the latter. I should have written as

#ifndef BOOST_NO_RANGE_BASED_FOR
namespace boost {
    using std::begin;

    namespace range_detail {
        // has_begin metafunction...
    }

    template <typename Range>
    inline typename boost::range_iterator<Range>::type
    begin(Range& rng, typename
disable_if<range_detail::has_begin<Range>>::type* = 0)
    {
        return range_begin(rng);
    }

    // const version ...
}
#else
// existing code...

So don't worry :-)
Here is a complete code I added to boost/range/begin.hpp:
(And I attached header files (not the patches) in this mail, for convenience.)

#ifndef BOOST_NO_RANGE_BASED_FOR
#include <boost/mpl/bool.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/range/iterator.hpp>

namespace boost
{

using std::begin;

namespace range_detail
{
    template <typename T>
    struct has_begin_impl
    {
        typedef char true_type;
        typedef char false_type[2];

        template <typename S>
        static true_type& check(S* s_ptr, decltype(s_ptr->begin())* = 0);

        template <typename S>
        static false_type& check(...);

        static const bool value = sizeof(check<T>(0)) == sizeof(true_type);
    };

    template <typename T>
    struct has_begin : boost::mpl::bool_<has_begin_impl<T>::value> {};
}

template <typename Range>
inline typename boost::range_iterator<Range>::type
begin(Range& rng, typename
disable_if<range_detail::has_begin<Range>>::type* = 0)
{
    return range_begin(rng);
}

template <typename Range>
inline typename boost::range_iterator<Range const>::type
begin(Range const& rng, typename
disable_if<range_detail::has_begin<Range>>::type* = 0)
{
    return range_begin(rng);
}

}
#else
// existing code...

Regards,
Michel





Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk