https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77660
Bug ID: 77660 Summary: Conversion operator unknown or ambiguous: gcc or clang behave differently Product: gcc Version: 5.4.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: naupacte at sfr dot fr Target Milestone: --- In relation with bug #50306: (using gcc5.4.1 or gcc6.1 from macports) struct A; struct B; template <class T> struct Ptr { template <class U> operator const Ptr<U>& () const; #ifdef GCC_BUT_CLANG_DECLARES_IT_IS_AMBIGUOUS template <class U> operator Ptr<U> () const; // required by gcc but skipped for clang #endif }; const Ptr<A>& foo1 (const Ptr<B>& b) { return b;}//gcc ok Ptr<A> foo2 (const Ptr<B>& b) { return b;}// needs GCC_BUT_CLANG_DECLARES_IT_IS_AMBIGUOUS to be set Ptr<A> foo2a(const Ptr<B>& b) { return static_cast<Ptr<A>>(b);} //gcc patch Who is right? Gcc cannot convert from const Ptr<B>& to Ptr<A> via const Ptr<A>&. I guess it has an influence on its inability to get the common type for brace-lists or ?: pairs when only the reference conversion is given. To avoid error: define GCC_BUT_CLANG_DECLARES_IT_IS_AMBIGUOUS only for gcc. Otherwise, we get: GCC ==== /opt/local/bin/gcc-mp-6 -x c++ -std=c++1y -c program.cpp program.cpp: In function 'Ptr<A> foo2(const Ptr<B>&)': program.cpp:22:47: error: could not convert 'b' from 'const Ptr<B>' to 'Ptr<A>' Ptr<A> foo2 (const Ptr<B>& b) { return b;}// needs GCC_BUT_CLANG_DECLARES_IT_IS_AMBIGUOUS to be set CLANG ===== clang-mp-3.8 -x c++ -std=c++1y -c program.cpp -DGCC_BUT_CLANG_DECLARES_IT_IS_AMBIGUOUS program.cpp:22:47: error: conversion from 'const Ptr<B>' to 'Ptr<A>' is ambiguous Ptr<A> foo2 (const Ptr<B>& b) { return b;}// needs GCC_BUT_CLANG_DECLARES_IT_IS_AMBIGUOUS to be set ^ program.cpp:13:76: note: candidate function [with U = A] template <class U> operator const Ptr<U>& () const; ^ program.cpp:15:76: note: candidate function [with U = A] template <class U> operator Ptr<U> () const; ^ program.cpp:23:47: error: ambiguous conversion for static_cast from 'const Ptr<B>' to 'Ptr<A>' Ptr<A> foo2a(const Ptr<B>& b) { return static_cast<Ptr<A>>(b);} //gcc patch ^~~~~~~~~~~~~~~~~~~~~~ program.cpp:11:27: note: candidate is the implicit copy constructor template <class T> struct Ptr ^ program.cpp:11:27: note: candidate is the implicit move constructor 2 errors generated.