https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85765
Bug ID: 85765 Summary: Missing SFINAE in default template argument Product: gcc Version: 8.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: ensadc at mailnesia dot com Target Milestone: --- https://wandbox.org/permlink/lxHtJOjvghJiLiIO ---- struct il { il(); il(const il&); }; int* begin(il); template<class T> T&& declval(); template<class T, class U = decltype(begin(declval<T&>())), decltype(*U(),0) = 0> U g(T& t, long) { return begin(t); } // #1 template<class T> int g(T& t, ...); // #2 volatile il a; auto n = g(a, 0); // calls #1 and ends with a hard error, should call #2 ---- prog.cc: In instantiation of 'U g(T&, long int) [with T = volatile il; U = int*; decltype (((* U()), 0)) <anonymous> = 0]': prog.cc:15:16: required from here prog.cc:8:31: error: binding reference of type 'const il&' to 'volatile il' discards qualifiers U g(T& t, long) { return begin(t); } // #1 ~~~~~^~~ prog.cc:1:19: note: initializing argument 1 of 'il::il(const il&)' struct il { il(); il(const il&); }; ^~ prog.cc:3:6: note: initializing argument 1 of 'int* begin(il)' int* begin(il); ^~~~~ ---- #1 should be SFINAE'ed out because `declval<T&>()` (of type `volatile il&`) is not convertible to the parameter of `begin` (of type `il`), so #2 should called without causing an error. But instead g++ 8.1 selects #1 and emits a hard error. g++ 7.3 and before calls #2, as do Clang and MSVC. g++ 8 and later will call #2 if ", decltype(*U(),0) = 0" is removed.