public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/30822]  New: wrong choice of overloaded template functions in recursive call
@ 2007-02-16 12:09 Zarathustra at gentlemansclub dot de
  2007-02-16 15:47 ` [Bug c++/30822] " pinskia at gcc dot gnu dot org
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Zarathustra at gentlemansclub dot de @ 2007-02-16 12:09 UTC (permalink / raw)
  To: gcc-bugs

Hello, in the attached piece of code two pairs of template functions are
defined which differ just in the order of their definitions.
The first pair (for_all_1) is accepted by the compiler (gcc 4.1.1) the second
(for_all_2) is rejected. (The aim of the code is to iterate over a list of
elements of different types and execute an operation on each element.) The code
compiles with the Visual Studio 2005 c++ compiler. gcc 3.3.1 claims that the
function calls are ambiguous. 

I do not have the newest gcc compiler. Could some one please confirm that this
is a bug and that it is not fixed with gcc 4.1.2 or later?

Thanks 
  Volker

#include <iostream>

class element
{
public:
 void test() { std::cout << "Hello World" << std::endl; }
};

template<typename TElement>
class op
{
public:
  void operator()(TElement elem) { elem.test(); }
};

class cons_end
{
};

template<typename TElement,typename TTail>
class cons
{
public:
 TElement elem;
 TTail tail;
};


// note the order of the definitions of the two functions named for_all_1
template<template<typename> class TOperator,typename TElement>
void for_all_1(TElement elem, cons_end tail)
{
  TOperator<TElement>()(elem);
}

template<template<typename> class TOperator,typename TElement, typename TTail>
void for_all_1(TElement elem, TTail tail)
{
  TOperator<TElement>()(elem);
  for_all_1<TOperator>(tail.elem,tail.tail);
}

// now the order changed and the compiler complains!
template<template<typename> class TOperator,typename TElement, typename TTail>
void for_all_2(TElement elem, TTail tail)
{
  TOperator<TElement>()(elem);
  for_all_2<TOperator>(tail.elem,tail.tail);
}

template<template<typename> class TOperator,typename TElement>
void for_all_2(TElement elem, cons_end tail)
{
  TOperator<TElement>()(elem);
}

int main(int argc, char *argv[])
{
  cons<element,cons<element,cons_end> > list;
  for_all_1<op>(list.elem,list.tail);
  for_all_2<op>(list.elem,list.tail);
}


-- 
           Summary: wrong choice of overloaded template functions in
                    recursive call
           Product: gcc
           Version: 4.1.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: Zarathustra at gentlemansclub dot de


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30822


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug c++/30822] wrong choice of overloaded template functions in recursive call
  2007-02-16 12:09 [Bug c++/30822] New: wrong choice of overloaded template functions in recursive call Zarathustra at gentlemansclub dot de
@ 2007-02-16 15:47 ` pinskia at gcc dot gnu dot org
  2007-02-16 16:35 ` Zarathustra at gentlemansclub dot de
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: pinskia at gcc dot gnu dot org @ 2007-02-16 15:47 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #1 from pinskia at gcc dot gnu dot org  2007-02-16 15:47 -------
// now the order changed and the compiler complains!

I think GCC 4.1.x and above are doing the correct behavior with respect of the
C++ standard.  The C++ standard has specific rules about namelookup in
templates which differs from what most people think they are as before GCC
4.1.x did not implement them and I think Microsoft's VS also still does not
implement them.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30822


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug c++/30822] wrong choice of overloaded template functions in recursive call
  2007-02-16 12:09 [Bug c++/30822] New: wrong choice of overloaded template functions in recursive call Zarathustra at gentlemansclub dot de
  2007-02-16 15:47 ` [Bug c++/30822] " pinskia at gcc dot gnu dot org
@ 2007-02-16 16:35 ` Zarathustra at gentlemansclub dot de
  2007-02-21  7:44 ` Zarathustra at gentlemansclub dot de
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Zarathustra at gentlemansclub dot de @ 2007-02-16 16:35 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #2 from Zarathustra at gentlemansclub dot de  2007-02-16 16:35 -------
I know the rules for template function name lookup are complicated, and I do
not claim that I understand them completely. But I am pretty sure that the
order of the definitions should not matter. There is a partial ordering of
template functions to decide which function is used. This ordering depends on
which function is "more specialized" than the other, but not the sequence of
the definitions.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30822


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug c++/30822] wrong choice of overloaded template functions in recursive call
  2007-02-16 12:09 [Bug c++/30822] New: wrong choice of overloaded template functions in recursive call Zarathustra at gentlemansclub dot de
  2007-02-16 15:47 ` [Bug c++/30822] " pinskia at gcc dot gnu dot org
  2007-02-16 16:35 ` Zarathustra at gentlemansclub dot de
