Topic: ADL lookup with explicit template parameters


Author: "Greg Herlihy" <greghe@pacbell.net>
Date: Wed, 14 Jun 2006 18:46:43 CST
Raw View
Ion Gazta   aga wrote:
> Hi to all,
>
>  Recently a bug was reported against a Boost library regarding an ADL
> customization point. VC 7.1 and VC 8.0 compile fine the library but gcc
> reports an error. This ADL issue has been discussed but it's not clear
> for me which compiler is right.
>
> The test case is simple. A container takes the pointer type as a
> template argument and wants to treat this pointer generically. The
> container wants to make an static cast in the pointer and calls
> "static_pointer_cast<Target>(source_ptr);". static_pointer_cast has
> been adopted as the casting function for std::tr1::shared_ptr, so it's
> logical to be overloaded by other smart pointers, like with
> get_pointer() is going to be used to obtain a raw pointer generically.
>
> It happens that VC 7.1 and VC 8.0 compile this fine but gcc compiles
> only if the static_pointer_cast code for the smart pointer is declared
> before the calling point. This causes problems to library users,
> because compilation success depends on header include order. This is a
> simplified test case:
..
> Should the "function<Type>(params...)" expression disallow ADL?

Yes, ADL does not occur for template function calls with explicitly
specified type parameters:

"...But when a function template with explicit template arguments is
used, the call does not have the correct syntactic form unless there is
a function template with that name visible at the point of the call. If
no such name is visible, the call is not syntactically well-formed and
argument-dependent lookup does not apply."    14.8.1/8

Greg


---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: dave@boost-consulting.com (David Abrahams)
Date: Wed, 14 Jun 2006 23:46:54 GMT
Raw View
johnchx2@yahoo.com writes:

> Ion Gazta=F1aga wrote:
>> On the other hand, if the cast operation is
>> declared without explicit template parameters:
>>
>>    //Declaration
>>    template<class T, class U>
>>    smart_ptr<T> static_pointer_cast(const smart_ptr<U> &u, T * =3D 0)
>>    {  return smart_ptr<T>(); }
>>
>>    //Call
>>    static_pointer_cast(Pointer(), (int*)0);
>>
>> both compilers compile this fine. Should the
>> "function<Type>(params...)" expression disallow ADL? To ADL or not to
>> ADL, that's the question.
>
> I suspect that the problem isn't ADL, it's two-phase name lookup. =20

Just to pedantically clarify: "the problem" is neither ADL nor
two-phase lookup; it's that the "wrong" function is called.

ADL only takes effect in phase two, so you can't really separate it
from two-phase lookup.  You are correct that lookup is happening only
at the point of definition because of the explicit template argument,
but in order for the OP's example to work, you need both lookup in
phase two *and* ADL.

--=20
Dave Abrahams
Boost Consulting
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.comeaucomputing.com/csc/faq.html                      ]





Author: Alberto Ganesh Barbati <AlbertoBarbati@libero.it>
Date: Thu, 15 Jun 2006 18:09:06 CST
Raw View
Greg Herlihy ha scritto:
> Ion Gazta   aga wrote:
>> Should the "function<Type>(params...)" expression disallow ADL?
>
> Yes, ADL does not occur for template function calls with explicitly
> specified type parameters:

Are you sure? I don't think so. See below.

> "...But when a function template with explicit template arguments is
> used, the call does not have the correct syntactic form unless there is
> a function template with that name visible at the point of the call. If
> no such name is visible, the call is not syntactically well-formed and
> argument-dependent lookup does not apply."    14.8.1/8

You snipped the most important part of the sentence: "[... adl does not
apply.] If some such name is visible, argument dependent lookup applies
and additional function templates may be found in other namespaces." If
I understand it correctly, this contradict your statement above: ADL can
indeed occur even in presence of explicit template parameters, as long
as the name matches a visible template name, so that the parser can
detect the correct syntactic form of the statement.

That said, I'm prone to believe that gcc is in error as the diagnostic
clearly hints that it was able to detect the syntactic correctness, yet
it did not apply ADL.

