[Bug c++/11340] New: Overload Resolution Failure Vis-a-Vis Broken Signature

mstaley at lanl dot gov gcc-bugzilla@gcc.gnu.org
Thu Jun 26 21:52:00 GMT 2003


PLEASE REPLY TO gcc-bugzilla@gcc.gnu.org ONLY, *NOT* gcc-bugs@gcc.gnu.org.

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

           Summary: Overload Resolution Failure Vis-a-Vis Broken Signature
           Product: gcc
           Version: 3.4
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: c++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: mstaley at lanl dot gov
                CC: gcc-bugs at gcc dot gnu dot org

This new bug report is related to my old c++/5732 bug report. That bug was
supposedly fixed with the new parser in g++ 3.4. Unfortunately, it seems that
the bug, like a zombie, stuck around in some form or another even after it was
supposed to be dead.

Consider the following code:

     #include <iostream>

     template<class T>
     T fun(const T &)
     {
        std::cout << "fun #1" << std::endl;
        return 0;
     }

     template<class T>
     typename T::value_type fun(const T &)
     {
        std::cout << "fun #2" << std::endl;
        return 0;
     }

     int main(void)
     {
        fun(1);
     }

This is legal C++. The two function templates differ in return type alone, which
is illegal for functions, but okay for function templates. Here, the return type
for fun #2, T::value_type, breaks for T == int. Because its return type breaks,
and because a return type is part of a function template's signature, fun #2 is
excluded from the list of candidates for overload resolution. Therefore, there
is no ambiguity in the call fun(1). The call matches exclusively with the first
function template. The second candidate is excluded from consideration before
the overload resolution phase is entered.

G++ 3.3 and earlier did not compile the above code. Instead, they produced the
following diagnostic:

     file.cc:12: new declaration `template<class T> T::value_type fun(const T&)'
     file.cc:5: ambiguates old declaration `template<class T> T fun(const T&)'

Yesterday (25.6.2003) I got the latest g++ 3.4 snapshot. G++ 3.4 compiles the
above code, as it should. However, let's now obfuscate the return types a bit:

     #include <iostream>

     template<int a, int b> class same { };
     template<int a> class same<a,a> { public: static const int result = a; };

     template<int n>
     class foo { public: typedef double value_type; };

     template<int n>
     class bar { public: static const int num = n; };

     template<class X>
     typename foo<same<1,X::num>::result>::value_type fun(const X &)
     {
        std::cout << "fun #1" << std::endl;
        return 0;
     }

     template<class X>
     typename foo<same<2,X::num>::result>::value_type fun(const X &)
     {
        std::cout << "fun #2" << std::endl;
        return 0;
     }

     int main(void)
     {
        bar<1> b;
        fun(b);
     }

b is of type bar<1>, and bar<1>::num is 1. same<1,1>::result makes sense, but
same<2,1>::result breaks. So, this example is morally equivalent to the first
example: the return type of the second instance of the function template breaks.
It breaks in a less direct way, but it breaks nonetheless. Unfortunately, g++
3.4 now says:

     file.cc: In function `int main()':
     file.cc:29: error: `result' is not a member of type `same<2, 1>'

But I'm betting my second code is legal C++. The fact that part of a function
template's signature (in this example its return type) breaks for a particular
proposed instantiation is not an error; it just means that the function template
in question is excluded from the upcoming overload resolution phase. Once
excluded, the calls matches exclusively with one instance of one function
template, namely the first "fun" with X == bar<1>. For what it's worth, both
Intel C++ and KAI C++, the latter of which I usually trust, compile this code.

It's worthwhile to note that the diagnostic produced by g++ 3.3 and earlier on
the first example is fundamentally different than the diagnostic produced by
g++ 3.4 on the second example: 3.3 complains about ambiguity, 3.4 complains
about the return type breaking. But in a large code of mine, in which certain
return types are much more obfuscated than they are in my second example here,
3.4 instead complained about ambiguity. Unfortunately, I was unable to make a
short example illustrating that diagnostic from 3.4. Either way, I'm thinking
there is neither an ambiguity, nor an a-priori error with a broken return type.

Martin



More information about the Gcc-bugs mailing list