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>...

Reply via email to