[cfe-dev] Templated operator overloading

Richard Smith richard at metafoo.co.uk
Thu May 22 14:45:44 PDT 2014


On Thu, May 22, 2014 at 1:12 AM, <antoni at buszta.info> wrote:

> Hi all,
>
> I have some small problem with clang behavior in such code:
>
> struct stream
> {
>     stream() {}
>     template<typename T>
>     inline stream& operator<<(T& t)
>     {
>         return *this;
>     }
> };
>
> template<typename Stream>
> inline Stream& operator<<(Stream& stream, int& t)
> {
>     return stream;
> }
>
> int main(int argc, char *argv[])
> {
>     int i = 42;
>     stream a;
>     a << i;
>
>     return 0;
> }
>
> This code compiles fine under clang (I have checked with 3.4 and current
> trunk) and gcc. However when I add -std=c++11 it still compiles fine under
> gcc but it stops compiling under clang. Error is:
>
> /home/abuszta/Development/llvm/bin/clang++ -std=c++11    operator.cpp
> -o operator
> operator.cpp:21:7: error: use of overloaded operator '<<' is ambiguous
> (with operand types 'stream' and 'int')
>     a << i;
>     ~ ^  ~
> operator.cpp:5:20: note: candidate function [with T = int]
>     inline stream& operator<<(T& t)
>                    ^
> operator.cpp:12:16: note: candidate function [with Stream = stream]
> inline Stream& operator<<(Stream& stream, int& t)
>                ^
> 1 error generated.
>

See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#532

Deduction succeeds for both function templates, and neither candidate is
better than the other based on implicit conversion sequences, so we perform
partial ordering on the function templates. Per 14.5.6.2, we perform
partial ordering on these signatures:

stream &(stream &, T &) // member
Stream &(Stream &, int &) // non-member

These are unordered, so the call is ambiguous.

In C++98 mode, we don't implement DR532, and instead only consider the
second parameter. That's arguably misguided, since the wording prior to
DR532 was simply broken (in particular, it didn't say that we ignore the
first parameter from the non-member, which is what we do in C++98 mode),
and we'd be better off using the C++11 rule rather than making up a
different rule.

Apparently GCC doesn't implement DR532 in any mode.

In order to answer the question which behavior is good and which is bad I
> tried to find appropriate section in C++ standard. After analyzing 14.5.6.2
> (section about Partial ordering of function templates in N3337) and related
> I think there should not be any ambiguity after substitution and function
> should be choosed...
>
> What is more, when I make const stream a; this code compiles fine even
> with -std=c++11 and chooses the standalone function in favor to member
> function which suggests that there may be some problem with template
> resolution here.
>
> What is your interpretation of this behavior? Should I report bug?


This is a GCC bug. And possibly a bug in Clang's C++98 mode, depending on
your point of view.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20140522/9b747c03/attachment.html>


More information about the cfe-dev mailing list