[Bug c++/56782] New: [C++11] Regression with empty pack expansions
daniel.kruegler at googlemail dot com
gcc-bugzilla@gcc.gnu.org
Fri Mar 29 13:44:00 GMT 2013
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: unassigned@gcc.gnu.org
ReportedBy: daniel.kruegler@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>...
More information about the Gcc-bugs
mailing list