Topic: function template overloading and name lookup


Author: tom_usenet@hotmail.com (tom_usenet)
Date: Wed, 9 Jun 2004 17:06:32 +0000 (UTC)
Raw View
On Wed, 9 Jun 2004 03:33:08 +0000 (UTC), nesotto@cs.auc.dk ("Thorsten
Ottosen") wrote:

>yep, I've skipped reliance on ADL entirely. Now I now it will never work as
>I wanted it to:
>
>// header h1.hpp
>
>template< class T >
>void foo( X<T> );
>#include <uses_adl.hpp>
>
>// header h2.hpp
>
>template< class T >
>void foo( Y<T> )
>#include <uses_adl.hpp>
>
>// header all.hpp
>
>#include <h1.hpp>
>#include <h2.hpp> // ups, won't work
>
>Since this won't work, I will store a callback in my objects instead.

In your code above, the foo functions are in the global namespace, and
both X and Y are too, so ADL would work fine (the global namespace
would be searched at the point of instantiation. I expect the real
code involves namespaces, but as long as you put the foo functions in
the same namespace as an associated namespace of one of their
parameters, they should be found by ADL. There's only a major problem
if one of the foo's has parameters whose only associated namespace is
std (as with the deque example).

This problem is obviously more serious when "export" gets involved,
since code then tends to rely more on point of instantiation lookup.
Perhaps we should be allowed to add names to std as long as they don't
clash with any of the known std names, and don't break the usual
naming rules for variables at global scope.

Tom
--
C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html

---
[ 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: Thu, 10 Jun 2004 17:42:42 +0000 (UTC)
Raw View
"tom_usenet" <tom_usenet@hotmail.com> wrote in message news:inidc097b21jsua88l8249g9qfulcv6tmp@4ax.com...

| In your code above, the foo functions are in the global namespace, and
| both X and Y are too, so ADL would work fine (the global namespace
| would be searched at the point of instantiation. I expect the real
| code involves namespaces, but as long as you put the foo functions in
| the same namespace as an associated namespace of one of their
| parameters, they should be found by ADL. There's only a major problem
| if one of the foo's has parameters whose only associated namespace is
| std (as with the deque example).

yep, and each header had a parameter from the std 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: pavel@despammed.com ("Pavel Kuznetsov")
Date: Thu, 10 Jun 2004 17:43:39 +0000 (UTC)
Raw View
tom_usenet <tom_usenet@hotmail.com> wrote:

> Neither have two-phase name lookup implemented. GCC 3.4 does, and
> I have a feeling that the new Whidbey version of VC may have it too.

AFAIK VC++ 8 aka Whidbey will not have two-phase name lookup.

--
Pavel Kuznetsov
MetaCommunications Engineering
http://www.meta-comm.com/engineering

---
[ 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: tom_usenet@hotmail.com (tom_usenet)
Date: Mon, 7 Jun 2004 16:46:17 +0000 (UTC)
Raw View
On Sat, 5 Jun 2004 04:03:57 +0000 (UTC), nesotto@cs.auc.dk ("Thorsten
Ottosen") wrote:

>| >    template< class T >
>| >    inline void use_bar( T t )
>| >    {
>| >        foo::bar( t );
>| >    }

>ok, I'm certainly missing something here :-) Can foo::bar be turned into
>a dependent name somehow?

Yes, you can, but no, it doesn't help! Changing to:

template< class T >
inline void use_bar( T t )
{
    bar( t );
}

Here, bar is an unqualified-id depending on t, so it is dependent.
Ordinary lookup will find bar(T). However, bar(deque) *still* won't be
found, since lookup at the point of instantiation is ADL only (see
14.6.4) - the only namespace searched for overloads of bar will be
namespace std (the only "associated" namespace of deque<int>), so only
the name found through ordinary lookup (bar(T)) will be in the
overload set.

Incidently, this exposed a bug in GCC 3.4. With the change above to
using bar(t), GCC chose bar(deque) for the third call, which is
incorrect. Unsurprisingly, Comeau got it right calling bar(T).

Your only real solution to getting bar(deque) called is to move the
deque overload above use_bar so that it is found by normal lookup (and
keep the code as foo::bar(t)). An illegal solution would be to put the
deque overload of bar in namespace std, so that ADL at the point of
instantation would find it. This is only illegal since you can't
legally add new names to std.

In your real world problem, there may be an alternative solution.

>| (hastily checks with Comeau C++ and GCC 3.4 - both agree!)
>
>gcc3.3 and vc7.1 disagrees.

Neither have two-phase name lookup implemented. GCC 3.4 does, and I
have a feeling that the new Whidbey version of VC may have it too.

Tom
--
C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html

---
[ 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, 9 Jun 2004 03:33:08 +0000 (UTC)
Raw View
"tom_usenet" <tom_usenet@hotmail.com> wrote in message news:j7g8c0tdf0ti5edkhbu0rfuehbqkhpo06i@4ax.com...

|. However, bar(deque) *still* won't be
| found, since lookup at the point of instantiation is ADL only (see
| 14.6.4) - the only namespace searched for overloads of bar will be
| namespace std (the only "associated" namespace of deque<int>), so only
| the name found through ordinary lookup (bar(T)) will be in the
| overload set.

Thanks for the explanation :-)

| In your real world problem, there may be an alternative solution.

yep, I've skipped reliance on ADL entirely. Now I now it will never work as
I wanted it to:

// header h1.hpp

template< class T >
void foo( X<T> );
#include <uses_adl.hpp>

// header h2.hpp

template< class T >
void foo( Y<T> )
#include <uses_adl.hpp>

// header all.hpp

#include <h1.hpp>
#include <h2.hpp> // ups, won't work

Since this won't work, I will store a callback in my objects instead.

Thanks to you all

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: tom_usenet@hotmail.com (tom_usenet)
Date: Fri, 4 Jun 2004 16:10:32 +0000 (UTC)
Raw View
On Thu, 3 Jun 2004 17:25:13 +0000 (UTC), nesotto@cs.auc.dk ("Thorsten
Ottosen") wrote:

>Hi All,
>
>Consider the small program below. What would you expect the output to be?
>
>#include <iostream>
>#include <deque>
>
>namespace foo
>{
>    template< class T >
>    inline void bar( T )
>    {
>        std::cout << " bar.T";
>    }
>
>    template< class T >
>    inline void use_bar( T t )
>    {
>        foo::bar( t );
>    }
>
>    template<>
>    inline void bar<int>( int i )
>    {
>        std::cout << " bar.Int";
>    }
>
>    template< class T, class A >
>    inline void bar( std::deque<T,A> d )
>    {
>        std::cout << " bar.Deque";
>    }
>}
>
>
>
>int main()
>{
>    using namespace foo;
>    use_bar( char() );

Will print bar.T, for obvious reasons.

>    use_bar( int() );

Will print bar.Int. This is less obvious. But because the explicit
specialization bar<int> has been declared before the point of
instantiation of bar<int>, (which is right after "main") it is fine.
This follows from 14.6.4.1/1 (for point of instantiation) and 14.7.3/6
for information about the declaration of the specialization having to
precede the use of it.

>    use_bar( std::deque<int>() );

Will print bar.T. This is because foo::bar is a non-dependent name,
and therefore is looked up at the point of definition, where the deque
overload is not visible.

(hastily checks with Comeau C++ and GCC 3.4 - both agree!)

Tom
--
C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html

---
[ 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: Sat, 5 Jun 2004 04:03:57 +0000 (UTC)
Raw View
"tom_usenet" <tom_usenet@hotmail.com> wrote in message news:mnj0c0tm8t11h7iltfcvoq2n2rh6466gqs@4ax.com...

| >namespace foo
| >{
| >    template< class T >
| >    inline void bar( T )
| >    {
| >        std::cout << " bar.T";
| >    }
| >
| >    template< class T >
| >    inline void use_bar( T t )
| >    {
| >        foo::bar( t );
| >    }

[snip]

| >    template< class T, class A >
| >    inline void bar( std::deque<T,A> d )
| >    {
| >        std::cout << " bar.Deque";
| >    }
| >}

[snip]

| >    use_bar( std::deque<int>() );
|
| Will print bar.T. This is because foo::bar is a non-dependent name,
| and therefore is looked up at the point of definition, where the deque
| overload is not visible.

ok, I'm certainly missing something here :-) Can foo::bar be turned into
a dependent name somehow?

| (hastily checks with Comeau C++ and GCC 3.4 - both agree!)

gcc3.3 and vc7.1 disagrees.

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: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Sat, 5 Jun 2004 07:54:38 +0000 (UTC)
Raw View
nesotto@cs.auc.dk ("Thorsten Ottosen") writes:

[...]

| | (hastily checks with Comeau C++ and GCC 3.4 - both agree!)
|
| gcc3.3 and vc7.1 disagrees.

GCC-3.3.x is not known to correctly implement the two-phase name
lookup rules.

--
                                                        Gabriel Dos Reis
                                                         gdr@cs.tamu.edu
  Texas A&M University -- Computer Science Department
 301, Bright Building -- College Station, TX 77843-3112

---
[ 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: llewelly.at@xmission.dot.com (llewelly)
Date: Sun, 6 Jun 2004 23:54:41 +0000 (UTC)
Raw View
nesotto@cs.auc.dk ("Thorsten Ottosen") writes:

> "tom_usenet" <tom_usenet@hotmail.com> wrote in message news:mnj0c0tm8t11h7iltfcvoq2n2rh6466gqs@4ax.com...
>
> | >namespace foo
> | >{
> | >    template< class T >
> | >    inline void bar( T )
> | >    {
> | >        std::cout << " bar.T";
> | >    }
> | >
> | >    template< class T >
> | >    inline void use_bar( T t )
> | >    {
> | >        foo::bar( t );
> | >    }
>
> [snip]
>
> | >    template< class T, class A >
> | >    inline void bar( std::deque<T,A> d )
> | >    {
> | >        std::cout << " bar.Deque";
> | >    }
> | >}
>
> [snip]
>
> | >    use_bar( std::deque<int>() );
> |
> | Will print bar.T. This is because foo::bar is a non-dependent name,
> | and therefore is looked up at the point of definition, where the deque
> | overload is not visible.
>
> ok, I'm certainly missing something here :-) Can foo::bar be turned into
> a dependent name somehow?
>
> | (hastily checks with Comeau C++ and GCC 3.4 - both agree!)
>
> gcc3.3 and vc7.1 disagrees.

gcc 3.3 does not implement two-phase lookup. Nor does vc 7.1

---
[ 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: Thu, 3 Jun 2004 17:25:13 +0000 (UTC)
Raw View
Hi All,

Consider the small program below. What would you expect the output to be?

#include <iostream>
#include <deque>

namespace foo
{
    template< class T >
    inline void bar( T )
    {
        std::cout << " bar.T";
    }

    template< class T >
    inline void use_bar( T t )
    {
        foo::bar( t );
    }

    template<>
    inline void bar<int>( int i )
    {
        std::cout << " bar.Int";
    }

    template< class T, class A >
    inline void bar( std::deque<T,A> d )
    {
        std::cout << " bar.Deque";
    }
}



int main()
{
    using namespace foo;
    use_bar( char() );
    use_bar( int() );
    use_bar( std::deque<int>() );
    return 0;
}

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                       ]