$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
From: David Abrahams (dave_at_[hidden])
Date: 2005-09-17 00:38:50
Rob Stewart <stewart_at_[hidden]> writes:
> I've been thinking about this issue and wonder if the following
> wouldn't solve the problem neatly for both conforming and
> non-conforming compilers:
>
>    // whatever/foo.h
>    namespace whatever
>    {
>       class foo
>       {
>       ...
>       };
>
>       // for conforming compilers
>       unspecified begin(foo const &) { ... };
>       ...
>    }
>
>    // for non-conforming compilers
>    namespace boost { namespace range {
>       using whatever::begin;
>    } }
>
>    // boost/range/begin.hpp
>    namespace boost
>    {
>       inline template <T>
>       unspecified begin(T const & range_i)
>       {
> 	 using boost::range::begin;
> 	 return begin(range_i);
>       }
>    }
Careful.  Many of the problems you can run into with dispatching only
show up in the case where the definition of begin you want to be
selected *follows* the template that uses it.
> If the author of foo has no other need for begin(), then
> whatever/foo.h could be done like this instead:
>
>    // whatever/foo.h
>    namespace whatever
>    {
>       class foo
>       {
>       ...
>       };
>    }
>
>    namespace boost { namespace range {
>       unspecified begin(foo const &) { ... };
>    } }
No it can't.  That begin() will only be found by ordinary lookup,
looks *backwards* from the point of definition of the template in
which it is used.  That's the problem I referred to above.
> If whatever::foo belongs to a user of Boost.Range that only uses
> conforming compilers, then foo.h only needs to be:
>
>    // whatever/foo.h
>    namespace whatever
>    {
>       class foo
>       {
>       ...
>       };
>
>       unspecified begin(foo const &) { ... };
>       ...
>    }
>
> If whatever::foo provides get_begin() instead, for whatever
> reason, then foo.h becomes:
>
>    // whatever/foo.h
>    namespace whatever
>    {
>       class foo
>       {
>       ...
>       };
>
>       unspecified get_begin(foo const &) { ... };
>       ...
>    }
>
>    namespace boost { namespace range {
>       inline unspecified begin(foo const & foo_i)
>       {
> 	 return get_begin(foo_i);
>       }
>    } }
Once again, no, for the same reason cited above.
> This approach provides a number of benefits:
>
> - we can use the most obvious name, boost::range::begin, for the
>   point of customization
> - benefits from ADL when supported
> - Types in namespace std or built-in types (pointers) can be
>   retrofitted in boost::range and will work like everything else
>   (though you must include the appropriate header to get the
>   required boost::range::begin() overload)
> - flexibility for those wishing to support Boost.Range
> - non-conformance code can be excised easily later
>
> Did I miss something?
Two-phase name lookup. 
  14.6.4 Dependent name resolution [temp.dep.res]
    In resolving dependent names, names from the following sources are
    considered:
    â Declarations that are visible at the point of definition of the
      template.
    â Declarations from namespaces associated with the types of the
      function arguments both from the instantiation context
      (14.6.4.1) and from the definition context.
Unless you arrange for boost::range to be an associated namespace of
foo, you're setting up dangerous #include order dependencies.
-- Dave Abrahams Boost Consulting www.boost-consulting.com