xref: /llvm-project/libcxx/test/std/utilities/function.objects/func.not_fn/not_fn.nttp.pass.cpp (revision c91d805e6627987bec8ec34ea67c1e8240940039)
1*c91d805eSJakub Mazurkiewicz //===----------------------------------------------------------------------===//
2*c91d805eSJakub Mazurkiewicz //
3*c91d805eSJakub Mazurkiewicz // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*c91d805eSJakub Mazurkiewicz // See https://llvm.org/LICENSE.txt for license information.
5*c91d805eSJakub Mazurkiewicz // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*c91d805eSJakub Mazurkiewicz //
7*c91d805eSJakub Mazurkiewicz //===----------------------------------------------------------------------===//
8*c91d805eSJakub Mazurkiewicz 
9*c91d805eSJakub Mazurkiewicz // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
10*c91d805eSJakub Mazurkiewicz 
11*c91d805eSJakub Mazurkiewicz // <functional>
12*c91d805eSJakub Mazurkiewicz 
13*c91d805eSJakub Mazurkiewicz // template<auto f> constexpr unspecified not_fn() noexcept;
14*c91d805eSJakub Mazurkiewicz 
15*c91d805eSJakub Mazurkiewicz #include <functional>
16*c91d805eSJakub Mazurkiewicz 
17*c91d805eSJakub Mazurkiewicz #include <bit>
18*c91d805eSJakub Mazurkiewicz #include <cassert>
19*c91d805eSJakub Mazurkiewicz #include <concepts>
20*c91d805eSJakub Mazurkiewicz #include <type_traits>
21*c91d805eSJakub Mazurkiewicz #include <utility>
22*c91d805eSJakub Mazurkiewicz 
23*c91d805eSJakub Mazurkiewicz #include "test_macros.h"
24*c91d805eSJakub Mazurkiewicz 
25*c91d805eSJakub Mazurkiewicz class BooleanTestable {
26*c91d805eSJakub Mazurkiewicz   bool val_;
27*c91d805eSJakub Mazurkiewicz 
28*c91d805eSJakub Mazurkiewicz public:
29*c91d805eSJakub Mazurkiewicz   constexpr explicit BooleanTestable(bool val) : val_(val) {}
30*c91d805eSJakub Mazurkiewicz   constexpr operator bool() const { return val_; }
31*c91d805eSJakub Mazurkiewicz   constexpr BooleanTestable operator!() const { return BooleanTestable{!val_}; }
32*c91d805eSJakub Mazurkiewicz };
33*c91d805eSJakub Mazurkiewicz 
34*c91d805eSJakub Mazurkiewicz LIBCPP_STATIC_ASSERT(std::__boolean_testable<BooleanTestable>);
35*c91d805eSJakub Mazurkiewicz 
36*c91d805eSJakub Mazurkiewicz class FakeBool {
37*c91d805eSJakub Mazurkiewicz   int val_;
38*c91d805eSJakub Mazurkiewicz 
39*c91d805eSJakub Mazurkiewicz public:
40*c91d805eSJakub Mazurkiewicz   constexpr FakeBool(int val) : val_(val) {}
41*c91d805eSJakub Mazurkiewicz   constexpr FakeBool operator!() const { return FakeBool{-val_}; }
42*c91d805eSJakub Mazurkiewicz   constexpr bool operator==(int other) const { return val_ == other; }
43*c91d805eSJakub Mazurkiewicz };
44*c91d805eSJakub Mazurkiewicz 
45*c91d805eSJakub Mazurkiewicz template <bool IsNoexcept>
46*c91d805eSJakub Mazurkiewicz struct MaybeNoexceptFn {
47*c91d805eSJakub Mazurkiewicz   bool operator()() const noexcept(IsNoexcept); // not defined
48*c91d805eSJakub Mazurkiewicz };
49*c91d805eSJakub Mazurkiewicz 
50*c91d805eSJakub Mazurkiewicz template <bool IsNoexcept>
51*c91d805eSJakub Mazurkiewicz struct MaybeNoexceptNegation {
52*c91d805eSJakub Mazurkiewicz   bool operator!() noexcept(IsNoexcept); // not defined
53*c91d805eSJakub Mazurkiewicz };
54*c91d805eSJakub Mazurkiewicz 
55*c91d805eSJakub Mazurkiewicz template <bool IsNoexcept>
56*c91d805eSJakub Mazurkiewicz MaybeNoexceptNegation<IsNoexcept> maybe_noexcept_negation() noexcept {
57*c91d805eSJakub Mazurkiewicz   return {};
58*c91d805eSJakub Mazurkiewicz }
59*c91d805eSJakub Mazurkiewicz 
60*c91d805eSJakub Mazurkiewicz constexpr void basic_tests() {
61*c91d805eSJakub Mazurkiewicz   { // Test constant functions
62*c91d805eSJakub Mazurkiewicz     auto false_fn = std::not_fn<std::false_type{}>();
63*c91d805eSJakub Mazurkiewicz     assert(false_fn());
64*c91d805eSJakub Mazurkiewicz 
65*c91d805eSJakub Mazurkiewicz     auto true_fn = std::not_fn<std::true_type{}>();
66*c91d805eSJakub Mazurkiewicz     assert(!true_fn());
67*c91d805eSJakub Mazurkiewicz 
68*c91d805eSJakub Mazurkiewicz     static_assert(noexcept(std::not_fn<std::false_type{}>()));
69*c91d805eSJakub Mazurkiewicz     static_assert(noexcept(std::not_fn<std::true_type{}>()));
70*c91d805eSJakub Mazurkiewicz   }
71*c91d805eSJakub Mazurkiewicz 
72*c91d805eSJakub Mazurkiewicz   { // Test function with one argument
73*c91d805eSJakub Mazurkiewicz     auto is_odd = std::not_fn<[](auto x) { return x % 2 == 0; }>();
74*c91d805eSJakub Mazurkiewicz     assert(is_odd(1));
75*c91d805eSJakub Mazurkiewicz     assert(!is_odd(2));
76*c91d805eSJakub Mazurkiewicz     assert(is_odd(3));
77*c91d805eSJakub Mazurkiewicz     assert(!is_odd(4));
78*c91d805eSJakub Mazurkiewicz     assert(is_odd(5));
79*c91d805eSJakub Mazurkiewicz   }
80*c91d805eSJakub Mazurkiewicz 
81*c91d805eSJakub Mazurkiewicz   { // Test function with multiple arguments
82*c91d805eSJakub Mazurkiewicz     auto at_least_10 = [](auto... vals) { return (vals + ... + 0) >= 10; };
83*c91d805eSJakub Mazurkiewicz     auto at_most_9   = std::not_fn<at_least_10>();
84*c91d805eSJakub Mazurkiewicz     assert(at_most_9());
85*c91d805eSJakub Mazurkiewicz     assert(at_most_9(1));
86*c91d805eSJakub Mazurkiewicz     assert(at_most_9(1, 2, 3, 4, -1));
87*c91d805eSJakub Mazurkiewicz     assert(at_most_9(3, 3, 2, 1, -2));
88*c91d805eSJakub Mazurkiewicz     assert(!at_most_9(10, -1, 2));
89*c91d805eSJakub Mazurkiewicz     assert(!at_most_9(5, 5));
90*c91d805eSJakub Mazurkiewicz     static_assert(noexcept(std::not_fn<at_least_10>()));
91*c91d805eSJakub Mazurkiewicz   }
92*c91d805eSJakub Mazurkiewicz 
93*c91d805eSJakub Mazurkiewicz   { // Test function that returns boolean-testable type other than bool
94*c91d805eSJakub Mazurkiewicz     auto is_product_even = [](auto... vals) { return BooleanTestable{(vals * ... * 1) % 2 == 0}; };
95*c91d805eSJakub Mazurkiewicz     auto is_product_odd  = std::not_fn<is_product_even>();
96*c91d805eSJakub Mazurkiewicz     assert(is_product_odd());
97*c91d805eSJakub Mazurkiewicz     assert(is_product_odd(1, 3, 5, 9));
98*c91d805eSJakub Mazurkiewicz     assert(is_product_odd(3, 3, 3, 3));
99*c91d805eSJakub Mazurkiewicz     assert(!is_product_odd(3, 5, 9, 11, 0));
100*c91d805eSJakub Mazurkiewicz     assert(!is_product_odd(11, 7, 5, 3, 2));
101*c91d805eSJakub Mazurkiewicz     static_assert(noexcept(std::not_fn<is_product_even>()));
102*c91d805eSJakub Mazurkiewicz   }
103*c91d805eSJakub Mazurkiewicz 
104*c91d805eSJakub Mazurkiewicz   { // Test function that returns non-boolean-testable type
105*c91d805eSJakub Mazurkiewicz     auto sum         = [](auto... vals) -> FakeBool { return (vals + ... + 0); };
106*c91d805eSJakub Mazurkiewicz     auto negated_sum = std::not_fn<sum>();
107*c91d805eSJakub Mazurkiewicz     assert(negated_sum() == 0);
108*c91d805eSJakub Mazurkiewicz     assert(negated_sum(3) == -3);
109*c91d805eSJakub Mazurkiewicz     assert(negated_sum(4, 5, 1, 3) == -13);
110*c91d805eSJakub Mazurkiewicz     assert(negated_sum(4, 2, 5, 6, 1) == -18);
111*c91d805eSJakub Mazurkiewicz     assert(negated_sum(-1, 3, 2, -8) == 4);
112*c91d805eSJakub Mazurkiewicz     static_assert(noexcept(std::not_fn<sum>()));
113*c91d805eSJakub Mazurkiewicz   }
114*c91d805eSJakub Mazurkiewicz 
115*c91d805eSJakub Mazurkiewicz   { // Test member pointers
116*c91d805eSJakub Mazurkiewicz     struct MemberPointerTester {
117*c91d805eSJakub Mazurkiewicz       bool value = true;
118*c91d805eSJakub Mazurkiewicz       constexpr bool not_value() const { return !value; }
119*c91d805eSJakub Mazurkiewicz       constexpr bool value_and(bool other) noexcept { return value && other; }
120*c91d805eSJakub Mazurkiewicz     };
121*c91d805eSJakub Mazurkiewicz 
122*c91d805eSJakub Mazurkiewicz     MemberPointerTester tester;
123*c91d805eSJakub Mazurkiewicz 
124*c91d805eSJakub Mazurkiewicz     auto not_mem_object = std::not_fn<&MemberPointerTester::value>();
125*c91d805eSJakub Mazurkiewicz     assert(!not_mem_object(tester));
126*c91d805eSJakub Mazurkiewicz     assert(!not_mem_object(std::as_const(tester)));
127*c91d805eSJakub Mazurkiewicz     static_assert(noexcept(not_mem_object(tester)));
128*c91d805eSJakub Mazurkiewicz     static_assert(noexcept(not_mem_object(std::as_const(tester))));
129*c91d805eSJakub Mazurkiewicz 
130*c91d805eSJakub Mazurkiewicz     auto not_nullary_mem_fn = std::not_fn<&MemberPointerTester::not_value>();
131*c91d805eSJakub Mazurkiewicz     assert(not_nullary_mem_fn(tester));
132*c91d805eSJakub Mazurkiewicz     static_assert(!noexcept(not_nullary_mem_fn(tester)));
133*c91d805eSJakub Mazurkiewicz 
134*c91d805eSJakub Mazurkiewicz     auto not_unary_mem_fn = std::not_fn<&MemberPointerTester::value_and>();
135*c91d805eSJakub Mazurkiewicz     assert(not_unary_mem_fn(tester, false));
136*c91d805eSJakub Mazurkiewicz     static_assert(noexcept(not_unary_mem_fn(tester, false)));
137*c91d805eSJakub Mazurkiewicz     static_assert(!std::is_invocable_v<decltype(not_unary_mem_fn), const MemberPointerTester&, bool>);
138*c91d805eSJakub Mazurkiewicz   }
139*c91d805eSJakub Mazurkiewicz }
140*c91d805eSJakub Mazurkiewicz 
141*c91d805eSJakub Mazurkiewicz constexpr void test_perfect_forwarding_call_wrapper() {
142*c91d805eSJakub Mazurkiewicz   { // Make sure we call the correctly cv-ref qualified operator()
143*c91d805eSJakub Mazurkiewicz     // based on the value category of the not_fn<NTTP> unspecified-type.
144*c91d805eSJakub Mazurkiewicz     struct X {
145*c91d805eSJakub Mazurkiewicz       constexpr FakeBool operator()() & { return 1; }
146*c91d805eSJakub Mazurkiewicz       constexpr FakeBool operator()() const& { return 2; }
147*c91d805eSJakub Mazurkiewicz       constexpr FakeBool operator()() && { return 3; }
148*c91d805eSJakub Mazurkiewicz       constexpr FakeBool operator()() const&& { return 4; }
149*c91d805eSJakub Mazurkiewicz     };
150*c91d805eSJakub Mazurkiewicz 
151*c91d805eSJakub Mazurkiewicz     auto f  = std::not_fn<X{}>();
152*c91d805eSJakub Mazurkiewicz     using F = decltype(f);
153*c91d805eSJakub Mazurkiewicz     assert(static_cast<F&>(f)() == -2);
154*c91d805eSJakub Mazurkiewicz     assert(static_cast<const F&>(f)() == -2);
155*c91d805eSJakub Mazurkiewicz     assert(static_cast<F&&>(f)() == -2);
156*c91d805eSJakub Mazurkiewicz     assert(static_cast<const F&&>(f)() == -2);
157*c91d805eSJakub Mazurkiewicz   }
158*c91d805eSJakub Mazurkiewicz 
159*c91d805eSJakub Mazurkiewicz   // Call to `not_fn<NTTP>` unspecified-type's operator() should always result in call to the const& overload of the underlying function object.
160*c91d805eSJakub Mazurkiewicz   {
161*c91d805eSJakub Mazurkiewicz     { // Make sure unspecified-type is still callable when we delete the & overload.
162*c91d805eSJakub Mazurkiewicz       struct X {
163*c91d805eSJakub Mazurkiewicz         FakeBool operator()() & = delete;
164*c91d805eSJakub Mazurkiewicz         FakeBool operator()() const&;
165*c91d805eSJakub Mazurkiewicz         FakeBool operator()() &&;
166*c91d805eSJakub Mazurkiewicz         FakeBool operator()() const&&;
167*c91d805eSJakub Mazurkiewicz       };
168*c91d805eSJakub Mazurkiewicz 
169*c91d805eSJakub Mazurkiewicz       using F = decltype(std::not_fn<X{}>());
170*c91d805eSJakub Mazurkiewicz       static_assert(std::invocable<F&>);
171*c91d805eSJakub Mazurkiewicz       static_assert(std::invocable<const F&>);
172*c91d805eSJakub Mazurkiewicz       static_assert(std::invocable<F>);
173*c91d805eSJakub Mazurkiewicz       static_assert(std::invocable<const F>);
174*c91d805eSJakub Mazurkiewicz     }
175*c91d805eSJakub Mazurkiewicz 
176*c91d805eSJakub Mazurkiewicz     { // Make sure unspecified-type is not callable when we delete the const& overload.
177*c91d805eSJakub Mazurkiewicz       struct X {
178*c91d805eSJakub Mazurkiewicz         FakeBool operator()() &;
179*c91d805eSJakub Mazurkiewicz         FakeBool operator()() const& = delete;
180*c91d805eSJakub Mazurkiewicz         FakeBool operator()() &&;
181*c91d805eSJakub Mazurkiewicz         FakeBool operator()() const&&;
182*c91d805eSJakub Mazurkiewicz       };
183*c91d805eSJakub Mazurkiewicz 
184*c91d805eSJakub Mazurkiewicz       using F = decltype(std::not_fn<X{}>());
185*c91d805eSJakub Mazurkiewicz       static_assert(!std::invocable<F&>);
186*c91d805eSJakub Mazurkiewicz       static_assert(!std::invocable<const F&>);
187*c91d805eSJakub Mazurkiewicz       static_assert(!std::invocable<F>);
188*c91d805eSJakub Mazurkiewicz       static_assert(!std::invocable<const F>);
189*c91d805eSJakub Mazurkiewicz     }
190*c91d805eSJakub Mazurkiewicz 
191*c91d805eSJakub Mazurkiewicz     { // Make sure unspecified-type is still callable when we delete the && overload.
192*c91d805eSJakub Mazurkiewicz       struct X {
193*c91d805eSJakub Mazurkiewicz         FakeBool operator()() &;
194*c91d805eSJakub Mazurkiewicz         FakeBool operator()() const&;
195*c91d805eSJakub Mazurkiewicz         FakeBool operator()() && = delete;
196*c91d805eSJakub Mazurkiewicz         FakeBool operator()() const&&;
197*c91d805eSJakub Mazurkiewicz       };
198*c91d805eSJakub Mazurkiewicz 
199*c91d805eSJakub Mazurkiewicz       using F = decltype(std::not_fn<X{}>());
200*c91d805eSJakub Mazurkiewicz       static_assert(std::invocable<F&>);
201*c91d805eSJakub Mazurkiewicz       static_assert(std::invocable<const F&>);
202*c91d805eSJakub Mazurkiewicz       static_assert(std::invocable<F>);
203*c91d805eSJakub Mazurkiewicz       static_assert(std::invocable<const F>);
204*c91d805eSJakub Mazurkiewicz     }
205*c91d805eSJakub Mazurkiewicz 
206*c91d805eSJakub Mazurkiewicz     { // Make sure unspecified-type is still callable when we delete the const&& overload.
207*c91d805eSJakub Mazurkiewicz       struct X {
208*c91d805eSJakub Mazurkiewicz         FakeBool operator()() &;
209*c91d805eSJakub Mazurkiewicz         FakeBool operator()() const&;
210*c91d805eSJakub Mazurkiewicz         FakeBool operator()() &&;
211*c91d805eSJakub Mazurkiewicz         FakeBool operator()() const&& = delete;
212*c91d805eSJakub Mazurkiewicz       };
213*c91d805eSJakub Mazurkiewicz 
214*c91d805eSJakub Mazurkiewicz       using F = decltype(std::not_fn<X{}>());
215*c91d805eSJakub Mazurkiewicz       static_assert(std::invocable<F&>);
216*c91d805eSJakub Mazurkiewicz       static_assert(std::invocable<const F&>);
217*c91d805eSJakub Mazurkiewicz       static_assert(std::invocable<F>);
218*c91d805eSJakub Mazurkiewicz       static_assert(std::invocable<const F>);
219*c91d805eSJakub Mazurkiewicz     }
220*c91d805eSJakub Mazurkiewicz   }
221*c91d805eSJakub Mazurkiewicz 
222*c91d805eSJakub Mazurkiewicz   { // Test perfect forwarding
223*c91d805eSJakub Mazurkiewicz     auto f = [](int& val) {
224*c91d805eSJakub Mazurkiewicz       val = 5;
225*c91d805eSJakub Mazurkiewicz       return false;
226*c91d805eSJakub Mazurkiewicz     };
227*c91d805eSJakub Mazurkiewicz 
228*c91d805eSJakub Mazurkiewicz     auto not_f = std::not_fn<f>();
229*c91d805eSJakub Mazurkiewicz     int val    = 0;
230*c91d805eSJakub Mazurkiewicz     assert(not_f(val));
231*c91d805eSJakub Mazurkiewicz     assert(val == 5);
232*c91d805eSJakub Mazurkiewicz 
233*c91d805eSJakub Mazurkiewicz     using NotF = decltype(not_f);
234*c91d805eSJakub Mazurkiewicz     static_assert(std::invocable<NotF, int&>);
235*c91d805eSJakub Mazurkiewicz     static_assert(!std::invocable<NotF, int>);
236*c91d805eSJakub Mazurkiewicz   }
237*c91d805eSJakub Mazurkiewicz }
238*c91d805eSJakub Mazurkiewicz 
239*c91d805eSJakub Mazurkiewicz constexpr void test_return_type() {
240*c91d805eSJakub Mazurkiewicz   { // Test constructors and assignment operators
241*c91d805eSJakub Mazurkiewicz     struct IsPowerOfTwo {
242*c91d805eSJakub Mazurkiewicz       constexpr bool operator()(unsigned int x) const { return std::has_single_bit(x); }
243*c91d805eSJakub Mazurkiewicz     };
244*c91d805eSJakub Mazurkiewicz 
245*c91d805eSJakub Mazurkiewicz     auto is_not_power_of_2 = std::not_fn<IsPowerOfTwo{}>();
246*c91d805eSJakub Mazurkiewicz     assert(is_not_power_of_2(5));
247*c91d805eSJakub Mazurkiewicz     assert(!is_not_power_of_2(4));
248*c91d805eSJakub Mazurkiewicz 
249*c91d805eSJakub Mazurkiewicz     auto moved = std::move(is_not_power_of_2);
250*c91d805eSJakub Mazurkiewicz     assert(moved(5));
251*c91d805eSJakub Mazurkiewicz     assert(!moved(4));
252*c91d805eSJakub Mazurkiewicz 
253*c91d805eSJakub Mazurkiewicz     auto copied = is_not_power_of_2;
254*c91d805eSJakub Mazurkiewicz     assert(copied(7));
255*c91d805eSJakub Mazurkiewicz     assert(!copied(8));
256*c91d805eSJakub Mazurkiewicz 
257*c91d805eSJakub Mazurkiewicz     moved = std::move(copied);
258*c91d805eSJakub Mazurkiewicz     assert(copied(9));
259*c91d805eSJakub Mazurkiewicz     assert(!copied(16));
260*c91d805eSJakub Mazurkiewicz 
261*c91d805eSJakub Mazurkiewicz     copied = moved;
262*c91d805eSJakub Mazurkiewicz     assert(copied(11));
263*c91d805eSJakub Mazurkiewicz     assert(!copied(32));
264*c91d805eSJakub Mazurkiewicz   }
265*c91d805eSJakub Mazurkiewicz 
266*c91d805eSJakub Mazurkiewicz   { // Make sure `not_fn<NTTP>` unspecified-type's operator() is SFINAE-friendly.
267*c91d805eSJakub Mazurkiewicz     using F = decltype(std::not_fn<[](int x) { return !x; }>());
268*c91d805eSJakub Mazurkiewicz     static_assert(!std::is_invocable<F>::value);
269*c91d805eSJakub Mazurkiewicz     static_assert(std::is_invocable<F, int>::value);
270*c91d805eSJakub Mazurkiewicz     static_assert(!std::is_invocable<F, void*>::value);
271*c91d805eSJakub Mazurkiewicz     static_assert(!std::is_invocable<F, int, int>::value);
272*c91d805eSJakub Mazurkiewicz   }
273*c91d805eSJakub Mazurkiewicz 
274*c91d805eSJakub Mazurkiewicz   { // Test noexceptness
275*c91d805eSJakub Mazurkiewicz     auto always_noexcept = std::not_fn<MaybeNoexceptFn<true>{}>();
276*c91d805eSJakub Mazurkiewicz     static_assert(noexcept(always_noexcept()));
277*c91d805eSJakub Mazurkiewicz 
278*c91d805eSJakub Mazurkiewicz     auto never_noexcept = std::not_fn<MaybeNoexceptFn<false>{}>();
279*c91d805eSJakub Mazurkiewicz     static_assert(!noexcept(never_noexcept()));
280*c91d805eSJakub Mazurkiewicz 
281*c91d805eSJakub Mazurkiewicz     auto always_noexcept_negation = std::not_fn<maybe_noexcept_negation<true>>();
282*c91d805eSJakub Mazurkiewicz     static_assert(noexcept(always_noexcept_negation()));
283*c91d805eSJakub Mazurkiewicz 
284*c91d805eSJakub Mazurkiewicz     auto never_noexcept_negation = std::not_fn<maybe_noexcept_negation<false>>();
285*c91d805eSJakub Mazurkiewicz     static_assert(!noexcept(never_noexcept_negation()));
286*c91d805eSJakub Mazurkiewicz   }
287*c91d805eSJakub Mazurkiewicz 
288*c91d805eSJakub Mazurkiewicz   { // Test calling volatile wrapper
289*c91d805eSJakub Mazurkiewicz     using NotFn = decltype(std::not_fn<std::false_type{}>());
290*c91d805eSJakub Mazurkiewicz     static_assert(!std::invocable<volatile NotFn&>);
291*c91d805eSJakub Mazurkiewicz     static_assert(!std::invocable<const volatile NotFn&>);
292*c91d805eSJakub Mazurkiewicz     static_assert(!std::invocable<volatile NotFn>);
293*c91d805eSJakub Mazurkiewicz     static_assert(!std::invocable<const volatile NotFn>);
294*c91d805eSJakub Mazurkiewicz   }
295*c91d805eSJakub Mazurkiewicz }
296*c91d805eSJakub Mazurkiewicz 
297*c91d805eSJakub Mazurkiewicz constexpr bool test() {
298*c91d805eSJakub Mazurkiewicz   basic_tests();
299*c91d805eSJakub Mazurkiewicz   test_perfect_forwarding_call_wrapper();
300*c91d805eSJakub Mazurkiewicz   test_return_type();
301*c91d805eSJakub Mazurkiewicz 
302*c91d805eSJakub Mazurkiewicz   return true;
303*c91d805eSJakub Mazurkiewicz }
304*c91d805eSJakub Mazurkiewicz 
305*c91d805eSJakub Mazurkiewicz int main(int, char**) {
306*c91d805eSJakub Mazurkiewicz   test();
307*c91d805eSJakub Mazurkiewicz   static_assert(test());
308*c91d805eSJakub Mazurkiewicz 
309*c91d805eSJakub Mazurkiewicz   return 0;
310*c91d805eSJakub Mazurkiewicz }
311