Topic: Call to overloaded operator of template class ambiguous?


Author: unknown@this.is.invalid ("Niels Dekker (no reply address)")
Date: Sun, 8 Aug 2004 23:21:11 GMT
Raw View
> GNU 3.4.1 says that the operator call in the following program is an
> error against ISO C++.  However, both MSVC++ 7.1 and Comeau C++ 4.3.3
> (online) accept the program.

Bart van Ingen Schenau replied:
> My take on this is that MSVC++ and Comeau are correct, the program is
> well-formed.
>
> The viable candidates for the call are
> 1. Foo<T>::operator <=(U), with [ T = char, U = Foo<int> ]
> 2. operator <=(U, Foo<T>), with [ T = int, U = Foo<char> ]
> 3. operator <=(Foo<U>, Foo<T>), with [ T = int, U = char ]
>
> Because all template instantiations form an exact match, the partial
> ordering rules for templates start to play a role.
> The third overload is preferred, because that operator is the most
> specialised template instantiation.

Thanks!  So it's a GNU bug!  But now I got even "closer to ambiguity",
by defining the left operand (c) as "const".  Is it still well-formed?
As follows:

  #include <cstdlib>

  template <typename T> class Foo
  {
  public:
    Foo<T>(void) {}
    template <typename U> bool operator<=(U) const;
    bool operator<=(Foo<T>) const;
  };

  template <typename T, typename U> bool operator<=(U, Foo<T>);

  template <typename T, typename U> bool operator<=(Foo<U>, Foo<T>)
  {
    return true;
  }

  int main(void)
  {
    const Foo<char> c;  // Now defined as "const"!
    Foo<int> i;

    return (c <= i) ? EXIT_SUCCESS : EXIT_FAILURE;  // error???
  }

Now MSVC++ and Comeau (online) still accept the program, while Borland
joins GNU, rejecting the operator call.

Borland C++ 5.5.1 says:
Error E2015 Foo.cpp 23: Ambiguity between
 'operator <= <int,char>(Foo<char>,Foo<int>)' and
 'operator <= <Foo<int> >(Foo<int>) const' in function main()

GNU no longer refers to ISO C++ (now that I added the "const"), but
still it says:
Foo.cpp: In function `int main()':
Foo.cpp:23: error: ambiguous overload for 'operator<=' in 'c <= i'
Foo.cpp:7: note: candidates are:
  bool Foo<T>::operator<=(U) const [with U = Foo<int>, T = char]
Foo.cpp:11: note:
  bool operator<=(U, Foo<T>) [with T = int, U = Foo<char>]
Foo.cpp:14: note:
  bool operator<=(Foo<U>, Foo<T>) [with T = int, U = char]

So is it indeed ambiguous, by now?

Your help is appreciated,

    Niels Dekker
    www.xs4all.nl/~nd/dekkerware

---
[ 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: Bart.van.Ingen.Schenau@ict.nl (Bart van Ingen Schenau)
Date: Fri, 6 Aug 2004 18:23:59 GMT
Raw View
On Sat, 31 Jul 2004 17:00:35 GMT, nospam@this.is.invalid ("Niels
Dekker (no reply address)") wrote:

>GNU 3.4.1 says that the operator call in the following program is an
>error against ISO C++.  However, both MSVC++ 7.1 and Comeau C++ 4.3.3
>(online) accept the program.  So please tell me if the program is
>according to the Standard.  The main function is meant to return
>EXIT_SUCCESS, of course.
>
>  #include <cstdlib>
>
>  template <typename T> class Foo
>  {
>  public:
>    template <typename U> bool operator<=(U) const;
>    bool operator<=(Foo<T>) const;
>  };
>
>  template <typename T, typename U> bool operator<=(U, Foo<T>);
>
>  template <typename T, typename U> bool operator<=(Foo<U>, Foo<T>)
>  {
>    return true;
>  }
>
>  int main(void)
>  {
>    Foo<char> c;
>    Foo<int> i;
>
>    return (c <= i) ? EXIT_SUCCESS : EXIT_FAILURE;  // error???
>  }
>
>The GNU error message is:
>Foo.cpp:22: error: ISO C++ says that these are ambiguous, even though
>the worst conversion for the first is better than the worst conversion
>for the second:
>Foo.cpp:13: note: candidate 1: bool operator<=(Foo<U>, Foo<T>)
> [with T = int, U = char]
>Foo.cpp:6: note: candidate 2: bool Foo<T>::operator<=(U) const
> [with U = Foo<int>, T = char]
>
>There's no diagnostic from either MSVC++ or Comeau.

My take on this is that MSVC++ and Comeau are correct, the program is
well-formed.

The viable candidates for the call are
1. Foo<T>::operator <=(U), with [ T = char, U = Foo<int> ]
2. operator <=(U, Foo<T>), with [ T = int, U = Foo<char> ]
3. operator <=(Foo<U>, Foo<T>), with [ T = int, U = char ]

Because all template instantiations form an exact match, the partial
ordering rules for templates start to play a role.
The third overload is preferred, because that operator is the most
specialised template instantiation.

>
>I posted a simular question on comp.lang.c++.moderated in February, but
>I need to have a second opinion!
>
>Thanks in advance,
>
>  Niels Dekker
>  www.xs4all.nl/~nd/dekkerware
>
Bart v Ingen Schenau

---
[ 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: nospam@this.is.invalid ("Niels Dekker (no reply address)")
Date: Sat, 31 Jul 2004 17:00:35 GMT
Raw View
GNU 3.4.1 says that the operator call in the following program is an
error against ISO C++.  However, both MSVC++ 7.1 and Comeau C++ 4.3.3
(online) accept the program.  So please tell me if the program is
according to the Standard.  The main function is meant to return
EXIT_SUCCESS, of course.

  #include <cstdlib>

  template <typename T> class Foo
  {
  public:
    template <typename U> bool operator<=(U) const;
    bool operator<=(Foo<T>) const;
  };

  template <typename T, typename U> bool operator<=(U, Foo<T>);

  template <typename T, typename U> bool operator<=(Foo<U>, Foo<T>)
  {
    return true;
  }

  int main(void)
  {
    Foo<char> c;
    Foo<int> i;

    return (c <= i) ? EXIT_SUCCESS : EXIT_FAILURE;  // error???
  }

The GNU error message is:
Foo.cpp:22: error: ISO C++ says that these are ambiguous, even though
the worst conversion for the first is better than the worst conversion
for the second:
Foo.cpp:13: note: candidate 1: bool operator<=(Foo<U>, Foo<T>)
 [with T = int, U = char]
Foo.cpp:6: note: candidate 2: bool Foo<T>::operator<=(U) const
 [with U = Foo<int>, T = char]

There's no diagnostic from either MSVC++ or Comeau.

I posted a simular question on comp.lang.c++.moderated in February, but
I need to have a second opinion!

Thanks in advance,

  Niels Dekker
  www.xs4all.nl/~nd/dekkerware

---
[ 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                       ]