1 // RUN: %clang_cc1 -std=c++1z -verify %s
2 // RUN: %clang_cc1 -std=c++2a -verify %s
4 template<typename
...T
> constexpr auto sum(T
...t
) { return (... + t
); }
5 template<typename
...T
> constexpr auto product(T
...t
) { return (t
* ...); }
6 template<typename
...T
> constexpr auto all(T
...t
) { return (true && ... && t
); }
7 template<typename
...T
> constexpr auto dumb(T
...t
) { return (false && ... && t
); }
9 static_assert(sum(1, 2, 3, 4, 5) == 15);
10 static_assert(product(1, 2, 3, 4, 5) == 120);
11 static_assert(!all(true, true, false, true, false));
12 static_assert(all(true, true, true, true, true));
13 static_assert(!dumb(true, true, true, true, true));
18 template<typename
...T
> constexpr auto increment_all(T
&...t
) {
21 constexpr bool check() {
22 S s
= { 1, 2, 3, 4, 5 };
23 increment_all(s
.a
, s
.b
, s
.c
, s
.d
, s
.e
);
24 return s
.a
== 2 && s
.b
== 3 && s
.c
== 4 && s
.d
== 5 && s
.e
== 6;
26 static_assert(check());
28 template<int ...N
> void empty() {
29 static_assert((N
|| ...) == false);
30 static_assert((N
&& ...) == true);
33 template void empty
<>();
35 // An empty fold-expression isn't a null pointer just because it's an integer
36 // with value 0. (This is no longer an issue since empty pack expansions don't
37 // produce integers any more.)
38 template<int ...N
> void null_ptr() {
39 void *p
= (N
|| ...); // expected-error {{rvalue of type 'bool'}}
40 void *q
= (N
, ...); // expected-error {{rvalue of type 'void'}}
42 template void null_ptr
<>(); // expected-note {{in instantiation of}}
44 template<int ...N
> void bad_empty() {
45 (N
+ ...); // expected-error {{empty expansion for operator '+' with no fallback}}
46 (N
* ...); // expected-error {{empty expansion for operator '*' with no fallback}}
47 (N
| ...); // expected-error {{empty expansion for operator '|' with no fallback}}
48 (N
& ...); // expected-error {{empty expansion for operator '&' with no fallback}}
49 (N
- ...); // expected-error {{empty expansion for operator '-' with no fallback}}
50 (N
/ ...); // expected-error {{empty expansion for operator '/' with no fallback}}
51 (N
% ...); // expected-error {{empty expansion for operator '%' with no fallback}}
52 (N
= ...); // expected-error {{empty expansion for operator '=' with no fallback}}
54 template void bad_empty
<>(); // expected-note {{in instantiation of}}
56 template<int ...N
> void empty_with_base() {
58 (k
= ... = N
); // expected-warning{{unused}}
60 void (k
= ... = N
); // expected-error {{expected ')'}} expected-note {{to match}}
64 template void empty_with_base
<>(); // expected-note {{in instantiation of}}
65 template void empty_with_base
<1>();
76 template<typename T
, typename
...Ts
> constexpr decltype(auto) apply(T
&t
, Ts
...ts
) {
79 static_assert(&apply(a
, &A::b
, &A::B::c
, &A::B::C::d
, &A::B::C::D::e
) == &a
.b
.c
.d
.e
);
81 #if __cplusplus > 201703L
82 // The <=> operator is unique among binary operators in not being a
84 // FIXME: This diagnostic is not great.
85 template<typename
...T
> constexpr auto spaceship1(T
...t
) { return (t
<=> ...); } // expected-error {{expected expression}}
86 template<typename
...T
> constexpr auto spaceship2(T
...t
) { return (... <=> t
); } // expected-error {{expected expression}}
87 template<typename
...T
> constexpr auto spaceship3(T
...t
) { return (t
<=> ... <=> 0); } // expected-error {{expected expression}}
90 // The GNU binary conditional operator ?: is not recognized as a fold-operator.
91 // FIXME: Why not? This seems like it would be useful.
92 template<typename
...T
> constexpr auto binary_conditional1(T
...t
) { return (t
?: ...); } // expected-error {{expected expression}}
93 template<typename
...T
> constexpr auto binary_conditional2(T
...t
) { return (... ?: t
); } // expected-error {{expected expression}}
94 template<typename
...T
> constexpr auto binary_conditional3(T
...t
) { return (t
?: ... ?: 0); } // expected-error {{expected expression}}
97 template <int I
> struct Constant
{};
99 template <int... Is
> struct Sum
{
100 template <int... Js
> using type
= Constant
<((Is
+ Js
) + ... + 0)>; // expected-error {{pack expansion contains parameter pack 'Js' that has a different length (1 vs. 2) from outer parameter packs}}
103 Sum
<1>::type
<1, 2> x
; // expected-note {{instantiation of}}
112 void operator+(N::S
, N::S
) {}
113 template<typename
...Ts
> void f() { (Ts
{} + ...); }
116 void g() { T::f
<N::S
, N::S
>(); }
118 template<typename T
, typename
...U
> auto h(U
...v
) {
119 T
operator+(T
, T
); // expected-note {{candidate}}
120 return (v
+ ...); // expected-error {{invalid operands}}
122 int test_h1
= h
<N::S
>(1, 2, 3);
123 N::S test_h2
= h
<N::S
>(N::S(), N::S(), N::S());
124 int test_h3
= h
<struct X
>(1, 2, 3);
125 N::S test_h4
= h
<struct X
>(N::S(), N::S(), N::S()); // expected-note {{instantiation of}}
132 template <typename
... T
>
133 void g(bool = (f
<T
>() || ...));