Bug 53162 - unexpanded parameter packs not diagnosed in alias template used in default argument
Summary: unexpanded parameter packs not diagnosed in alias template used in default ar...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.8.0
: P3 normal
Target Milestone: 5.0
Assignee: Not yet assigned to anyone
URL:
Keywords: accepts-invalid, diagnostic
Depends on:
Blocks:
 
Reported: 2012-04-30 00:50 UTC by Jonathan Wakely
Modified: 2015-03-25 20:33 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jonathan Wakely 2012-04-30 00:50:10 UTC
template<bool B>
struct bool_constant
{
  static const bool value = B;
};

template<bool> struct enable_if { };
template<> struct enable_if<true> { typedef void type; };

template<typename... A>
struct F
{
  template<typename... B>
    using SameSize = bool_constant<sizeof...(A) == sizeof...(B)>;

  template<typename... B,
           typename = SameSize<B>>
  F(int, B...) { }

  template<typename... B,
           typename = typename enable_if<SameSize<B>::value>::type>
  F(char, B...) { }
};

int main()
{
  F<int, int> f1(1, 2, 3);
  F<int, int> f2('1', 2, 3);
}

$ g++ -std=c++11 t.cc
t.cc: In instantiation of ‘struct F<int, int>’:
t.cc:27:17:   required from here
t.cc:22:3: error: no type named ‘type’ in ‘struct enable_if<false>’
   F(char, B...) { }
   ^

The declaration of f1 should be rejected because the F(int, B...) constructor's default template argument refers to the parameter pack B without expanding it, but there is no error.

The declaration of f1 is rejected but with an unhelpful diagnostic, if the problem was that there's no 'type' in enable_if then it should result in a substitution failure not an error. The actual problem is that B is not expanded in SameSize<B>, so the error should say so.
Comment 1 Jonathan Wakely 2012-04-30 08:12:44 UTC
(In reply to comment #0)
> The declaration of f1 is rejected but with an unhelpful diagnostic, if the
                     ^^
That should say:     f2

I believe the errors should be given when the constructor templates are defined, rather than at instantiation, because "An appearance of a name of a parameter pack that is not expanded is ill-formed." (14.5.3 [temp.variadic] p5)
Comment 2 Paolo Carlini 2015-03-25 19:42:52 UTC
Jon, this seems fixed to me in 5.0.
Comment 3 Jonathan Wakely 2015-03-25 20:33:23 UTC
Yes, the unexpanded packs are diagnosed now:

f.cc:17:23: error: parameter packs not expanded with ‘...’:
            typename = SameSize<B>>
                       ^
f.cc:17:23: note:         ‘B’
f.cc:21:63: error: parameter packs not expanded with ‘...’:
            typename = typename enable_if<SameSize<B>::value>::type>
                                                               ^
f.cc:21:63: note:         ‘B’

And the constructors are not viable, so fixed.


Oddly, if I fixed the error in the original testcase (so trunk accepts it) then both clang and EDG reject it, but I think they're wrong:

template<bool B>
struct bool_constant
{
  static const bool value = B;
};

template<bool> struct enable_if { };
template<> struct enable_if<true> { typedef void type; };

template<typename... A>
struct F
{
  template<typename... B>
    using SameSize = bool_constant<sizeof...(A) == sizeof...(B)>;

  template<typename... B,
           typename = typename enable_if<SameSize<B...>::value>::type>
  F(B...) { }
};

int main()
{
  F<int, int> f2(2, 3);
}