|
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