Boost logo

Boost :

From: Fernando Cacciola (fernando_cacciola_at_[hidden])
Date: 2003-08-06 16:15:14


David Abrahams <dave_at_[hidden]> wrote in message
news:uk79qvc01.fsf_at_boost-consulting.com...
> "Fernando Cacciola" <fernando_cacciola_at_[hidden]> writes:
>
> >>and anyway I don't see how it could help if you want to
> >> specialize something in std. Am I missing something?
> >>
> > If the specialization is injected into 'std' via
> > a using directive, as in
> >
> > namespace std { using namespace stdx ; }
> >
> > the problem goes away (the primary swap<> is now found).
>
> Err, no. Koenig lookup doesn't proceed through using directives.
>
Right, but ADL is not in stake here.
The problem is the _qualified_ call:

std::swap(px, other.px);

inside

shared_ptr::swap();

>
> namespace std { using stdx::swap; }
>
> works.
>
It works for ADL.

Still, according to 3.4.3.2/2, for the _qualified_ call "std::swap()",
to find the primary template there cannot be any 'swap' declared
directly in 'std' since the primary template is in a nested namespace.
Furthermore, the names are injected into namespace std via a
"using directive" and not a "using declaration",
so my workaround does work for the qualified case
(by the same mechanism the "using namespace _STLP_STD"
works for the library implementation)

As for unqualified calls (involving ADL),
you're right, but then there's a "conflict of interest"
as shown by this program (which I tested against Comeau Online)

*******************************
#include <iostream>

// This represents _STLP_STD
namespace N
{
  template<class T> void f( T const& ) { std::cout << "primary.\n" ;}
  template<> void f(int const& ) { std::cout << "<int> specialization.\n" ; }
}

// This represents 'std' as implemented by STLPort
namespace A
{
  using namespace N ;
}

// A sample user class.
class C{};

// A user-side namespace
namespace M
{
  // A::f cannot be specialized here, but can be overloaded.
  void f(C const& ) { std::cout << "<C> overload.\n" ; }
}

namespace A
{
  using namespace M ;
// using M::f ;
// template<> void f(C const& ) { std::cout << "<C> specialization.\n" ; }

}

void qual()
{
  A::f(std::cout); // should call primary template
  A::f(1); // should call int specialization
  C c ; A::f(c); // should user overload
}

void koenig()
{
  using A::f ;

  f(std::cout); // should call primary template
  f(1); // should call int specialization
  C c ; f(c); // should user overload
}

int main()
{
  qual();
  koenig();
}
*******************

Now, If I switch from the using directive to the using declaration,
Comeau reports that it can't convert to 'C',
thus hiding the 'f' in N.
That is, if the using declaration is used to enable ADL,
the std library names are hidden because those are not
found during koenig lookup, as you said, so a using
directive would be needed, mirroring the library
implementation.
OTOH however, you can't specialize swap neither in
stdx nor in std (even though BCB6 incorrectly allows it),
so as you initially said, the _only_ correct
woraround is to put the specialization in _STLP_STD,
were the primary template is.

Fernando Cacciola


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