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