@ 2007-02-21  7:44 ` Zarathustra at gentlemansclub dot de
  2007-02-21 10:16 ` Zarathustra at gentlemansclub dot de
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Zarathustra at gentlemansclub dot de @ 2007-02-21  7:44 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #3 from Zarathustra at gentlemansclub dot de  2007-02-21 07:44 -------
The same problem appears with gcc 4.1.2 20061115 (prerelease) (SUSE Linux)


-- 

Zarathustra at gentlemansclub dot de changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Version|4.1.1                       |4.1.2


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30822


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug c++/30822] wrong choice of overloaded template functions in recursive call
  2007-02-16 12:09 [Bug c++/30822] New: wrong choice of overloaded template functions in recursive call Zarathustra at gentlemansclub dot de
                   ` (2 preceding siblings ...)
  2007-02-21  7:44 ` Zarathustra at gentlemansclub dot de
@ 2007-02-21 10:16 ` Zarathustra at gentlemansclub dot de
  2007-03-09  4:14 ` bangerth at dealii dot org
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Zarathustra at gentlemansclub dot de @ 2007-02-21 10:16 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #4 from Zarathustra at gentlemansclub dot de  2007-02-21 10:16 -------
Now the code was also compiled with 4.3.0 and produced the same error message.

I can make the actual failure more specific: The following code compiles fine:

template<template<typename> class TOperator,typename TElement>
void for_all_5(TElement elem, cons_end tail);

template<template<typename> class TOperator,typename TElement, typename TTail>
void for_all_5(TElement elem, TTail tail)
{
  TOperator<TElement>()(elem);
  for_all_5<TOperator>(tail.elem,tail.tail);
}

template<template<typename> class TOperator,typename TElement>
void for_all_5(TElement elem, cons_end tail)
{
  TOperator<TElement>()(elem);
}

// -- snip -- //
in main:
for_all_5<op>(list.elem,list.tail);

The difference is the forward declaration of the second for_all method.
>From my understanding of the standard it is not necessary to do the forward
declaration since by 14.6.4/1 declarations which are visible at the point of
instantiation are to be considered and by 14.6.4.1/1 the point of 
instantiation of all template functions is at the definition of the main
function.


-- 

Zarathustra at gentlemansclub dot de changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Version|4.1.2                       |4.3.0


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30822


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug c++/30822] wrong choice of overloaded template functions in recursive call
  2007-02-16 12:09 [Bug c++/30822] New: wrong choice of overloaded template functions in recursive call Zarathustra at gentlemansclub dot de
                   ` (3 preceding siblings ...)
  2007-02-21 10:16 ` Zarathustra at gentlemansclub dot de
@ 2007-03-09  4:14 ` bangerth at dealii dot org
  2007-03-09 12:36 ` Zarathustra at gentlemansclub dot de
  2007-05-17 12:27 ` Zarathustra at gentlemansclub dot de
  6 siblings, 0 replies; 8+ messages in thread
From: bangerth at dealii dot org @ 2007-03-09  4:14 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #5 from bangerth at dealii dot org  2007-03-09 04:14 -------
Here's a reduced code:
-----------------
struct cons_end {};

template<typename U,typename V> struct cons {
    U elem;
    V tail;
};

template<class T,typename U, typename V>
void foo(U elem, V tail)
{
  foo<T>(tail.elem,tail.tail);
}

template<class T,typename U>
void foo(U elem, cons_end tail)
{}

int main()
{
  cons<int,cons<int,cons_end> > list;
  foo<int>(list.elem,list.tail);
}
--------------------

With gcc3.3, we get this error:

tmp/g> c++ -c x.cc
x.cc: In function `void foo(U, V) [with T = int, U = int, V = cons<int, 
   cons_end>]':