Just my opinion.

Ganesh

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: "=?iso-8859-1?q?Ion_Gazta=F1aga?=" <igaztanaga@gmail.com>
Date: Fri, 16 Jun 2006 15:58:25 CST
Raw View
> > Yes, ADL does not occur for template function calls with explicitly
> > specified type parameters:

> That said, I'm prone to believe that gcc is in error as the diagnostic
> clearly hints that it was able to detect the syntactic correctness, yet
> it did not apply ADL.

Thanks for the replies. Since there is an issue about this (thanks to
Peter Dimov for the link):

http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_active.html#485

I think that I will let the experts solve this. The only comment I want
to make is that if template function calls disable ADL, the standard
should define cast functions for smart pointers that could be reached
using ADL.

My 2 cents,

Ion

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Sun, 18 Jun 2006 15:00:15 GMT
Raw View
Ion Gazta=F1aga ha scritto:
>>> Yes, ADL does not occur for template function calls with explicitly
>>> specified type parameters:
>=20
>> That said, I'm prone to believe that gcc is in error as the diagnostic
>> clearly hints that it was able to detect the syntactic correctness, ye=
t
>> it did not apply ADL.
>=20
> Thanks for the replies. Since there is an issue about this (thanks to
> Peter Dimov for the link):
>=20
> http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_active.html#485

Sure the DR is legitimate, the standard does not show good coherency in
this area. A clarification is much needed. However, in this particular
case, I do believe the paragraph I cited in my post does not show
latitude for an interpretation that allows the gcc behaviour as correct.

> I think that I will let the experts solve this. The only comment I want
> to make is that if template function calls disable ADL, the standard
> should define cast functions for smart pointers that could be reached
> using ADL.

Well said. As TR1 (and, hopefully, the next revision of C++) is going to
introduce xxx_pointer_cast functions, unqualified calls to functions
with an explicit template parameter list is an idiom that is surely
useful and might even become quite popular.

Ganesh

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: johnchx2@yahoo.com
Date: Sun, 18 Jun 2006 12:38:25 CST
Raw View
David Abrahams wrote:

> Just to pedantically clarify: "the problem" is neither ADL nor
> two-phase lookup; it's that the "wrong" function is called.

Sure. :-)

What I meant to say was that the *source* of the problem was not, as
the OP seemed to suspect, that ADL doesn't apply to template-id's (it
does, IIUC), but that, because of the 2-phase lookup rules, ADL wasn't
happening where it was expected: it was being applied only in the
definition context, not in the instantiation context.

> ADL only takes effect in phase two, so you can't really separate it
> from two-phase lookup.

Hmm.  Are you saying that non-dependent names are never looked up with
ADL?

> You are correct that lookup is happening only
> at the point of definition because of the explicit template argument,
> but in order for the OP's example to work, you need both lookup in
> phase two *and* ADL.

I may be mistaken, but I thought a non-dependent name could be found
via ADL provided the declaration was in scope at the point of the
template's definition.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: dave@boost-consulting.com (David Abrahams)
Date: Sun, 18 Jun 2006 21:13:12 GMT
Raw View
johnchx2@yahoo.com writes:

>> ADL only takes effect in phase two, so you can't really separate it
>> from two-phase lookup.
>
> Hmm.  Are you saying that non-dependent names are never looked up with
> ADL?

Hmm, I'm not sure what I was thinking.  Non-templates don't have
phases, and ADL certainly happens there.

Re-reading your explanation it looks perfectly correct to me.  Sorry
for the noise.

>> You are correct that lookup is happening only
>> at the point of definition because of the explicit template argument,
>> but in order for the OP's example to work, you need both lookup in
>> phase two *and* ADL.
>
> I may be mistaken, but I thought a non-dependent name could be found
> via ADL provided the declaration was in scope at the point of the
> template's definition.

Yes, I think you're right.

--
Dave Abrahams
Boost Consulting
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.comeaucomputing.com/csc/faq.html                      ]





