Topic: Namespaces/templates conflict


Author: mtsirkin@iil.intel.com
Date: 2000/10/04
Raw View
Hello!
It seems that a "kind of koenig lookup" is active for templates,
making namespaces much less closed than they are though to be.
(I am not referring to teh actual koenig lookup, but seems
similiar).

Could one of the standard gurus please clarify the following case (it
is common in STL implementations):

 template<class T> void foo(T t) {}

 namespace A {
 template<class T> void foo(T t) {}
 }
 namespace A {
 template<class T> void bar(T t) { foo(t); }
 // the call to foo is dependent on T
 }
 void mess() { A::bar(2); } // which foo will be called?


 According to the standard:
 ----------------------------
 14.6.4 - Dependent name resolution [temp.dep.res]

 -1- 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 (temp.point) and from
the definition context.
 ---------------------------------
 And this makes 2 foo functions visible when trying to instantiate call
to
 A::bar(d)

 Is it really an ambiguity? Or am I reading the standard incorrectly?
 If so, how should I understand this?
 Please mail a copy to mailto:mtsirkin@iil.intel.com
 Thanks,
       MST


Sent via Deja.com http://www.deja.com/
Before you buy.

---
[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: "Daniel Longest" <dajr4@vt.edu>
Date: 2000/10/05
Raw View
I'm by no means a standard guru but it seems to me that the one inside the A
namespace will be called because there is no using namespace A; directive in
the code sample you posted and you called foo() by prefixing the namespace
to it.


Daniel

--
--------------------------------------------------
Daniel Longest
dajr4@vt.edu

"Java isn't platform-independent; it is a platform"- Stroustrup
comp.lang.c++ http://www.parashift.com/cpp-faq-lite/
alt.comp.lang.learn.c-c++ http://www.faqs.org/faqs/C-faq/learn/
 -----------------------------------------------------------------------
 Pursuant to US Code, Title 47, Chapter 5, Subchapter II,    227,
 Any and all nonsolicited commercial E-mail sent to this address
 is subject to a download and archival fee in the amount of $500.00 US.
 E-Mailing denotes the acceptance of these terms
 -----------------------------------------------------------------------
<mtsirkin@iil.intel.com> wrote in message
news:8rg363$i1s$1@nnrp1.deja.com...
> Hello!
> It seems that a "kind of koenig lookup" is active for templates,
> making namespaces much less closed than they are though to be.
> (I am not referring to teh actual koenig lookup, but seems
> similiar).
>
> Could one of the standard gurus please clarify the following case (it
> is common in STL implementations):
>
>  template<class T> void foo(T t) {}
>
>  namespace A {
>  template<class T> void foo(T t) {}
>  }
>  namespace A {
>  template<class T> void bar(T t) { foo(t); }
>  // the call to foo is dependent on T
>  }
>  void mess() { A::bar(2); } // which foo will be called?
>
>
>  According to the standard:
>  ----------------------------
>  14.6.4 - Dependent name resolution [temp.dep.res]
>
>  -1- 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 (temp.point) and from
> the definition context.
>  ---------------------------------
>  And this makes 2 foo functions visible when trying to instantiate call
> to
>  A::bar(d)
>
>  Is it really an ambiguity? Or am I reading the standard incorrectly?
>  If so, how should I understand this?
>  Please mail a copy to mailto:mtsirkin@iil.intel.com
>  Thanks,
>        MST
>
>
> Sent via Deja.com http://www.deja.com/
> Before you buy.
>
> ---
> [ 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.research.att.com/~austern/csc/faq.html                ]
> [ Note that the FAQ URL has changed!  Please update your bookmarks.     ]
>


---
[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: =?ISO-8859-1?Q?J=F6rg?= Barfurth <joerg.barfurth@attglobal.net>
Date: 2000/10/05
Raw View
Am 04.10.00, 22:54:12, schrieb mtsirkin@iil.intel.com zum Thema=20
Namespaces/templates conflict:

> Hello!
> It seems that a "kind of koenig lookup" is active for templates,
> making namespaces much less closed than they are though to be.

> Could one of the standard gurus please clarify the following case (it
> is common in STL implementations):

I'm no guru, but I'll try.

>  template<class T> void foo(T t) {}

>  namespace A {
>  template<class T> void foo(T t) {}
>  }
>  namespace A {
>  template<class T> void bar(T t) { foo(t); }
>  // the call to foo is dependent on T
>  }
>  void mess() { A::bar(2); } // which foo will be called?

>From what you cite below, A::bar<int>(int) will call A::foo<int>(). A=20
builtin type (here: int) has no associated namespaces.

But you can produce an ambiguity though by using types with associated=20
namespaces:

   struct Global {};
   namespace B { struct InB {}; template <class T> foo(T t); }
   struct Both : B::InB {};

   void real_mess()
   {
      B::InB associateNamespaceB;
      Global associateGlobalNS;
=09
      A::bar( associateGlobalNS );   // error: use A::foo or  ::foo ?
      A::bar( associateNamespaceB ); // error: use A::foo or B::foo ?

      Both bothGlobalAndB;
      A::bar( bothGlobalAndB ); // error: use A::foo or B::foo or ::foo ?
   }

In these examples:
- the declaration of A::foo<> is visible at the point of definition
-  ::foo<> is from an associated namespace of ::Global in both the=20
  template's definition and instantiation context
- B::foo<> is from an associated namespace of B::InB but visible only=20
  in the instantiation context
(The associated namespaces of type ::Both are B and the global namespace)

>  According to the standard:
>  ----------------------------
>  14.6.4 - Dependent name resolution [temp.dep.res]

>  -1- 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 (temp.point) and from
> the definition context.
>  ---------------------------------
>  And this makes 2 foo functions visible when trying to instantiate call
> to
>  A::bar(d)
Where does 'd' come from ?

Two functions are visible only if:
- d is of a type such that at least one of its associated namespaces is=20
different from A=20
- there is a declaration of a function or function template named foo in=20
such a namespace
- that declaration is visible in either the definition or the=20
instantiation context of the template
Your example has such a declaration in the global namespace

As usual, the additional foo() is ambiguous with A::foo only if it also=20
is a template function and the  template isn't more specialized than A::f=
oo.=20

>  Is it really an ambiguity? Or am I reading the standard incorrectly?

Disclaimer: I did not look this up in the standard. But judging only from=
=20
what you quote above, your example (using 'int') is not ambiguous, but my=
=20
examples (using types with associated namespaces) are ambiguous.

Regards, J=F6rg

>  Please mail a copy to mailto:mtsirkin@iil.intel.com
Sorry I don't cc usenet posts without a compelling reason.


---
[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: wmm@fastdial.net
Date: 2000/10/05
Raw View
In article <8rg363$i1s$1@nnrp1.deja.com>,
  mtsirkin@iil.intel.com wrote:
>
> Could one of the standard gurus please clarify the following case (it
> is common in STL implementations):
>
>  template<class T> void foo(T t) {}
>
>  namespace A {
>  template<class T> void foo(T t) {}
>  }
>  namespace A {
>  template<class T> void bar(T t) { foo(t); }
>  // the call to foo is dependent on T
>  }
>  void mess() { A::bar(2); } // which foo will be called?
>
>  According to the standard:
>  ----------------------------
>  14.6.4 - Dependent name resolution [temp.dep.res]
>
>  -1- 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 (temp.point) and from
> the definition context.
>  ---------------------------------
>  And this makes 2 foo functions visible when trying to instantiate
call
> to
>  A::bar(d)

No, there's only one "foo" in the overload set in the call
from A::bar.  The argument in the call is "int," and there
is no associated namespace for fundamental types (3.4.2p2).
Thus only the visible declarations are considered, and
there's only one visible declaration -- A::foo (::foo is
hidden).  If you modified the example so that the argument
was a class or enumeration type declared in global scope,
then Koenig lookup would come into play and there would be
an ambiguity.

--
William M. Miller, wmm@fastdial.net
Vignette Corporation (www.vignette.com)


Sent via Deja.com http://www.deja.com/
Before you buy.

---
[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]