x.cc:21:   instantiated from here
x.cc:11: error: call of overloaded `foo(int&, cons_end&)' is ambiguous
x.cc:10: error: candidates are: void foo(U, V) [with T = int, U = int, V = 
   cons_end]
x.cc:16: error:                 void foo(U, cons_end) [with T = int, U = int]


On the other hand, gcc 4.1 produces this:
g/x> c++ -c x.cc
x.cc: In function 'void foo(U, V) [with T = int, U = int, V = cons_end]':
x.cc:11:   instantiated from 'void foo(U, V) [with T = int, U = int, V =
cons<int, cons_end>]'
x.cc:21:   instantiated from here
x.cc:11: error: 'struct cons_end' has no member named 'elem'
x.cc:11: error: 'struct cons_end' has no member named 'tail'


Finally, icc gives me this:
tmp/g> icc -c x.cc
x.cc(21): warning #592: variable "list" is used before its value is set
    foo<int>(list.elem,list.tail);
             ^

x.cc(11): error: more than one instance of overloaded function "foo" matches
the argument list:
            function template "foo<T,U,V>(U, V)"
            function template "foo<T,U>(U, cons_end)"
            argument types are: (int, cons_end)
    foo<T>(tail.elem,tail.tail);
    ^
          detected during instantiation of "void foo<T,U,V>(U, V) [with T=int,
U=int, V=cons<int, cons_end>]" 

compilation aborted for x.cc (code 2)


So, the way I read this is that gcc3.3 and icc9.0 agree that the call is
ambiguous. I must admit that I don't know whether this is the correct
behavior.

On the other hand, gcc4.1 appears to not find an ambiguity, then goes on to
unconditionally call the first function and there hits onto a problem.

W.


-- 

bangerth at dealii dot org changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bangerth at dealii dot org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30822


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug c++/30822] wrong choice of overloaded template functions in recursive call
  2007-02-16 12:09 [Bug c++/30822] New: wrong choice of overloaded template functions in recursive call Zarathustra at gentlemansclub dot de
                   ` (4 preceding siblings ...)
  2007-03-09  4:14 ` bangerth at dealii dot org
@ 2007-03-09 12:36 ` Zarathustra at gentlemansclub dot de
  2007-05-17 12:27 ` Zarathustra at gentlemansclub dot de
  6 siblings, 0 replies; 8+ messages in thread
From: Zarathustra at gentlemansclub dot de @ 2007-03-09 12:36 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #6 from Zarathustra at gentlemansclub dot de  2007-03-09 12:35 -------
(In reply to comment #5)
> So, the way I read this is that gcc3.3 and icc9.0 agree that the call is
> ambiguous. I must admit that I don't know whether this is the correct
> behavior.
Also the SunCC yields the ambiguity message. I think in all such cases the
compilers do not implement all rules for the look up of template names as given
by the standard. Probably starting from version 3.4.0 of gcc the error message
changes.

Perhaps it is worth taking a look at the following code:
One template argument is left away, and some "<>" are added.
foo2 is accepted, foo3 is not! From this I assume that there is some problem
with the implementation of the argument-dependent lookup (ADP) in gcc. Does
anyone have any other assumptions?

struct cons_end {};

template<typename U,typename V> struct cons {
 U elem;
 V tail;
};

template<typename U, typename V>
void foo2(U elem, V tail)
{
 foo2(tail.elem,tail.tail);
}

template<typename U>
void foo2(U elem, cons_end tail)
{}

template<typename U, typename V>
void foo3(U elem, V tail)
{
 foo3<>(tail.elem,tail.tail); // <-- the difference is here (<> added)
}

template<typename U>
void foo3(U elem, cons_end tail)
{}

int main()
{
 cons<int,cons<int,cons_end> > list;
 foo2(list.elem,list.tail);
 foo2<>(list.elem,list.tail);
 foo3(list.elem,list.tail);
}

The error message (from gcc 4.1.2 and gcc 4.3):
test_gccbug.cpp: In function "void foo3(U, V) [with U = int, V = cons_end]":
test_gccbug.cpp:32:   instantiated from "void foo3(U, V) [with U = int, V =
cons<int, cons_end>]"
test_gccbug.cpp:44:   instantiated from here
test_gccbug.cpp:32: error: "struct cons_end" has no member named "elem"
test_gccbug.cpp:32: error: "struct cons_end" has no member named "tail"

Volker


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30822


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug c++/30822] wrong choice of overloaded template functions in recursive call
  2007-02-16 12:09 [Bug c++/30822] New: wrong choice of overloaded template functions in recursive call Zarathustra at gentlemansclub dot de
                   ` (5 preceding siblings ...)
  2007-03-09 12:36 ` Zarathustra at gentlemansclub dot de
@ 2007-05-17 12:27 ` Zarathustra at gentlemansclub dot de
  6 siblings, 0 replies; 8+ messages in thread
From: Zarathustra at gentlemansclub dot de @ 2007-05-17 12:27 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #7 from Zarathustra at gentlemansclub dot de  2007-05-17 13:27 -------
According to my current understanding, the compiler is right not to accept the
given example code:
Name resolution at the point of instantiation does only work for dependent 
names.
Given a expression which looks like
"postfix-expression ( expression-listopt )"
"postfix-expression" is a dependent name if (and only if) some thing in 
"expression-listopt" depends on a template parameter and "postfix-expression" 
is an identifier. This holds for foo(...) but it does not hold for 
foo<...>(...) or ::foo(...). Therefore I assume the compiler behaves 
correctly. This is probably another case where the C++ standard is somehow
counterintuitive.


-- 

Zarathustra at gentlemansclub dot de changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|                            |INVALID


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30822


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2007-05-17 12:27 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-02-16 12:09 [Bug c++/30822] New: wrong choice of overloaded template functions in recursive call Zarathustra at gentlemansclub dot de
2007-02-16 15:47 ` [Bug c++/30822] " pinskia at gcc dot gnu dot org
2007-02-16 16:35 ` Zarathustra at gentlemansclub dot de
2007-02-21  7:44 ` Zarathustra at gentlemansclub dot de
2007-02-21 10:16 ` Zarathustra at gentlemansclub dot de
2007-03-09  4:14 ` bangerth at dealii dot org
2007-03-09 12:36 ` Zarathustra at gentlemansclub dot de
2007-05-17 12:27 ` Zarathustra at gentlemansclub dot de

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).