[Bug c++/30822] wrong choice of overloaded template functions in recursive call
--- 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
[Bug c++/30822] wrong choice of overloaded template functions in recursive call
--- 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 {}; templatetypename U,typename V struct cons { U elem; V tail; }; templatetypename U, typename V void foo2(U elem, V tail) { foo2(tail.elem,tail.tail); } templatetypename U void foo2(U elem, cons_end tail) {} templatetypename U, typename V void foo3(U elem, V tail) { foo3(tail.elem,tail.tail); // -- the difference is here ( added) } templatetypename U void foo3(U elem, cons_end tail) {} int main() { consint,consint,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 = consint, 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
[Bug c++/30822] wrong choice of overloaded template functions in recursive call
--- Comment #5 from bangerth at dealii dot org 2007-03-09 04:14 --- Here's a reduced code: - struct cons_end {}; templatetypename U,typename V struct cons { U elem; V tail; }; templateclass T,typename U, typename V void foo(U elem, V tail) { fooT(tail.elem,tail.tail); } templateclass T,typename U void foo(U elem, cons_end tail) {} int main() { consint,consint,cons_end list; fooint(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 = consint, 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 = consint, 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 fooint(list.elem,list.tail); ^ x.cc(11): error: more than one instance of overloaded function foo matches the argument list: function template fooT,U,V(U, V) function template fooT,U(U, cons_end) argument types are: (int, cons_end) fooT(tail.elem,tail.tail); ^ detected during instantiation of void fooT,U,V(U, V) [with T=int, U=int, V=consint, 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
[Bug c++/30822] wrong choice of overloaded template functions in recursive call
--- 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: templatetemplatetypename class TOperator,typename TElement void for_all_5(TElement elem, cons_end tail); templatetemplatetypename class TOperator,typename TElement, typename TTail void for_all_5(TElement elem, TTail tail) { TOperatorTElement()(elem); for_all_5TOperator(tail.elem,tail.tail); } templatetemplatetypename class TOperator,typename TElement void for_all_5(TElement elem, cons_end tail) { TOperatorTElement()(elem); } // -- snip -- // in main: for_all_5op(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
[Bug c++/30822] wrong choice of overloaded template functions in recursive call
--- 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
[Bug c++/30822] wrong choice of overloaded template functions in recursive call
--- 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
[Bug c++/30822] wrong choice of overloaded template functions in recursive call
--- 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