Author: "=?iso-8859-1?q?Ion_Gazta=F1aga?=" <igaztanaga@gmail.com>
Date: Wed, 14 Jun 2006 11:52:59 CST
Raw View
Hi to all,

 Recently a bug was reported against a Boost library regarding an ADL
customization point. VC 7.1 and VC 8.0 compile fine the library but gcc
reports an error. This ADL issue has been discussed but it's not clear
for me which compiler is right.

The test case is simple. A container takes the pointer type as a
template argument and wants to treat this pointer generically. The
container wants to make an static cast in the pointer and calls
"static_pointer_cast<Target>(source_ptr);". static_pointer_cast has
been adopted as the casting function for std::tr1::shared_ptr, so it's
logical to be overloaded by other smart pointers, like with
get_pointer() is going to be used to obtain a raw pointer generically.

It happens that VC 7.1 and VC 8.0 compile this fine but gcc compiles
only if the static_pointer_cast code for the smart pointer is declared
before the calling point. This causes problems to library users,
because compilation success depends on header include order. This is a
simplified test case:

////////////////////////////////////////
//raw_ptr.hpp header:
////////////////////////////////////////

namespace raw_ptr
{

//static_pointer_cast overload for raw pointers
template<class T, class U>
inline T* static_pointer_cast(U *ptr)
{  return static_cast<T*>(ptr);  }

}  //namespace raw_ptr

////////////////////////////////////////
//container.hpp header:
////////////////////////////////////////

namespace dummy {

template<class Pointer>
class container
{
   public:

   void func()
   {
      using raw_ptr::static_pointer_cast;
      static_pointer_cast<int>(Pointer());
   }
};

}  //namespace dummy {


////////////////////////////////////////
//smart_ptr.hpp header:
////////////////////////////////////////

namespace dummy {

template<class T>
class smart_ptr
{};

template<class T, class U>
smart_ptr<T> static_pointer_cast(const smart_ptr<U> &u)
{  return smart_ptr<T>(); }

}  //namespace dummy {

int main()
{
   using namespace dummy;
   typedef container<smart_ptr<int> > my_container;
   my_container cont;
   cont.func();

   typedef container<int *> my_container2;
   my_container2 cont2;
   cont2.func();
   return 0;
}

This fails in gcc (3.4 and 4.1) with: "no matching function for call to
'static_pointer_cast(dummy::smart_ptr<int>)" error. The questions are:

-> Is gcc right or it should should kick ADL lookup like VC?

If gcc is right, generic casts expression would be unsuitable as
customization points. On the other hand, if the cast operation is
declared without explicit template parameters:

   //Declaration
   template<class T, class U>
   smart_ptr<T> static_pointer_cast(const smart_ptr<U> &u, T * = 0)
   {  return smart_ptr<T>(); }

   //Call
   static_pointer_cast(Pointer(), (int*)0);

both compilers compile this fine. Should the
"function<Type>(params...)" expression disallow ADL? To ADL or not to
ADL, that's the question.

Regards,

Ion

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: johnchx2@yahoo.com
Date: Wed, 14 Jun 2006 15:24:35 CST
Raw View
Ion Gazta   aga wrote:
> On the other hand, if the cast operation is
> declared without explicit template parameters:
>
>    //Declaration
>    template<class T, class U>
>    smart_ptr<T> static_pointer_cast(const smart_ptr<U> &u, T * = 0)
>    {  return smart_ptr<T>(); }
>
>    //Call
>    static_pointer_cast(Pointer(), (int*)0);
>
> both compilers compile this fine. Should the
> "function<Type>(params...)" expression disallow ADL? To ADL or not to
> ADL, that's the question.

I suspect that the problem isn't ADL, it's two-phase name lookup.  In
the alternate version of the code (quoted above), the name
static_pointer_cast is a dependent name, so it's looked up at the point
of instantiation (by which point the customized version of
static_pointer_cast is in scope).  But in the original version,
static_pointer_cast<int> isn't a dependent name, since it's a
template-id, not a plain identifier.  In that case, the name is looked
up immediately, before the custom verision is introduced.


---
[ 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.comeaucomputing.com/csc/faq.html                      ]