|
Boost : |
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
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk