Topic: can block scope using declarations and ADL create ambiguity?


Author: dave@boost-consulting.com (David Abrahams)
Date: Sat, 21 Aug 2004 06:18:14 GMT
Raw View
hinnant@metrowerks.com (Howard Hinnant) writes:

> In article <cfv2en$bco$1@swifty.westend.com>,
>  daniel.frey@aixigo.de (Daniel Frey) wrote:
>
>> Well, for the records, I've improved the technique since:
> <snip>
>> The freedom *not* to provide an overload is only possible outside of the
>> algorithm's namespace. A restriction I think one can live with as a
>> namespace is usually not filled by independent authors.
>
> The lack of this freedom is what bit us before.  I don't think we can
> live with this restriction.  Add the following test:
>
>     A::f(&ca);
>
> You get ambiguity again.  Once that gets fixed, add:
>
>     A::C* cp = &ca;
>     A::f(&cp);
>
> Ambiguity again.
>
> I think ultimately in adl_f you need some way to say:  Use ADL for this
> call except for namespace A.

Can't this be fixed by detecting whether there's an ADL-accessible f()
for the argument?  How to do that is well-understood.

--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: daniel.frey@aixigo.de (Daniel Frey)
Date: Wed, 18 Aug 2004 11:24:36 GMT
Raw View
Howard Hinnant wrote:
> I believe so.  And that drives the nail in the coffin of this technique=
=20
> that just a few weeks ago looked so promising to me.
>=20
> <sigh>

Well, for the records, I've improved the technique since:

#include <iostream>

namespace A
{
    namespace detail
    {
       template< typename T >
       void f( const T& )
       {
          std::cout << 1 << std::endl;
       }

       template< typename T >
       void adl_f( const T& x )
       {
          f( x );
       }
    }

    template< typename T >
    void f( const T& x )
    {
       detail::adl_f( x );
    }

    struct C {};

    void f( const C& x )
    {
       std::cout << 3 << std::cout;
       // or just call detail::f( x );
    }

    template< typename T >
    struct D {};

    template< typename T >
    void f( const D< T >& x )
    {
       std::cout << 4 << std::endl;
    }
}

namespace B
{
    class C {};

    void f( const C& )
    {
       std::cout << 2 << std::endl;
    }
}

int main()
{
    A::f( 42 );

    A::C ca;
    A::f( ca );

    B::C cb;
    A::f( cb );

    A::D< int > d;
    A::f( d );
}

The freedom *not* to provide an overload is only possible outside of the=20
algorithm's namespace. A restriction I think one can live with as a=20
namespace is usually not filled by independent authors.

Regards, Daniel

--=20
Daniel Frey

aixigo AG - financial solutions & technology
Schlo=DF-Rahe-Stra=DFe 15, 52072 Aachen, Germany
fon: +49 (0)241 936737-42, fax: +49 (0)241 936737-99
eMail: daniel.frey@aixigo.de, web: http://www.aixigo.de


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hinnant@metrowerks.com (Howard Hinnant)
Date: Wed, 18 Aug 2004 16:54:02 GMT
Raw View
In article <cfv2en$bco$1@swifty.westend.com>,
 daniel.frey@aixigo.de (Daniel Frey) wrote:

> Well, for the records, I've improved the technique since:
<snip>
> The freedom *not* to provide an overload is only possible outside of the
> algorithm's namespace. A restriction I think one can live with as a
> namespace is usually not filled by independent authors.

The lack of this freedom is what bit us before.  I don't think we can
live with this restriction.  Add the following test:

    A::f(&ca);

You get ambiguity again.  Once that gets fixed, add:

    A::C* cp = &ca;
    A::f(&cp);

Ambiguity again.

I think ultimately in adl_f you need some way to say:  Use ADL for this
call except for namespace A.

-Howard

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: nesotto@cs.auc.dk ("Thorsten Ottosen")
Date: Wed, 18 Aug 2004 17:16:22 GMT
Raw View
"Daniel Frey" <daniel.frey@aixigo.de> wrote in message news:cfv2en$bco$1@swifty.westend.com...

|The freedom *not* to provide an overload is only possible outside of the
|algorithm's namespace. A restriction I think one can live with as a
|namespace is usually not filled by independent authors.

and then again, if boost.range ever moved to namespace std, *all* standard containers would have to have an overload for
size(), begin(), end(). In that sense it does not scale superbly.

It might be the best to do anyway.

How is 7.3.3/9 read anyway:

"Definitions added to the namespace after the using-declaration are not considered when a use of the name is made."

shouldn't this prohibit a compiler from considering the function we are defining? I mean, when is a definitions precisely added to
the namespace?

br

Thorsten


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: nesotto@cs.auc.dk ("Thorsten Ottosen")
Date: Tue, 17 Aug 2004 21:45:26 GMT
Raw View
Dear all,

The problem is very simple: I want to enable ADL even with qualified syntax as discussed in the thread "Whence swap".

Consider this code:

namespace X
{
    namespace detail
   {
       template< class T >
       void foo( T& t )
      { /* default implementation */ }
   }

   template< class T >
   void foo( T& t )
  {
      //
      // create ADL hook
      //
      using detail::foo;
      foo( t ); // label1
  }

}

So far so good. The problem is now that if we call X::foo() with an object of a class from namespace X. At "label1" some compilers,
in particular
gcc 3.4.1, claim ambiguity: The using declaration means we can find detail::foo and ADL means we can get a recursive call to foo().

In short, is this new version of gcc correct?

br

Thorsten


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hinnant@metrowerks.com (Howard Hinnant)
Date: Wed, 18 Aug 2004 01:35:41 GMT
Raw View
In article <41226fd2$0$73941$14726298@news.sunsite.dk>,
 nesotto@cs.auc.dk ("Thorsten Ottosen") wrote:

> Dear all,
>
> The problem is very simple: I want to enable ADL even with qualified syntax
> as discussed in the thread "Whence swap".
>
> Consider this code:
>
> namespace X
> {
>     namespace detail
>    {
>        template< class T >
>        void foo( T& t )
>       { /* default implementation */ }
>    }
>
>    template< class T >
>    void foo( T& t )
>   {
>       //
>       // create ADL hook
>       //
>       using detail::foo;
>       foo( t ); // label1
>   }
>
> }
>
> So far so good. The problem is now that if we call X::foo() with an object of
> a class from namespace X. At "label1" some compilers,
> in particular
> gcc 3.4.1, claim ambiguity: The using declaration means we can find
> detail::foo and ADL means we can get a recursive call to foo().
>
> In short, is this new version of gcc correct?

I believe so.  And that drives the nail in the coffin of this technique
that just a few weeks ago looked so promising to me.

The reason why the technique looked so promising in the first place is
that the local X::detail::foo prototype (via the using declaration) hid
the X::foo prototype from ordinary lookup because the X::detail::foo
prototype was (re)declared in an enclosing scope as compared to the
X::foo prototype, thus preventing ambiguity or recursion.

But when ADL is performed, X::foo can once again be found if X is a
namespace associated with T (by the rules of 3.4.2/2), and there doesn't
exist a more specialized (or ordinary) overload of X::foo.

<sigh>

-Howard

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]