http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56782
Bug #: 56782 Summary: [C++11] Regression with empty pack expansions Classification: Unclassified Product: gcc Version: 4.8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: daniel.krueg...@googlemail.com As of gcc 4.8.0 the following code is now rejected when compiled with flags -std=c++11 -Wall -W -pedantic //--------------------------- template<class T> T&& declval(); struct is_convertible_impl { template<class T> static void sink(T); template<class T, class U, class = decltype(sink<U>(declval<T>()))> static auto test(int) -> char; template<class, class> static auto test(...) -> char(&)[2]; }; template<class T, class U> struct is_convertible : is_convertible_impl { static const bool value = sizeof(test<T, U>(0)) == 1; }; template<bool, class> struct enable_if {}; template<class T> struct enable_if<true, T> { typedef T type; }; template<bool, class If, class Else> struct conditional { typedef If type; }; template<class If, class Else> struct conditional<false, If, Else> { typedef Else type; }; template<class...> struct and_; template<> struct and_<> { static const bool value = true; }; template<class P> struct and_<P> : P { }; template<class P1, class P2> struct and_<P1, P2> : conditional<P1::value, P2, P1>::type { }; template<class... T> struct Tuple { template<class... U, class = typename enable_if<and_< is_convertible<U, T>... >::value, int>::type > Tuple(U&&...){} }; static_assert(is_convertible<Tuple<int>, Tuple<int>>::value, "Ouch"); // OK static_assert(is_convertible<Tuple<>, Tuple<>>::value, "Ouch"); // Error //--------------------------- The diagnostics being: " Compilation finished with errors: source.cpp:18:48: error: template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum) substituting 'template<class, class> static char (& is_convertible_impl::test(...))[2] [with <template-parameter-1-1> = Tuple<>; <template-parameter-1-2> = Tuple<>]' static const bool value = sizeof(test<T, U>(0)) == 1; ^ source.cpp:55:5: recursively required from 'const bool is_convertible<Tuple<>, Tuple<> >::value' source.cpp:55:5: required from 'const bool is_convertible<Tuple<>, Tuple<> >::value' source.cpp:64:49: required from here source.cpp:18:48: error: no matching function for call to 'is_convertible<Tuple<>, Tuple<> >::test(int)' source.cpp:18:48: note: candidates are: source.cpp:9:15: note: template<class T, class U, class> static char is_convertible_impl::test(int) static auto test(int) -> char; ^ source.cpp:9:15: note: template argument deduction/substitution failed: source.cpp:12:15: note: template<class, class> static char (& is_convertible_impl::test(...))[2] static auto test(...) -> char(&)[2]; ^ source.cpp:12:15: note: substitution of deduced template arguments resulted in errors seen above source.cpp:64:1: error: non-constant condition for static assertion static_assert(is_convertible<Tuple<>, Tuple<>>::value, "Ouch"); // Error ^ source.cpp:64:1: error: the value of 'is_convertible<Tuple<>, Tuple<> >::value' is not usable in a constant expression source.cpp:18:21: note: 'is_convertible<Tuple<>, Tuple<> >::value' was not initialized with a constant expression static const bool value = sizeof(test<T, U>(0)) == 1; ^ " The code is accepted with gcc 4.7.2 and with Clang 3.2. It seems that for empty expansions the compiler erroneously does enter into the actually empty expansion: is_convertible<U, T>...