https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70737
Matteo Italia <matteo at mitalia dot net> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |matteo at mitalia dot net --- Comment #2 from Matteo Italia <matteo at mitalia dot net> --- Templates don't seem to have a relevant role here, I found that this simpler test case exhibits the same problem: struct A { explicit operator bool(); operator int(); operator double(); }; bool foo(A& a) { return a; } bool bar(A& a) { return bool(a); } As in Andrea's example, `foo`'s code is not valid, since `operator bool` is disabled (it's marked as explicit), and it's ambiguous whether `operator int` or `operator double` should be invoked. clang correctly refuses to compile this snippet (https://godbolt.org/g/lZa2Qx), while all gcc>=4.6 (and <=6.1) I tried on gcc.godbolt.org compile `foo` to a no-op function (`rep ret` on x86), thus leading to garbage being returned: foo(A&): rep ret bar(A&): jmp A::operator bool() (https://godbolt.org/g/xmrMGN) (here -O3 optimizes the tail call and removes some stack setup/cleanup noise, but the problem is present at all optimization levels) So, the core of the bug seems to be that gcc discards completely a conversion that becomes ambiguous once the "obvious" candidate is discarded for being marked as `explicit`. The gcc 4 series at least issued a dubious "warning: control reaches end of non-void function [-Wreturn-type]", from gcc 5 onwards even this warning disappeared (although, this may save you in this artificial example, in my original code gcc dropped a conditional assignment to an already-initialized variable, so the issue was completely silent).