diff --git a/libcxx/test/msvc-stl/P0898R3_concepts/invocable_cc.hpp b/libcxx/test/msvc-stl/P0898R3_concepts/invocable_cc.hpp new file mode 100644 --- /dev/null +++ b/libcxx/test/msvc-stl/P0898R3_concepts/invocable_cc.hpp @@ -0,0 +1,827 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// expects NAME (function name), CALLCONV (calling convention for non-member functions), and MCALLCONV (calling +// convention for member functions) to be defined before including; undefines all three. + +// clang-format off +void NAME() { + struct S { + using FreeFunc = short(CALLCONV*)(long); + operator FreeFunc() const; + double MCALLCONV operator()(char, int&); + double const& MCALLCONV operator()(char, int&) const; + double volatile& MCALLCONV operator()(char, int&) volatile; + double const volatile& MCALLCONV operator()(char, int&) const volatile; + }; + + { + using Fn = int (MCALLCONV tag::*)(int); + using RFn = int (MCALLCONV tag::*)(int)&&; + { + // N4849 [func.require]/1.1: "... f is a pointer to member function of a class T and + // is_base_of_v> is true" + STATIC_ASSERT(test()); + STATIC_ASSERT(test&, int>()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + } + { + // N4849 [func.require]/1.2: "... f is a pointer to a member function of a class T and + // remove_cvref_t is a specialization of reference_wrapper" + using T = std::reference_wrapper; + using DT = std::reference_wrapper>; + using CT = std::reference_wrapper; + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + } + { + // N4849 [func.require]/1.3: "... f is a pointer to a member function of a class T and t_1 does not satisfy + // the previous two items" + using T = tag*; + using DT = DerivesFrom*; + using CT = tag const*; + using ST = std::unique_ptr; + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + } + } + + // clang-format off + { + // N4849 [func.require]/1.7: "f(t_1, t_2, ..., t_N) in all other cases" + { + // function pointer + using Fp = void(CALLCONV*)(tag&, int); + STATIC_ASSERT(test()); + STATIC_ASSERT(test&, int>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + } + { + // function reference + using Fp = void(CALLCONV&)(tag&, int); + STATIC_ASSERT(test()); + STATIC_ASSERT(test&, int>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + } + { + // function object + struct not_callable_with_int { + int operator()(int) = delete; + int MCALLCONV operator()(tag) { + return 42; + } + }; + + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + } + } + + { + // function object + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(test, int>()); + STATIC_ASSERT(test, char>()); + STATIC_ASSERT(test, float>()); + STATIC_ASSERT(!test, char const*>()); + STATIC_ASSERT(!test, S const&>()); + + auto lambda_lambda_lambda = [x = 42](int, double) { return x; }; + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + } + + { // pointer to function + using RF0 = bool(CALLCONV&)(); + using RF1 = bool*(CALLCONV&) (int); + using RF2 = bool&(CALLCONV&) (int, int); + using RF3 = bool const&(CALLCONV&) (int, int, int); + using RF4 = bool (&)(int, ...); + using PF0 = bool(CALLCONV*)(); + using PF1 = bool*(CALLCONV*) (int); + using PF2 = bool&(CALLCONV*) (int, int); + using PF3 = bool const&(CALLCONV*) (int, int, int); + using PF4 = bool (*)(int, ...); + using RPF0 = bool(CALLCONV*&)(); + using RPF1 = bool*(CALLCONV*&) (int); + using RPF2 = bool&(CALLCONV*&) (int, int); + using RPF3 = bool const&(CALLCONV*&) (int, int, int); + using RPF4 = bool (*&)(int, ...); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + } + + { // pointer to member function + using PMF0 = int (MCALLCONV S::*)(); + using PMF1 = int* (MCALLCONV S::*) (long); + using PMF2 = int& (MCALLCONV S::*) (long, int); + using PMF1P = int const& (S::*) (int, ...); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test>()); + STATIC_ASSERT(test const&>()); + STATIC_ASSERT(test>>()); + STATIC_ASSERT(test> const&>()); + STATIC_ASSERT(test>()); + STATIC_ASSERT(test>>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test>()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test, int>()); + STATIC_ASSERT(test>, int>()); + STATIC_ASSERT(test, int>()); + STATIC_ASSERT(test const&, int>()); + STATIC_ASSERT(test>, int>()); + STATIC_ASSERT(test> const&, int>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test, int>()); + STATIC_ASSERT(!test, int>()); + STATIC_ASSERT(!test, int>()); + STATIC_ASSERT(!test, int>()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test, int, int>()); + STATIC_ASSERT(test>, int, int>()); + STATIC_ASSERT(test, int, int>()); + STATIC_ASSERT(test const&, int, int>()); + STATIC_ASSERT(test>, int, int>()); + STATIC_ASSERT(test> const&, int, int>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test, int, int>()); + STATIC_ASSERT(!test, int, int>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test, int, int>()); + STATIC_ASSERT(!test, int, int>()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + using PMF0C = int (MCALLCONV S::*)() const; + using PMF1C = int* (MCALLCONV S::*) (long) const; + using PMF2C = int& (MCALLCONV S::*) (long, int) const; + using PMF1PC = int const& (S::*) (int, ...) const; + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test>()); + STATIC_ASSERT(test>>()); + STATIC_ASSERT(test>()); + STATIC_ASSERT(test>()); + STATIC_ASSERT(test const&>()); + STATIC_ASSERT(test const&>()); + STATIC_ASSERT(test>>()); + STATIC_ASSERT(test const>>()); + STATIC_ASSERT(test> const&>()); + STATIC_ASSERT(test const> const&>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test, int>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test, int, int>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + using PMF0V = int (MCALLCONV S::*)() volatile; + using PMF1V = int* (MCALLCONV S::*) (long) volatile; + using PMF2V = int& (MCALLCONV S::*) (long, int) volatile; + using PMF1PV = int const& (S::*) (int, ...) volatile; + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test, int>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test, int, int>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + using PMF0CV = int (MCALLCONV S::*)() const volatile; + using PMF1CV = int* (MCALLCONV S::*) (long) const volatile; + using PMF2CV = int& (MCALLCONV S::*) (long, int) const volatile; + using PMF1PCV = int const& (S::*) (int, ...) const volatile; + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test>()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test, int>()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test, int, int>()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + using PMF0R = int (MCALLCONV S::*)()&; + using PMF1R = int* (MCALLCONV S::*) (long) &; + using PMF2R = int& (MCALLCONV S::*) (long, int) &; + using PMF1PR = int const& (S::*) (int, ...)&; + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test>()); + STATIC_ASSERT(test const&>()); + STATIC_ASSERT(test>>()); + STATIC_ASSERT(test> const&>()); + STATIC_ASSERT(test>()); + STATIC_ASSERT(test>>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test>()); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test, int>()); + STATIC_ASSERT(test>, int>()); + STATIC_ASSERT(test, int>()); + STATIC_ASSERT(test const&, int>()); + STATIC_ASSERT(test>, int>()); + STATIC_ASSERT(test> const&, int>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test, int>()); + STATIC_ASSERT(!test, int>()); + STATIC_ASSERT(!test, int>()); + STATIC_ASSERT(!test, int>()); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test, int, int>()); + STATIC_ASSERT(test>, int, int>()); + STATIC_ASSERT(test, int, int>()); + STATIC_ASSERT(test const&, int, int>()); + STATIC_ASSERT(test>, int, int>()); + STATIC_ASSERT(test> const&, int, int>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test, int, int>()); + STATIC_ASSERT(!test, int, int>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test, int, int>()); + STATIC_ASSERT(!test, int, int>()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + using PMF0CR = int (MCALLCONV S::*)() const&; + using PMF1CR = int* (MCALLCONV S::*) (long) const&; + using PMF2CR = int& (MCALLCONV S::*) (long, int) const&; + using PMF1PCR = int const& (S::*) (int, ...) const&; + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test>()); + STATIC_ASSERT(test const&>()); + STATIC_ASSERT(test>>()); + STATIC_ASSERT(test> const&>()); + STATIC_ASSERT(test>()); + STATIC_ASSERT(test>>()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(test>()); + STATIC_ASSERT(test>()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test>()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test, int>()); + STATIC_ASSERT(test>, int>()); + STATIC_ASSERT(test, int>()); + STATIC_ASSERT(test const&, int>()); + STATIC_ASSERT(test>, int>()); + STATIC_ASSERT(test> const&, int>()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(test, int>()); + STATIC_ASSERT(test, int>()); + STATIC_ASSERT(!test, int>()); + STATIC_ASSERT(!test, int>()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test, int, int>()); + STATIC_ASSERT(test>, int, int>()); + STATIC_ASSERT(test, int, int>()); + STATIC_ASSERT(test const&, int, int>()); + STATIC_ASSERT(test>, int, int>()); + STATIC_ASSERT(test> const&, int, int>()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(test, int, int>()); + STATIC_ASSERT(test, int, int>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test, int, int>()); + STATIC_ASSERT(!test, int, int>()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + using PMF0CVR = int (MCALLCONV S::*)() const volatile&; + using PMF1CVR = int* (MCALLCONV S::*) (long) const volatile&; + using PMF2CVR = int& (MCALLCONV S::*) (long, int) const volatile&; + using PMF1PCVR = int const& (S::*) (int, ...) const volatile&; + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test>()); + STATIC_ASSERT(test const&>()); + STATIC_ASSERT(test>>()); + STATIC_ASSERT(test> const&>()); + STATIC_ASSERT(test>()); + STATIC_ASSERT(test>>()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(test>()); + STATIC_ASSERT(test>()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test>()); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test, int>()); + STATIC_ASSERT(test>, int>()); + STATIC_ASSERT(test, int>()); + STATIC_ASSERT(test const&, int>()); + STATIC_ASSERT(test>, int>()); + STATIC_ASSERT(test> const&, int>()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(test, int>()); + STATIC_ASSERT(test, int>()); + STATIC_ASSERT(!test, int>()); + STATIC_ASSERT(!test, int>()); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test, int, int>()); + STATIC_ASSERT(test>, int, int>()); + STATIC_ASSERT(test, int, int>()); + STATIC_ASSERT(test const&, int, int>()); + STATIC_ASSERT(test>, int, int>()); + STATIC_ASSERT(test> const&, int, int>()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test, int, int>()); + STATIC_ASSERT(test, int, int>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test, int, int>()); + STATIC_ASSERT(!test, int, int>()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + using PMF0RR = int (MCALLCONV S::*)()&&; + using PMF1RR = int* (MCALLCONV S::*) (long) &&; + using PMF2RR = int& (MCALLCONV S::*) (long, int) &&; + using PMF1PRR = int const& (S::*) (int, ...)&&; + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test const&>()); + STATIC_ASSERT(!test>>()); + STATIC_ASSERT(!test> const&>()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test>>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test>()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test, int>()); + STATIC_ASSERT(!test>, int>()); + STATIC_ASSERT(!test, int>()); + STATIC_ASSERT(!test const&, int>()); + STATIC_ASSERT(!test>, int>()); + STATIC_ASSERT(!test> const&, int>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test, int>()); + STATIC_ASSERT(!test, int>()); + STATIC_ASSERT(!test, int>()); + STATIC_ASSERT(!test, int>()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test, int, int>()); + STATIC_ASSERT(!test>, int, int>()); + STATIC_ASSERT(!test, int, int>()); + STATIC_ASSERT(!test const&, int, int>()); + STATIC_ASSERT(!test>, int, int>()); + STATIC_ASSERT(!test> const&, int, int>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test, int, int>()); + STATIC_ASSERT(!test, int, int>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test, int, int>()); + STATIC_ASSERT(!test, int, int>()); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + using PMF0CRR = int (MCALLCONV S::*)() const&&; + using PMF1CRR = int* (MCALLCONV S::*) (long) const&&; + using PMF2CRR = int& (MCALLCONV S::*) (long, int) const&&; + using PMF1PCRR = int const& (S::*) (int, ...) const&&; + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test const&>()); + STATIC_ASSERT(!test>>()); + STATIC_ASSERT(!test> const&>()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test>>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test>()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test, int>()); + STATIC_ASSERT(!test>, int>()); + STATIC_ASSERT(!test, int>()); + STATIC_ASSERT(!test const&, int>()); + STATIC_ASSERT(!test>, int>()); + STATIC_ASSERT(!test> const&, int>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test, int>()); + STATIC_ASSERT(!test, int>()); + STATIC_ASSERT(!test, int>()); + STATIC_ASSERT(!test, int>()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test, int, int>()); + STATIC_ASSERT(!test>, int, int>()); + STATIC_ASSERT(!test, int, int>()); + STATIC_ASSERT(!test const&, int, int>()); + STATIC_ASSERT(!test>, int, int>()); + STATIC_ASSERT(!test> const&, int, int>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test, int, int>()); + STATIC_ASSERT(!test, int, int>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test, int, int>()); + STATIC_ASSERT(!test, int, int>()); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + using PMF0VRR = int (MCALLCONV S::*)() volatile&&; + using PMF1VRR = int* (MCALLCONV S::*) (long) volatile&&; + using PMF2VRR = int& (MCALLCONV S::*) (long, int) volatile&&; + using PMF1PVRR = int const& (S::*) (int, ...) volatile&&; + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test const&>()); + STATIC_ASSERT(!test>>()); + STATIC_ASSERT(!test> const&>()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test>>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test>()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test, int>()); + STATIC_ASSERT(!test>, int>()); + STATIC_ASSERT(!test, int>()); + STATIC_ASSERT(!test const&, int>()); + STATIC_ASSERT(!test>, int>()); + STATIC_ASSERT(!test> const&, int>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test, int>()); + STATIC_ASSERT(!test, int>()); + STATIC_ASSERT(!test, int>()); + STATIC_ASSERT(!test, int>()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test, int, int>()); + STATIC_ASSERT(!test>, int, int>()); + STATIC_ASSERT(!test, int, int>()); + STATIC_ASSERT(!test const&, int, int>()); + STATIC_ASSERT(!test>, int, int>()); + STATIC_ASSERT(!test> const&, int, int>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test, int, int>()); + STATIC_ASSERT(!test, int, int>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test, int, int>()); + STATIC_ASSERT(!test, int, int>()); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + using PMF0CVRR = int (MCALLCONV S::*)() const volatile&&; + using PMF1CVRR = int* (MCALLCONV S::*) (long) const volatile&&; + using PMF2CVRR = int& (MCALLCONV S::*) (long, int) const volatile&&; + using PMF1PCVRR = int const& (S::*) (int, ...) const volatile&&; + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test const&>()); + STATIC_ASSERT(!test>>()); + STATIC_ASSERT(!test> const&>()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test>>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test>()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test, int>()); + STATIC_ASSERT(!test>, int>()); + STATIC_ASSERT(!test, int>()); + STATIC_ASSERT(!test const&, int>()); + STATIC_ASSERT(!test>, int>()); + STATIC_ASSERT(!test> const&, int>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test, int>()); + STATIC_ASSERT(!test, int>()); + STATIC_ASSERT(!test, int>()); + STATIC_ASSERT(!test, int>()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test, int, int>()); + STATIC_ASSERT(!test>, int, int>()); + STATIC_ASSERT(!test, int, int>()); + STATIC_ASSERT(!test const&, int, int>()); + STATIC_ASSERT(!test>, int, int>()); + STATIC_ASSERT(!test> const&, int, int>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test, int, int>()); + STATIC_ASSERT(!test, int, int>()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test, int, int>()); + STATIC_ASSERT(!test, int, int>()); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + } +// clang-format on +} + +#undef CALLCONV +#undef MCALLCONV +#undef NAME diff --git a/libcxx/test/msvc-stl/P0898R3_concepts/test.pass.cpp b/libcxx/test/msvc-stl/P0898R3_concepts/test.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/msvc-stl/P0898R3_concepts/test.pass.cpp @@ -0,0 +1,3559 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts + +// clang-format off +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunknown-pragmas" +#pragma clang diagnostic ignored "-Wdeprecated-volatile" + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunknown-pragmas" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +template +constexpr bool is_trait = false; +template +constexpr bool is_trait> = true; + +template +constexpr bool always_false = false; + +namespace detail { + static constexpr bool permissive() { + return false; + } + + template + struct DependentBase { + static constexpr bool permissive() { + return true; + } + }; + + template + struct Derived : DependentBase { + static constexpr bool test() { + return permissive(); + } + }; +} // namespace detail +constexpr bool is_permissive = detail::Derived::test(); + +struct IncompleteClass; +union IncompleteUnion; + +template +struct DoNotInstantiate { + STATIC_ASSERT(always_false); +}; + +struct Immobile { + Immobile() = default; + Immobile(Immobile const&) = delete; + Immobile& operator=(Immobile const&) = delete; +}; + +struct MoveOnly { + MoveOnly() = default; + MoveOnly(MoveOnly&&) = default; + MoveOnly& operator=(MoveOnly&&) = default; +}; + +struct CopyOnlyAbomination { + CopyOnlyAbomination() = default; + CopyOnlyAbomination(CopyOnlyAbomination const&) = default; + CopyOnlyAbomination(CopyOnlyAbomination&&) = delete; + CopyOnlyAbomination& operator=(CopyOnlyAbomination const&) = default; + CopyOnlyAbomination& operator=(CopyOnlyAbomination&&) = delete; +}; + +struct CopyableType { + CopyableType() = delete; +}; + +struct SemiregularType {}; + +struct RegularType { + friend constexpr bool operator==(RegularType const&, RegularType const&) { + return true; + } + friend constexpr bool operator!=(RegularType const&, RegularType const&) { + return false; + } +}; + +struct Indestructible { + ~Indestructible() = delete; +}; + +struct NonTriviallyDestructible { + ~NonTriviallyDestructible(); +}; + +class PrivateDestructor { +public: + PrivateDestructor(int) {} + +private: + ~PrivateDestructor() {} +}; + +struct ThrowingDestructor { + ~ThrowingDestructor() noexcept(false); +}; + +class PurePublicDestructor { +public: + virtual ~PurePublicDestructor() = 0; +}; +class PureProtectedDestructor { +protected: + virtual ~PureProtectedDestructor() = 0; +}; +class PurePrivateDestructor { +private: + virtual ~PurePrivateDestructor() = 0; +}; + +struct NotDefaultConstructible { + NotDefaultConstructible(int) {} +}; + +class PublicAbstract { +public: + virtual void meow() = 0; +}; +class ProtectedAbstract { +protected: + virtual void meow() = 0; +}; +class PrivateAbstract { +private: + virtual void meow() = 0; +}; + +struct ExplicitDefault { + explicit ExplicitDefault() = default; +}; + +struct AggregatesExplicitDefault { + ExplicitDefault meow; +}; + +struct DeletedDefault { + DeletedDefault() = delete; +}; + +struct ExplicitMoveAbomination { + ExplicitMoveAbomination() = default; + explicit ExplicitMoveAbomination(ExplicitMoveAbomination&&) = default; +}; + +struct ExplicitCopyAbomination { + ExplicitCopyAbomination() = default; + ExplicitCopyAbomination(ExplicitCopyAbomination&&) = default; + explicit ExplicitCopyAbomination(ExplicitCopyAbomination const&) = default; +}; + +struct EmptyClass {}; +union EmptyUnion {}; + +struct NotEmpty { + virtual ~NotEmpty() = default; +}; + +struct BitZero { + int : 0; +}; + +template +struct ConvertsFrom { + ConvertsFrom() = default; + constexpr ConvertsFrom(First) noexcept {} + // clang-format off + constexpr ConvertsFrom(Second) noexcept requires (!std::is_same_v) {} + // clang-format on +}; + +template +struct Interconvertible { + Interconvertible() = default; + template + explicit Interconvertible(Interconvertible) {} +}; + +struct Omniconvertible { + template + Omniconvertible(T&&); +}; + +template +struct ImplicitTo { + operator To() const; +}; +template +struct ExplicitTo { + explicit operator To() const; +}; + +template +struct DerivesFrom : Ts... {}; + +struct SimpleBase {}; +using SimpleDerived = DerivesFrom; + +struct MovableFriendSwap { + friend void swap(MovableFriendSwap&, MovableFriendSwap&) {} +}; +struct ImmobileFriendSwap : Immobile { + friend void swap(ImmobileFriendSwap&, ImmobileFriendSwap&) noexcept {} +}; + +struct ImmobileNonMemberSwap : Immobile {}; +void swap(ImmobileNonMemberSwap&, ImmobileNonMemberSwap&) {} + +template <> +struct std::common_type, Interconvertible<1>> { + using type = Interconvertible<2>; +}; +template <> +struct std::common_type, Interconvertible<0>> { + using type = Interconvertible<2>; +}; + +template <> +struct std::common_type, EmptyClass> { + using type = EmptyClass; +}; +template <> +struct std::common_type> { + using type = EmptyClass; +}; + +namespace test_same_as { + using std::same_as; + + template + constexpr bool test() { + STATIC_ASSERT(same_as); + STATIC_ASSERT(same_as); + STATIC_ASSERT(same_as); + STATIC_ASSERT(same_as); + + constexpr bool is_ref = std::is_reference_v; + + STATIC_ASSERT(same_as == is_ref); + STATIC_ASSERT(same_as == is_ref); + STATIC_ASSERT(same_as == is_ref); + STATIC_ASSERT(same_as == is_ref); + STATIC_ASSERT(same_as == is_ref); + STATIC_ASSERT(same_as == is_ref); + + if constexpr (!std::is_void_v) { + STATIC_ASSERT(same_as); + STATIC_ASSERT(same_as == is_ref); + STATIC_ASSERT(same_as); + STATIC_ASSERT(same_as == is_ref); + } + + if constexpr (!is_ref) { + STATIC_ASSERT(same_as); + STATIC_ASSERT(same_as); + } + + return true; + } + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!same_as); + STATIC_ASSERT(test()); + STATIC_ASSERT(!same_as); + STATIC_ASSERT(!same_as); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(!same_as); + STATIC_ASSERT(!same_as); + + STATIC_ASSERT(test()); + STATIC_ASSERT(!same_as); + STATIC_ASSERT(!same_as); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(same_as); + STATIC_ASSERT(same_as); + + // clang-format off + // Verify that `same_as` subsumes `same_as` (note reversed argument order) + template + requires same_as + constexpr bool f() { + return false; + } + + template + requires same_as && std::is_integral_v + constexpr bool f() { + return true; + } + // clang-format on + + STATIC_ASSERT(!f()); + STATIC_ASSERT(!f()); + + STATIC_ASSERT(f()); // ambiguous if second overload's requirements do not subsume the first's + STATIC_ASSERT(f()); // Ditto +} // namespace test_same_as + +namespace test_derived_from { + using std::derived_from; + + STATIC_ASSERT(!derived_from); + STATIC_ASSERT(!derived_from); + STATIC_ASSERT(!derived_from); + STATIC_ASSERT(!derived_from); + STATIC_ASSERT(!derived_from); + STATIC_ASSERT(!derived_from); + STATIC_ASSERT(!derived_from); + STATIC_ASSERT(!derived_from); + + template + constexpr bool test() { + STATIC_ASSERT(derived_from); + STATIC_ASSERT(derived_from); + STATIC_ASSERT(derived_from); + STATIC_ASSERT(derived_from); + STATIC_ASSERT(derived_from); + STATIC_ASSERT(derived_from); + STATIC_ASSERT(derived_from); + STATIC_ASSERT(derived_from); + STATIC_ASSERT(derived_from); + STATIC_ASSERT(derived_from); + STATIC_ASSERT(derived_from); + STATIC_ASSERT(derived_from); + STATIC_ASSERT(derived_from); + STATIC_ASSERT(derived_from); + STATIC_ASSERT(derived_from); + STATIC_ASSERT(derived_from); + return true; + } + + STATIC_ASSERT(test()); + STATIC_ASSERT(!derived_from); + + template + struct Middle : SimpleBase {}; + + STATIC_ASSERT(test, SimpleBase>()); + STATIC_ASSERT(!derived_from>); + STATIC_ASSERT(!derived_from&, SimpleBase&>); + STATIC_ASSERT(!derived_from*, SimpleBase*>); + STATIC_ASSERT(!derived_from[42], SimpleBase[42]>); + + STATIC_ASSERT(test, SimpleBase>()); + STATIC_ASSERT(!derived_from>); + + STATIC_ASSERT(test, Middle<1>>, Middle<0>>()); + STATIC_ASSERT(test, Middle<1>>, Middle<1>>()); + STATIC_ASSERT(!derived_from, Middle<1>>, SimpleBase>); + + class PrivateDerived : private Middle<0>, private Middle<1> { + public: + void f(); + }; + + void PrivateDerived::f() { + // Check these in a member to verify that access doesn't depend on context + STATIC_ASSERT(!derived_from>); + STATIC_ASSERT(!derived_from>); + } + + STATIC_ASSERT(!derived_from); + + STATIC_ASSERT(test()); + + STATIC_ASSERT(!derived_from); + STATIC_ASSERT(!derived_from); + STATIC_ASSERT(!derived_from); +} // namespace test_derived_from + +namespace test_convertible_to { + using std::convertible_to; + + using char_array = char[42]; + using fn = void(); + using const_fn = void() const; + +#pragma warning(push) +#pragma warning(disable : 4180) // qualifier applied to function type has no meaning; ignored + template + constexpr bool test() { + constexpr bool result = convertible_to; + STATIC_ASSERT(convertible_to == result); + STATIC_ASSERT(convertible_to == result); + STATIC_ASSERT(convertible_to == result); + return result; + } +#pragma warning(pop) + + // void + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + // fn + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(convertible_to); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + // fn& + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + // fn* + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + // Abominable function + STATIC_ASSERT(!convertible_to); + STATIC_ASSERT(!convertible_to); + STATIC_ASSERT(!convertible_to); + STATIC_ASSERT(!convertible_to); + STATIC_ASSERT(!convertible_to); + STATIC_ASSERT(!convertible_to); + STATIC_ASSERT(!convertible_to); + STATIC_ASSERT(!convertible_to); + + // char_array + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(!convertible_to); + STATIC_ASSERT(convertible_to); + STATIC_ASSERT(!convertible_to); + + STATIC_ASSERT(!convertible_to); + STATIC_ASSERT(convertible_to); + STATIC_ASSERT(!convertible_to); + STATIC_ASSERT(!convertible_to); + + STATIC_ASSERT(convertible_to); + STATIC_ASSERT(convertible_to); + STATIC_ASSERT(convertible_to); + STATIC_ASSERT(convertible_to); + STATIC_ASSERT(convertible_to); + STATIC_ASSERT(!convertible_to); + STATIC_ASSERT(!convertible_to); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(convertible_to); + STATIC_ASSERT(convertible_to); + STATIC_ASSERT(convertible_to); + STATIC_ASSERT(convertible_to); + + STATIC_ASSERT(!convertible_to); + STATIC_ASSERT(convertible_to); + + STATIC_ASSERT(!convertible_to); + STATIC_ASSERT(!convertible_to); + + // char_array& + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(convertible_to); + STATIC_ASSERT(convertible_to); + STATIC_ASSERT(!convertible_to); + STATIC_ASSERT(convertible_to); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(convertible_to); + STATIC_ASSERT(convertible_to); + STATIC_ASSERT(!convertible_to); + STATIC_ASSERT(convertible_to); + + STATIC_ASSERT(convertible_to>); + STATIC_ASSERT(convertible_to>); + + // char + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test()); + + STATIC_ASSERT(!convertible_to); + STATIC_ASSERT(convertible_to); + STATIC_ASSERT(!convertible_to); + STATIC_ASSERT(convertible_to); + + STATIC_ASSERT(!test()); + + // char& + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test()); + + STATIC_ASSERT(convertible_to); + STATIC_ASSERT(convertible_to); + STATIC_ASSERT(!convertible_to); + STATIC_ASSERT(convertible_to); + + STATIC_ASSERT(!test()); + + // char* + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(convertible_to); + STATIC_ASSERT(convertible_to); + STATIC_ASSERT(!convertible_to); + STATIC_ASSERT(convertible_to); + + STATIC_ASSERT(convertible_to); + STATIC_ASSERT(convertible_to); + STATIC_ASSERT(convertible_to); + STATIC_ASSERT(convertible_to); + STATIC_ASSERT(convertible_to); + STATIC_ASSERT(convertible_to); + STATIC_ASSERT(convertible_to); + STATIC_ASSERT(convertible_to); + STATIC_ASSERT(!convertible_to); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + // Ensure that DoNotInstantiate is not instantiated by is_convertible when it is not needed. + // (For example, DoNotInstantiate is instantiated by ADL lookup for arguments of type DoNotInstantiate*.) + STATIC_ASSERT(convertible_to*, DoNotInstantiate*>); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + + struct ImplicitConversionOnly; + struct Target { + Target() = default; + explicit Target(ImplicitConversionOnly) = delete; + }; + struct ImplicitConversionOnly { + operator Target() const; + }; + STATIC_ASSERT(test, Target>()); + STATIC_ASSERT(!test, Target>()); + STATIC_ASSERT(!test()); + + namespace overloading { // a test of overload resolution moreso than the concept itself + enum class result { exact, convertible, unrelated }; + + constexpr result f(ConvertsFrom) { + return result::exact; + } + + template > T> + constexpr result f(T&&) { + return result::convertible; + } + + template + constexpr result f(T&&) { + return result::unrelated; + } + + STATIC_ASSERT(f(ConvertsFrom{}) == result::exact); // the most specialized overload is chosen + constexpr ConvertsFrom cfi{}; + STATIC_ASSERT(f(cfi) == result::exact); // Ditto with qualification conversion + STATIC_ASSERT(f(42) == result::convertible); // the more-constrained overload is chosen + STATIC_ASSERT(f("meow") == result::unrelated); // everything isn't completely broken + } // namespace overloading +} // namespace test_convertible_to + +namespace test_common_reference_with { + using std::common_reference_t, std::common_reference_with; + + template + constexpr bool test() { + constexpr bool result = common_reference_with; + STATIC_ASSERT(common_reference_with == result); + return result; + } + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + // common_reference_t<, EmptyClass> is EmptyClass, to which ExplicitTo is + // not implicitly convertible + STATIC_ASSERT(!test, EmptyClass>()); + + STATIC_ASSERT(test&>()); + STATIC_ASSERT(test&&>()); + STATIC_ASSERT(!test>()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + // https://github.com/ericniebler/stl2/issues/338 + STATIC_ASSERT(test>()); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!test const&, MoveOnly>()); + STATIC_ASSERT(test const&, MoveOnly&&>()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(test const&>()); + + STATIC_ASSERT( + std::is_same_v, common_reference_t&, Interconvertible<1> const&>>); + STATIC_ASSERT(!test&, Interconvertible<1> const&>()); + + STATIC_ASSERT(test>()); +} // namespace test_common_reference_with + +namespace test_common_with { + template + struct ExplicitFromConstLvalue { + explicit ExplicitFromConstLvalue(T const&) {} + }; +} // namespace test_common_with + +template +struct std::common_type> { + using type = test_common_with::ExplicitFromConstLvalue; +}; +template +struct std::common_type, T> { + using type = test_common_with::ExplicitFromConstLvalue; +}; + +namespace test_common_with { + using std::common_with, std::common_type_t, std::is_same_v; + + template + constexpr bool test() { + constexpr bool result = common_with; + STATIC_ASSERT(common_with == result); + return result; + } + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test, int>()); + + STATIC_ASSERT(test, ExplicitFromConstLvalue>()); + STATIC_ASSERT(!test>()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test*>()); + + STATIC_ASSERT(is_same_v, EmptyClass>, EmptyClass>); + STATIC_ASSERT(is_same_v>, EmptyClass>); + STATIC_ASSERT(!test, EmptyClass>()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test>()); + + STATIC_ASSERT(is_same_v>, Immobile>); + STATIC_ASSERT(is_same_v, Immobile>, Immobile>); + STATIC_ASSERT(!test>()); +} // namespace test_common_with + +namespace test_integral_concepts { + using std::integral, std::signed_integral, std::unsigned_integral; + + namespace subsumption { + enum class is { not_integral, integral, signed_integral, unsigned_integral, ull }; + + template + constexpr is f(T&&) { + return is::not_integral; + } + template + constexpr is f(T) { + return is::integral; + } + template + constexpr is f(T) { + return is::signed_integral; + } + template + constexpr is f(T) { + return is::unsigned_integral; + } + constexpr is f(unsigned long long) { + return is::ull; + } + + constexpr bool test_subsumption() { + STATIC_ASSERT(f(0.0f) == is::not_integral); + STATIC_ASSERT(f(0.0) == is::not_integral); + STATIC_ASSERT(f(0) == is::signed_integral); + STATIC_ASSERT(f(0u) == is::unsigned_integral); + STATIC_ASSERT(f('a') == is::signed_integral || f('a') == is::unsigned_integral); + STATIC_ASSERT(f(nullptr) == is::not_integral); + STATIC_ASSERT(f(0ull) == is::ull); + STATIC_ASSERT(f(static_cast(nullptr)) == is::not_integral); + struct A {}; + STATIC_ASSERT(f(static_cast(nullptr)) == is::not_integral); + STATIC_ASSERT(f(static_cast(nullptr)) == is::not_integral); + return true; + } + STATIC_ASSERT(test_subsumption()); + } // namespace subsumption + +#pragma warning(push) +#pragma warning(disable : 4180) // qualifier applied to function type has no meaning; ignored + enum class is_signed { no, yes, NA }; + + template + constexpr bool test_integral() { + constexpr bool result = integral; + STATIC_ASSERT(integral == result); + STATIC_ASSERT(integral == result); + STATIC_ASSERT(integral == result); + if constexpr (!result) { + STATIC_ASSERT(S == is_signed::NA); + STATIC_ASSERT(!signed_integral); + STATIC_ASSERT(!signed_integral); + STATIC_ASSERT(!signed_integral); + STATIC_ASSERT(!signed_integral); + STATIC_ASSERT(!unsigned_integral); + STATIC_ASSERT(!unsigned_integral); + STATIC_ASSERT(!unsigned_integral); + STATIC_ASSERT(!unsigned_integral); + } else if constexpr (S == is_signed::yes) { + STATIC_ASSERT(signed_integral); + STATIC_ASSERT(signed_integral); + STATIC_ASSERT(signed_integral); + STATIC_ASSERT(signed_integral); + STATIC_ASSERT(!unsigned_integral); + STATIC_ASSERT(!unsigned_integral); + STATIC_ASSERT(!unsigned_integral); + STATIC_ASSERT(!unsigned_integral); + } else { + STATIC_ASSERT(!signed_integral); + STATIC_ASSERT(!signed_integral); + STATIC_ASSERT(!signed_integral); + STATIC_ASSERT(!signed_integral); + STATIC_ASSERT(unsigned_integral); + STATIC_ASSERT(unsigned_integral); + STATIC_ASSERT(unsigned_integral); + STATIC_ASSERT(unsigned_integral); + } + return result; + } +#pragma warning(pop) + + STATIC_ASSERT(test_integral()); + STATIC_ASSERT(test_integral()); + STATIC_ASSERT(test_integral()); + STATIC_ASSERT(test_integral()); + STATIC_ASSERT(test_integral()); + + STATIC_ASSERT(test_integral()); + STATIC_ASSERT(test_integral()); + STATIC_ASSERT(test_integral()); + STATIC_ASSERT(test_integral()); + STATIC_ASSERT(test_integral()); + + STATIC_ASSERT(test_integral()); + STATIC_ASSERT(test_integral}>()); + STATIC_ASSERT(test_integral}>()); + STATIC_ASSERT(test_integral()); + STATIC_ASSERT(test_integral()); + + STATIC_ASSERT(!test_integral()); + STATIC_ASSERT(!test_integral()); + STATIC_ASSERT(!test_integral()); + + STATIC_ASSERT(!test_integral()); + STATIC_ASSERT(!test_integral()); + + STATIC_ASSERT(!test_integral()); + STATIC_ASSERT(!test_integral()); + STATIC_ASSERT(!test_integral()); + STATIC_ASSERT(!test_integral()); + STATIC_ASSERT(!test_integral()); + + STATIC_ASSERT(!test_integral()); + STATIC_ASSERT(!test_integral()); + STATIC_ASSERT(!test_integral, is_signed::NA>()); + STATIC_ASSERT(!test_integral()); + + enum int_enum : int {}; + STATIC_ASSERT(!test_integral()); + + STATIC_ASSERT(test_integral()); + STATIC_ASSERT(test_integral()); +} // namespace test_integral_concepts + +namespace test_floating_point { + using std::floating_point; + +#pragma warning(push) +#pragma warning(disable : 4180) // qualifier applied to function type has no meaning; ignored + template + constexpr bool test_floating_point() { + constexpr bool result = floating_point; + STATIC_ASSERT(floating_point == result); + STATIC_ASSERT(floating_point == result); + STATIC_ASSERT(floating_point == result); + return result; + } +#pragma warning(pop) + + STATIC_ASSERT(!test_floating_point()); + STATIC_ASSERT(!test_floating_point()); + STATIC_ASSERT(!test_floating_point()); + STATIC_ASSERT(!test_floating_point()); + STATIC_ASSERT(!test_floating_point()); + + STATIC_ASSERT(!test_floating_point()); + STATIC_ASSERT(!test_floating_point()); + STATIC_ASSERT(!test_floating_point()); + STATIC_ASSERT(!test_floating_point()); + STATIC_ASSERT(!test_floating_point()); + + STATIC_ASSERT(!test_floating_point()); + STATIC_ASSERT(!test_floating_point()); + STATIC_ASSERT(!test_floating_point()); + STATIC_ASSERT(!test_floating_point()); + STATIC_ASSERT(!test_floating_point()); + + STATIC_ASSERT(test_floating_point()); + STATIC_ASSERT(test_floating_point()); + STATIC_ASSERT(test_floating_point()); + + STATIC_ASSERT(!test_floating_point()); + STATIC_ASSERT(!test_floating_point()); + + STATIC_ASSERT(!test_floating_point()); + STATIC_ASSERT(!test_floating_point()); + STATIC_ASSERT(!test_floating_point()); + STATIC_ASSERT(!test_floating_point()); + STATIC_ASSERT(!test_floating_point()); + + STATIC_ASSERT(!test_floating_point()); + STATIC_ASSERT(!test_floating_point()); + STATIC_ASSERT(!test_floating_point>()); + STATIC_ASSERT(!test_floating_point()); + + enum int_enum : int {}; + STATIC_ASSERT(!test_floating_point()); + + STATIC_ASSERT(!test_floating_point()); + STATIC_ASSERT(!test_floating_point()); +} // namespace test_floating_point + +namespace test_assignable_from { + using std::assignable_from; + + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + + STATIC_ASSERT(assignable_from); + STATIC_ASSERT(assignable_from); + STATIC_ASSERT(assignable_from); + STATIC_ASSERT(assignable_from); + STATIC_ASSERT(assignable_from); + STATIC_ASSERT(assignable_from); + + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + + STATIC_ASSERT(assignable_from); + STATIC_ASSERT(assignable_from); + + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + + STATIC_ASSERT(assignable_from); + STATIC_ASSERT(assignable_from); + STATIC_ASSERT(assignable_from); + STATIC_ASSERT(assignable_from); + STATIC_ASSERT(assignable_from); + STATIC_ASSERT(assignable_from); + + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + + // assignment operator exists, but no common_reference_with + struct AssignButUncommon { + AssignButUncommon& operator=(EmptyClass const&); + }; + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + + // assignment operator exists, with common_reference_with + struct AssignAndCommon { + AssignAndCommon(EmptyClass const&); + AssignAndCommon& operator=(EmptyClass const&) &; + }; + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + + STATIC_ASSERT(assignable_from); + STATIC_ASSERT(assignable_from); + STATIC_ASSERT(assignable_from); + STATIC_ASSERT(assignable_from); + STATIC_ASSERT(assignable_from); + STATIC_ASSERT(assignable_from); + + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + + struct VoidReturn { + void operator=(EmptyClass); + }; + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + + struct EvilReturn { + struct EvilCommaOverload { + template + IncompleteClass operator,(U&&); + }; + + EvilCommaOverload operator=(int); + }; + STATIC_ASSERT(!assignable_from); + + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + STATIC_ASSERT(!assignable_from); + + STATIC_ASSERT(assignable_from*&, DoNotInstantiate*>); +} // namespace test_assignable_from + +namespace test_destructible { + using std::destructible; + + using void_function = void(); + + class PublicDestructor { + public: + ~PublicDestructor() {} + }; + class ProtectedDestructor { + protected: + ~ProtectedDestructor() {} + }; + + class VirtualPublicDestructor { + public: + virtual ~VirtualPublicDestructor() {} + }; + class VirtualProtectedDestructor { + protected: + virtual ~VirtualProtectedDestructor() {} + }; + class VirtualPrivateDestructor { + private: + virtual ~VirtualPrivateDestructor() {} + }; + class DeletedPublicDestructor { + public: + ~DeletedPublicDestructor() = delete; + }; + class DeletedProtectedDestructor { + protected: + ~DeletedProtectedDestructor() = delete; + }; + class DeletedPrivateDestructor { + private: + ~DeletedPrivateDestructor() = delete; + }; + + class DeletedVirtualPublicDestructor { + public: + virtual ~DeletedVirtualPublicDestructor() = delete; + }; + class DeletedVirtualProtectedDestructor { + protected: + virtual ~DeletedVirtualProtectedDestructor() = delete; + }; + class DeletedVirtualPrivateDestructor { + private: + virtual ~DeletedVirtualPrivateDestructor() = delete; + }; + +#pragma warning(push) +#pragma warning(disable : 4180) // qualifier applied to function type has no meaning; ignored + template + constexpr bool test() { + constexpr bool result = destructible; + STATIC_ASSERT(destructible == result); + STATIC_ASSERT(destructible == result); + STATIC_ASSERT(destructible == result); + return result; + } +#pragma warning(pop) + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + // Test inaccessible destructors + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + // Test deleted constructors + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); +} // namespace test_destructible + +namespace test_constructible_from { + using std::constructible_from, std::initializer_list; + +#pragma warning(push) +#pragma warning(disable : 4180) // qualifier applied to function type has no meaning; ignored + template + constexpr bool test() { + constexpr bool result = constructible_from; + STATIC_ASSERT(constructible_from == result); + STATIC_ASSERT(constructible_from == result); + STATIC_ASSERT(constructible_from == result); + return result; + } +#pragma warning(pop) + + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(!test()); // https://github.com/ericniebler/stl2/issues/301 + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + +#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-752709 + STATIC_ASSERT(test()); +#endif // TRANSITION, VSO-752709 + + STATIC_ASSERT(test>()); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + // Indestructible types are not constructible + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test>()); + STATIC_ASSERT(test>()); + STATIC_ASSERT(test>()); + STATIC_ASSERT(test>()); + STATIC_ASSERT(test>()); + STATIC_ASSERT(test&>()); + + STATIC_ASSERT(test>()); + STATIC_ASSERT(test&>()); + + STATIC_ASSERT(test>()); + STATIC_ASSERT(test>()); + STATIC_ASSERT(test&>()); +#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-752709 + STATIC_ASSERT(test>()); +#endif // TRANSITION, VSO-752709 + + struct Multiparameter { + explicit Multiparameter(int); + Multiparameter(int, double); + Multiparameter(int, long, double); + Multiparameter(char) = delete; + }; + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!test() || is_permissive); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + struct ExplicitToDeduced { + template + explicit operator T() const; + }; + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + // Binding through reference-compatible type is required to perform + // direct-initialization as described in N4849 [over.match.ref]/1.1: + STATIC_ASSERT(test>()); +#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-752709 + STATIC_ASSERT(test>()); +#endif // TRANSITION, VSO-752709 + STATIC_ASSERT(test>()); + + // Binding through temporary behaves like copy-initialization, + // see N4849 [dcl.init.ref]/5.4: +#ifndef __clang__ // TRANSITION, LLVM-44688 + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test>()); +#endif // TRANSITION, LLVM-44688 + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test>()); + + struct ImmobileExplicitFromInt { + ImmobileExplicitFromInt() = default; + ImmobileExplicitFromInt(ImmobileExplicitFromInt&&) = delete; + explicit ImmobileExplicitFromInt(int); + }; + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); +} // namespace test_constructible_from + +namespace test_default_initializable { + using std::default_initializable, std::initializer_list; + + STATIC_ASSERT(default_initializable); +#if defined(MSVC_INTERNAL_TESTING) || defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-952724 + STATIC_ASSERT(!default_initializable); +#endif // TRANSITION, DevCom-952724 + STATIC_ASSERT(default_initializable); +#if defined(MSVC_INTERNAL_TESTING) || defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-952724 + STATIC_ASSERT(!default_initializable); +#endif // TRANSITION, DevCom-952724 + STATIC_ASSERT(default_initializable); + STATIC_ASSERT(!default_initializable); + + STATIC_ASSERT(default_initializable); + STATIC_ASSERT(default_initializable); + + STATIC_ASSERT(default_initializable); + STATIC_ASSERT(default_initializable); + STATIC_ASSERT(default_initializable); + STATIC_ASSERT(!default_initializable); + STATIC_ASSERT(!default_initializable); + STATIC_ASSERT(!default_initializable); +#if defined(MSVC_INTERNAL_TESTING) || defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-952724 + STATIC_ASSERT(!default_initializable); +#endif // TRANSITION, DevCom-952724 + + STATIC_ASSERT(!default_initializable); + STATIC_ASSERT(!default_initializable); + STATIC_ASSERT(!default_initializable); + + STATIC_ASSERT(!default_initializable); + STATIC_ASSERT(!default_initializable); + + STATIC_ASSERT(!default_initializable); + STATIC_ASSERT(!default_initializable); + STATIC_ASSERT(!default_initializable); + STATIC_ASSERT(!default_initializable); + STATIC_ASSERT(!default_initializable); + + STATIC_ASSERT(default_initializable); + STATIC_ASSERT(default_initializable); + STATIC_ASSERT(default_initializable); + STATIC_ASSERT(default_initializable); + + STATIC_ASSERT(default_initializable>); + + STATIC_ASSERT(default_initializable); + STATIC_ASSERT(default_initializable); + + STATIC_ASSERT(default_initializable); + STATIC_ASSERT(default_initializable); + STATIC_ASSERT(default_initializable); + + STATIC_ASSERT(!default_initializable); + STATIC_ASSERT(!default_initializable); + + STATIC_ASSERT(!default_initializable); + STATIC_ASSERT(!default_initializable); + + class PrivateDefault { + PrivateDefault(); + }; + STATIC_ASSERT(!default_initializable); + + struct S { + int x; + }; + STATIC_ASSERT(default_initializable); +#if defined(MSVC_INTERNAL_TESTING) || defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-952724 + STATIC_ASSERT(!default_initializable); +#endif // TRANSITION, DevCom-952724 + + // Also test GH-1603 "default_initializable accepts types that are not default-initializable" +#if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-1326684 + STATIC_ASSERT(!default_initializable); +#else // ^^^ no workaround / assert bug so we'll notice when it's fixed vvv + STATIC_ASSERT(default_initializable); +#endif // TRANSITION, DevCom-1326684 +} // namespace test_default_initializable + +namespace test_move_constructible { + using std::move_constructible; + + STATIC_ASSERT(move_constructible); + STATIC_ASSERT(move_constructible); + STATIC_ASSERT(move_constructible); + STATIC_ASSERT(!move_constructible); + + STATIC_ASSERT(move_constructible); + STATIC_ASSERT(move_constructible); + + STATIC_ASSERT(!move_constructible); + STATIC_ASSERT(!move_constructible); + STATIC_ASSERT(!move_constructible); + + STATIC_ASSERT(move_constructible); + STATIC_ASSERT(move_constructible); + STATIC_ASSERT(move_constructible); + STATIC_ASSERT(move_constructible); + + STATIC_ASSERT(!move_constructible); + + STATIC_ASSERT(move_constructible); + STATIC_ASSERT(move_constructible); + STATIC_ASSERT(move_constructible); + STATIC_ASSERT(move_constructible); + STATIC_ASSERT(move_constructible); + STATIC_ASSERT(!move_constructible); + STATIC_ASSERT(!move_constructible); + STATIC_ASSERT(!move_constructible); + STATIC_ASSERT(move_constructible); + STATIC_ASSERT(move_constructible); + + STATIC_ASSERT(move_constructible); + STATIC_ASSERT(!move_constructible); + STATIC_ASSERT(!move_constructible); + STATIC_ASSERT(move_constructible); + STATIC_ASSERT(move_constructible); + + STATIC_ASSERT(move_constructible); + STATIC_ASSERT(move_constructible); + STATIC_ASSERT(move_constructible); + STATIC_ASSERT(move_constructible); + + STATIC_ASSERT(!move_constructible); + + struct ImplicitlyDeletedMove { + ImplicitlyDeletedMove(ImplicitlyDeletedMove const&); + }; + STATIC_ASSERT(move_constructible); +} // namespace test_move_constructible + +namespace test_ranges_swap { + namespace ranges = std::ranges; + + // clang-format off + template + constexpr bool can_swap = false; + template + requires requires { ranges::swap(std::declval(), std::declval()); } + constexpr bool can_swap = true; + + template + constexpr bool can_nothrow_swap = false; + template + requires can_swap + constexpr bool can_nothrow_swap = noexcept(ranges::swap(std::declval(), std::declval())); + // clang-format on + + STATIC_ASSERT(!can_swap); + STATIC_ASSERT(!can_swap); + STATIC_ASSERT(!can_swap); + STATIC_ASSERT(!can_swap); + + STATIC_ASSERT(can_nothrow_swap); + STATIC_ASSERT(!can_swap); + STATIC_ASSERT(can_nothrow_swap); + STATIC_ASSERT(!can_swap); + + STATIC_ASSERT(!can_swap); + STATIC_ASSERT(!can_swap); + STATIC_ASSERT(!can_swap); + STATIC_ASSERT(!can_swap); + + STATIC_ASSERT(!can_swap); + STATIC_ASSERT(!can_swap); + STATIC_ASSERT(!can_swap); + STATIC_ASSERT(!can_swap); + + STATIC_ASSERT(!can_swap); + STATIC_ASSERT(!can_swap); + + STATIC_ASSERT(can_nothrow_swap); + STATIC_ASSERT(can_nothrow_swap); + STATIC_ASSERT(!can_swap); + STATIC_ASSERT(!can_swap); + STATIC_ASSERT(can_nothrow_swap); + STATIC_ASSERT(!can_swap); + STATIC_ASSERT(!can_swap); + STATIC_ASSERT(can_nothrow_swap); + STATIC_ASSERT(!can_swap); + + STATIC_ASSERT(!can_swap); + STATIC_ASSERT(!can_swap); + + STATIC_ASSERT(!can_swap); + + struct SemithrowCopyOnly { + SemithrowCopyOnly() = default; + SemithrowCopyOnly(SemithrowCopyOnly const&) noexcept = default; + + SemithrowCopyOnly& operator=(SemithrowCopyOnly const&) noexcept(false) { + return *this; + } + }; + STATIC_ASSERT(can_swap); + STATIC_ASSERT(!can_nothrow_swap); + STATIC_ASSERT(can_swap); + STATIC_ASSERT(!can_nothrow_swap); + + struct SemithrowMoveOnly { + SemithrowMoveOnly() = default; + SemithrowMoveOnly(SemithrowMoveOnly&&) noexcept(false) {} + SemithrowMoveOnly& operator=(SemithrowMoveOnly&&) noexcept = default; + }; + STATIC_ASSERT(can_swap); + STATIC_ASSERT(!can_nothrow_swap); + STATIC_ASSERT(can_swap); + STATIC_ASSERT(!can_nothrow_swap); + + struct NothrowMoveOnly { + NothrowMoveOnly() = default; + NothrowMoveOnly(NothrowMoveOnly&&) noexcept = default; + NothrowMoveOnly& operator=(NothrowMoveOnly&&) noexcept = default; + }; + STATIC_ASSERT(can_nothrow_swap); + STATIC_ASSERT(can_nothrow_swap); + + struct NotMoveConstructible { + NotMoveConstructible() = default; + NotMoveConstructible(NotMoveConstructible&&) = delete; + NotMoveConstructible& operator=(NotMoveConstructible&&) = default; + }; + STATIC_ASSERT(!can_swap); + STATIC_ASSERT(!can_swap); + + struct NotMoveAssignable { + NotMoveAssignable(NotMoveAssignable&&) = default; + NotMoveAssignable& operator=(NotMoveAssignable&&) = delete; + }; + STATIC_ASSERT(!can_swap); + STATIC_ASSERT(!can_swap); + + struct ImmobileNothrowSwap { + ImmobileNothrowSwap() = default; + ImmobileNothrowSwap(ImmobileNothrowSwap&&) = delete; + ImmobileNothrowSwap& operator=(ImmobileNothrowSwap&&) = delete; + friend void swap(ImmobileNothrowSwap&, ImmobileNothrowSwap&) noexcept {} + }; + STATIC_ASSERT(can_nothrow_swap); + STATIC_ASSERT(can_nothrow_swap); + + struct HasThrowingSwap { + friend void swap(HasThrowingSwap&, HasThrowingSwap&) {} + }; + STATIC_ASSERT(can_swap); + STATIC_ASSERT(!can_nothrow_swap); + STATIC_ASSERT(can_swap); + STATIC_ASSERT(!can_nothrow_swap); + + // Derives from type in std with overloaded swap to validate the poison pill + struct Unswappable : std::pair { + Unswappable() = default; + Unswappable(Unswappable const&) = delete; + Unswappable(Unswappable&&) = delete; + }; + STATIC_ASSERT(!can_swap); + + STATIC_ASSERT(!can_swap); + STATIC_ASSERT(!can_swap); + STATIC_ASSERT(!can_swap); + + STATIC_ASSERT(!can_swap); + STATIC_ASSERT(!can_swap); + STATIC_ASSERT(!can_swap); + + // The wording allows customization of swap for unions as well + union U { + U(U const&) = delete; + U& operator=(U const&) = delete; + + friend void swap(U&, U&) {} + }; + STATIC_ASSERT(can_swap); + + namespace adl_barrier { + struct ConstrainedSwappable { + ConstrainedSwappable() = default; + ConstrainedSwappable(ConstrainedSwappable const&) = default; + ConstrainedSwappable(ConstrainedSwappable&&) = default; + }; + // ensure equally-specialized but more-constrained non-member swap is preferred to the poison pill + template T> + void swap(T&, T&) {} + } // namespace adl_barrier + STATIC_ASSERT(can_swap); + STATIC_ASSERT(!can_swap); + + struct MyInt { + int i = 42; + }; + STATIC_ASSERT(can_nothrow_swap); + + struct YourInt { + int i = 13; + }; + STATIC_ASSERT(can_nothrow_swap); + + constexpr void swap(MyInt& x, YourInt& y) noexcept { + ranges::swap(x.i, y.i); + } + constexpr void swap(YourInt& x, MyInt& y) noexcept { + ranges::swap(x.i, y.i); + } + STATIC_ASSERT(can_nothrow_swap); + STATIC_ASSERT(can_nothrow_swap); + + struct DoNotUseFallback { + DoNotUseFallback() = default; + DoNotUseFallback(DoNotUseFallback&&) noexcept { + abort(); + } + DoNotUseFallback& operator=(DoNotUseFallback&&) noexcept { + return *this; + } + friend constexpr void swap(DoNotUseFallback&, DoNotUseFallback&) noexcept {} + }; + + constexpr auto for_each_232 = [](auto (&array)[2][3][2], auto f) { + for (int i = 0; i < 2; ++i) { + for (int j = 0; j < 3; ++j) { + for (int k = 0; k < 2; ++k) { + f(array[i][j][k]); + } + } + } + }; + + constexpr bool compile_time_tests() { + using ranges::swap; + + { + DoNotUseFallback x, y; + swap(x, y); + } + { + // Non-array swap + int i = 1; + int j = 2; + swap(i, j); + STATIC_ASSERT(noexcept(swap(i, j))); + assert(i == 2); + assert(j == 1); + } + { + // Array swap + int a[3] = {1, 2, 3}; + int b[3] = {4, 5, 6}; + swap(a, b); + STATIC_ASSERT(noexcept(swap(a, b))); + assert(a[0] == 4); + assert(a[1] == 5); + assert(a[2] == 6); + assert(b[0] == 1); + assert(b[1] == 2); + assert(b[2] == 3); + } + { + // Multidimensional array + int a[2][3][2] = { + {{0, 1}, {2, 3}, {4, 5}}, + {{6, 7}, {8, 9}, {10, 11}}, + }; + int b[2][3][2] = { + {{12, 13}, {14, 15}, {16, 17}}, + {{18, 19}, {20, 21}, {22, 23}}, + }; + swap(a, b); + STATIC_ASSERT(noexcept(swap(a, b))); + int counter = 0; + auto check = [&counter](int const& i) { + assert(i == counter); + ++counter; + }; + for_each_232(b, check); + for_each_232(a, check); + } + { + // Cross-type multidimensional array swap + MyInt a[2][3][2] = { + {{{0}, {1}}, {{2}, {3}}, {{4}, {5}}}, + {{{6}, {7}}, {{8}, {9}}, {{10}, {11}}}, + }; + YourInt b[2][3][2] = { + {{{12}, {13}}, {{14}, {15}}, {{16}, {17}}}, + {{{18}, {19}}, {{20}, {21}}, {{22}, {23}}}, + }; + swap(a, b); + STATIC_ASSERT(noexcept(swap(a, b))); + int counter = 0; + auto check = [&counter](auto const& e) { + assert(e.i == counter); + ++counter; + }; + for_each_232(b, check); + for_each_232(a, check); + } + return true; + } + STATIC_ASSERT(compile_time_tests()); + + void runtime_tests() { + using ranges::swap; + compile_time_tests(); + + { + // Non-array swap + auto i = std::make_unique(1); + auto j = std::make_unique(2); + swap(i, j); + STATIC_ASSERT(noexcept(swap(i, j))); + assert(*i == 2); + assert(*j == 1); + } + { + // Array swap + std::unique_ptr a[3]; + for (int i = 0; i < 3; ++i) { + a[i] = std::make_unique(i + 1); + } + std::unique_ptr b[3]; + for (int i = 0; i < 3; ++i) { + b[i] = std::make_unique(i + 4); + } + swap(a, b); + STATIC_ASSERT(noexcept(swap(a, b))); + assert(*a[0] == 4); + assert(*a[1] == 5); + assert(*a[2] == 6); + assert(*b[0] == 1); + assert(*b[1] == 2); + assert(*b[2] == 3); + } + { + // Multidimensional array + std::unique_ptr a[2][3][2]; + std::unique_ptr b[2][3][2]; + + int counter = 0; + auto init = [&counter](std::unique_ptr& e) { e = std::make_unique(counter++); }; + auto check = [&counter](std::unique_ptr const& e) { + assert(*e == counter); + ++counter; + }; + + for_each_232(a, init); + for_each_232(b, init); + swap(a, b); + STATIC_ASSERT(noexcept(swap(a, b))); + counter = 0; + for_each_232(b, check); + for_each_232(a, check); + } + } +} // namespace test_ranges_swap + +namespace test_swappable { + using std::swappable; + + STATIC_ASSERT(swappable); + STATIC_ASSERT(swappable); + STATIC_ASSERT(!swappable); + STATIC_ASSERT(!swappable); + STATIC_ASSERT(swappable); + + STATIC_ASSERT(swappable); + STATIC_ASSERT(swappable); + + STATIC_ASSERT(!swappable); + STATIC_ASSERT(!swappable); + STATIC_ASSERT(!swappable); + + STATIC_ASSERT(swappable); + // It may not be a great idea that swappable admits reference types and treats them as lvalues, but that's what + // is_swappable does, so: + STATIC_ASSERT(swappable); + STATIC_ASSERT(swappable); + + STATIC_ASSERT(swappable); + STATIC_ASSERT(swappable); + STATIC_ASSERT(swappable); + + // test non-referenceable types + STATIC_ASSERT(!swappable); + STATIC_ASSERT(!swappable); + STATIC_ASSERT(!swappable); + + STATIC_ASSERT(swappable); + STATIC_ASSERT(swappable); + STATIC_ASSERT(swappable); + + namespace non_member { + struct OnlyRvalueSwappable : Immobile {}; + void swap(OnlyRvalueSwappable&&, OnlyRvalueSwappable&&) {} + // swappable only cares about lvalue swaps + STATIC_ASSERT(!swappable); + STATIC_ASSERT(!swappable); + STATIC_ASSERT(!swappable); + + struct DeletedSwap { + friend void swap(DeletedSwap&, DeletedSwap&) = delete; + }; + // a deleted swap overload is correctly ignored + STATIC_ASSERT(swappable); + STATIC_ASSERT(swappable); + STATIC_ASSERT(swappable); + } // namespace non_member + + namespace underconstrained { + struct AmbiguousSwap {}; + + template + void swap(T&, T&); + + // a swap overload that isn't more specialized or constrained than the poison pill is ignored + STATIC_ASSERT(swappable); + STATIC_ASSERT(swappable); + STATIC_ASSERT(swappable); + } // namespace underconstrained +} // namespace test_swappable + +namespace test_swappable_with { + using std::swappable_with; + + template + constexpr bool test() { + STATIC_ASSERT(swappable_with == swappable_with); + return swappable_with; + } + + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test()); + + STATIC_ASSERT(test() == is_permissive); + STATIC_ASSERT(test()); + STATIC_ASSERT(test() == is_permissive); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test() == is_permissive); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test() == is_permissive); + + struct LvalueAndRvalueSwappable {}; + void swap(LvalueAndRvalueSwappable&&, LvalueAndRvalueSwappable&&) {} + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + template + struct ImmobileAndSwappable : Immobile { + friend void swap(ImmobileAndSwappable&, ImmobileAndSwappable&) {} + }; + template + void swap(ImmobileAndSwappable&, ImmobileAndSwappable&) {} + + struct ImmobileAndNotSwappable : Immobile {}; + void swap(ImmobileNonMemberSwap&, ImmobileAndNotSwappable&) {} + void swap(ImmobileAndNotSwappable&, ImmobileNonMemberSwap&) {} + + struct CanSwapButUncommon {}; + void swap(ImmobileNonMemberSwap&, CanSwapButUncommon&) {} + void swap(CanSwapButUncommon&, ImmobileNonMemberSwap&) {} + + template + struct AsymmetricallySwappable {}; + void swap(AsymmetricallySwappable<0>&, AsymmetricallySwappable<1>&) {} +} // namespace test_swappable_with + +// common_type specializations to satisfy swappable_with's common_reference_with requirement +template <> +struct std::common_type { + using type = Omniconvertible; +}; +template <> +struct std::common_type { + using type = Omniconvertible; +}; + +template +struct std::common_type, + test_swappable_with::AsymmetricallySwappable> { + using type = Omniconvertible; +}; + +template +struct std::common_type, test_swappable_with::ImmobileAndSwappable> { + using type = Omniconvertible; +}; + +namespace test_swappable_with { + // Not swappable_with: a constituent type is not swappable + STATIC_ASSERT(!test()); + // Not swappable_with: common_reference_with requirement is not satisfied + STATIC_ASSERT(!test()); + // Not swappable_with: asymmetric + STATIC_ASSERT(!test&, AsymmetricallySwappable<1>&>()); + // swappable_with: all requirements met + STATIC_ASSERT(test&, ImmobileAndSwappable<1>&>()); + + namespace example { + // The example from [concept.swappable] with changes per the proposed resolution of LWG-3175: + // clang-format off + namespace ranges = std::ranges; + + template U> + void value_swap(T&& t, U&& u) { + ranges::swap(std::forward(t), std::forward(u)); + } + + template + void lv_swap(T& t1, T& t2) { + ranges::swap(t1, t2); + } + + namespace N { + struct A { int m; }; + struct Proxy { + A* a; + Proxy(A& a) : a{&a} {} + friend void swap(Proxy x, Proxy y) { + ranges::swap(*x.a, *y.a); + } + }; + Proxy proxy(A& a) { return Proxy{a}; } + } + + void test() { + int i = 1, j = 2; + lv_swap(i, j); + assert(i == 2 && j == 1); + + N::A a1 = { 5 }; + N::A a2 = { -5 }; + value_swap(a1, proxy(a2)); + assert(a1.m == -5 && a2.m == 5); + + // additional test cases not from [concept.swappable] for completeness: + STATIC_ASSERT(std::is_same_v, N::Proxy>); + STATIC_ASSERT(swappable_with); + + value_swap(proxy(a1), a2); + assert(a1.m == 5 && a2.m == -5); + + value_swap(proxy(a1), proxy(a2)); + assert(a1.m == -5 && a2.m == 5); + + value_swap(a1, a2); + assert(a1.m == 5 && a2.m == -5); + // end additional test cases + } + // clang-format on + } // namespace example +} // namespace test_swappable_with + +namespace test_copy_constructible { + using std::copy_constructible; + +#pragma warning(push) +#pragma warning(disable : 4180) // qualifier applied to function type has no meaning; ignored + template + constexpr bool test() { + constexpr bool result = copy_constructible; + STATIC_ASSERT(copy_constructible == result); + if constexpr (std::is_scalar_v || std::is_reference_v) { + STATIC_ASSERT(copy_constructible == result); + STATIC_ASSERT(copy_constructible == result); + } else { + STATIC_ASSERT(!copy_constructible); + STATIC_ASSERT(!copy_constructible); + } + return result; + } +#pragma warning(pop) + + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!copy_constructible); + STATIC_ASSERT(copy_constructible); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + +#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-119526 + // https://github.com/ericniebler/stl2/issues/301 + struct NotMutableRef { + NotMutableRef() = default; + NotMutableRef(NotMutableRef const&) = default; + NotMutableRef(NotMutableRef&) = delete; + NotMutableRef(NotMutableRef&&) = default; + }; + struct NotConstRefRef { + NotConstRefRef() = default; + NotConstRefRef(NotConstRefRef const&) = default; + NotConstRefRef(NotConstRefRef&&) = default; + NotConstRefRef(NotConstRefRef const&&) = delete; + }; + + STATIC_ASSERT(!copy_constructible); + STATIC_ASSERT(!copy_constructible); +#endif // TRANSITION, VSO-119526 + + struct UserProvidedCopy { + UserProvidedCopy(UserProvidedCopy const&); + }; + STATIC_ASSERT(test()); + + class PrivateCopy { + private: + PrivateCopy(PrivateCopy const&); + }; + STATIC_ASSERT(!test()); + + struct MutatingCopyAbomination { + MutatingCopyAbomination(MutatingCopyAbomination&); // NB: not const& + void operator=(MutatingCopyAbomination&); // NB: not const& + }; + STATIC_ASSERT(!test()); +} // namespace test_copy_constructible + +namespace test_object_concepts { + using std::copyable, std::movable, std::regular, std::semiregular; + +#pragma warning(push) +#pragma warning(disable : 4180) // qualifier applied to function type has no meaning; ignored + template + constexpr bool test_movable() { + constexpr bool result = movable; + STATIC_ASSERT(!movable); + STATIC_ASSERT(movable == std::is_scalar_v); + STATIC_ASSERT(!movable); + return result; + } + + template + constexpr bool test_copyable() { + constexpr bool result = copyable; + STATIC_ASSERT(!copyable); + STATIC_ASSERT(copyable == std::is_scalar_v); + STATIC_ASSERT(!copyable); + return result; + } + + template + constexpr bool test_semiregular() { + constexpr bool result = semiregular; + STATIC_ASSERT(!semiregular); + STATIC_ASSERT(semiregular == std::is_scalar_v); + STATIC_ASSERT(!semiregular); + return result; + } + + template + constexpr bool test_regular() { + constexpr bool result = regular; + STATIC_ASSERT(!regular); + STATIC_ASSERT(regular == std::is_scalar_v); + STATIC_ASSERT(!regular); + return result; + } +#pragma warning(pop) + + STATIC_ASSERT(!test_movable()); + + STATIC_ASSERT(test_movable()); + STATIC_ASSERT(test_movable()); + + STATIC_ASSERT(!test_movable()); + STATIC_ASSERT(!test_movable()); // https://github.com/ericniebler/stl2/issues/310 + + STATIC_ASSERT(!test_movable()); + STATIC_ASSERT(!test_movable()); + + STATIC_ASSERT(!test_movable()); + + STATIC_ASSERT(test_movable()); + STATIC_ASSERT(test_movable()); + STATIC_ASSERT(!test_movable()); + STATIC_ASSERT(!test_movable()); + + STATIC_ASSERT(!test_copyable()); + + STATIC_ASSERT(test_copyable()); + STATIC_ASSERT(test_copyable()); + + STATIC_ASSERT(!test_copyable()); + STATIC_ASSERT(!test_copyable()); + + STATIC_ASSERT(!test_copyable()); + STATIC_ASSERT(!test_copyable()); + + STATIC_ASSERT(!test_copyable()); + + STATIC_ASSERT(test_copyable()); + STATIC_ASSERT(!test_copyable()); + STATIC_ASSERT(!test_copyable()); + STATIC_ASSERT(!test_copyable()); + + STATIC_ASSERT(!test_semiregular()); + + STATIC_ASSERT(test_semiregular()); + STATIC_ASSERT(test_semiregular()); + + STATIC_ASSERT(!test_semiregular()); + + STATIC_ASSERT(!test_semiregular()); + STATIC_ASSERT(!test_semiregular()); + STATIC_ASSERT(!test_semiregular()); + STATIC_ASSERT(!test_semiregular()); + STATIC_ASSERT(!test_semiregular()); + STATIC_ASSERT(test_semiregular()); + STATIC_ASSERT(test_semiregular()); + + STATIC_ASSERT(!test_regular()); + + STATIC_ASSERT(test_regular()); + STATIC_ASSERT(test_regular()); + + STATIC_ASSERT(!test_regular()); + + STATIC_ASSERT(!test_regular()); + STATIC_ASSERT(!test_regular()); + STATIC_ASSERT(!test_regular()); + STATIC_ASSERT(!test_regular()); + STATIC_ASSERT(!test_regular()); + STATIC_ASSERT(!test_regular()); + STATIC_ASSERT(!test_regular()); + STATIC_ASSERT(test_regular()); +} // namespace test_object_concepts + +namespace test_boolean_testable { + // Note: other than knowing the secret internal concept name, this is a portable test. + using std::__boolean_testable; + + // Better have these four, since we use them as examples in the Standard. + STATIC_ASSERT(__boolean_testable); + STATIC_ASSERT(__boolean_testable); + STATIC_ASSERT(__boolean_testable); + STATIC_ASSERT(__boolean_testable::reference>); + + STATIC_ASSERT(__boolean_testable); + + STATIC_ASSERT(__boolean_testable); + STATIC_ASSERT(__boolean_testable); + + enum unscoped_boolish : bool { No, Yes }; + STATIC_ASSERT(__boolean_testable); + + enum class scoped_boolish : bool { No, Yes }; + STATIC_ASSERT(!__boolean_testable); + + STATIC_ASSERT(!__boolean_testable); + + STATIC_ASSERT(__boolean_testable>); + STATIC_ASSERT(!__boolean_testable>); + + struct MutatingBoolConversion { + operator bool(); + }; + STATIC_ASSERT(__boolean_testable); + + template // values in [0, Archetype_max) select a requirement to violate + struct Archetype { + // clang-format off + operator bool() const requires (Select != 0); // Archetype<0> is not implicitly convertible to bool + explicit operator bool() const requires (Select < 2); // Archetype<1> is not explicitly convertible + // to bool (ambiguity) + void operator!() const requires (Select == 2); // !Archetype<2> does not model _Boolean_testable_impl + // clang-format on + }; + + STATIC_ASSERT(!__boolean_testable>); + STATIC_ASSERT(!__boolean_testable>); + STATIC_ASSERT(!__boolean_testable>); + STATIC_ASSERT(__boolean_testable>); +} // namespace test_boolean_testable + +namespace test_equality_comparable { + using std::equality_comparable; + +#pragma warning(push) +#pragma warning(disable : 4180) // qualifier applied to function type has no meaning; ignored + template + constexpr bool test() { + constexpr bool result = equality_comparable; + STATIC_ASSERT(equality_comparable == result); + if constexpr (!std::is_same_v>) { + STATIC_ASSERT(equality_comparable == result); + STATIC_ASSERT(equality_comparable == result); + STATIC_ASSERT(equality_comparable == result); + STATIC_ASSERT(equality_comparable == result); + } + return result; + } +#pragma warning(pop) + + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(!test()); + + template // selects one requirement to violate + struct Archetype {}; + + template + bool operator==(Archetype const&); + void operator==(Archetype<0> const&, Archetype<0> const&); // Archetype<0> == Archetype<0> is not __boolean_testable + + template + bool operator!=(Archetype const&); + void operator!=(Archetype<1> const&, Archetype<1> const&); // Archetype<1> != Archetype<1> is not __boolean_testable + + STATIC_ASSERT(!test>()); + STATIC_ASSERT(!test>()); + STATIC_ASSERT(test>()); +} // namespace test_equality_comparable + +namespace test_equality_comparable_with { + using std::equality_comparable_with; + +#pragma warning(push) +#pragma warning(disable : 4180) // qualifier applied to function type has no meaning; ignored + template + constexpr bool test() { + using std::is_same_v, std::add_lvalue_reference_t; + + constexpr bool result = equality_comparable_with; + STATIC_ASSERT(equality_comparable_with == result); + + if constexpr (!is_same_v>) { + STATIC_ASSERT(equality_comparable_with == result); + STATIC_ASSERT(equality_comparable_with == result); + STATIC_ASSERT(equality_comparable_with == result); + STATIC_ASSERT(equality_comparable_with == result); + } + + if constexpr (!is_same_v>) { + STATIC_ASSERT(equality_comparable_with == result); + STATIC_ASSERT(equality_comparable_with == result); + STATIC_ASSERT(equality_comparable_with == result); + STATIC_ASSERT(equality_comparable_with == result); + } + + if constexpr (!is_same_v> && !is_same_v>) { + STATIC_ASSERT(equality_comparable_with == result); + STATIC_ASSERT(equality_comparable_with == result); + STATIC_ASSERT(equality_comparable_with == result); + STATIC_ASSERT(equality_comparable_with == result); + + STATIC_ASSERT(equality_comparable_with == result); + STATIC_ASSERT(equality_comparable_with == result); + STATIC_ASSERT(equality_comparable_with == result); + STATIC_ASSERT(equality_comparable_with == result); + + STATIC_ASSERT(equality_comparable_with == result); + STATIC_ASSERT(equality_comparable_with == result); + STATIC_ASSERT(equality_comparable_with == result); + STATIC_ASSERT(equality_comparable_with == result); + + STATIC_ASSERT(equality_comparable_with == result); + STATIC_ASSERT(equality_comparable_with == result); + STATIC_ASSERT(equality_comparable_with == result); + STATIC_ASSERT(equality_comparable_with == result); + } + + return result; + } +#pragma warning(pop) + + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + template + struct CrossSpecializationComparable { + bool operator==(CrossSpecializationComparable const&) const; + bool operator!=(CrossSpecializationComparable const&) const; + }; + STATIC_ASSERT(test, CrossSpecializationComparable<0>>()); + + template + bool operator==(CrossSpecializationComparable const&, CrossSpecializationComparable const&); + template + bool operator!=(CrossSpecializationComparable const&, CrossSpecializationComparable const&); + + struct Common { // A common type for CrossSpecializationComparable<1> / <2> + Common(CrossSpecializationComparable<1>); + Common(CrossSpecializationComparable<2>); + + friend bool operator==(Common const&, Common const&) { + return true; + } + friend bool operator!=(Common const&, Common const&) { + return false; + } + }; + STATIC_ASSERT(test()); + STATIC_ASSERT(!test, Common>()); + STATIC_ASSERT(test, Common>()); + STATIC_ASSERT(test, Common>()); +} // namespace test_equality_comparable_with + +template <> +struct std::common_type, + test_equality_comparable_with::CrossSpecializationComparable<2>> { + using type = test_equality_comparable_with::Common; +}; +template <> +struct std::common_type, + test_equality_comparable_with::CrossSpecializationComparable<1>> { + using type = test_equality_comparable_with::Common; +}; + +namespace test_equality_comparable_with { + // CrossSpecializationComparable<0> / <1> have all the necessary operators, but fail common_reference_with. + STATIC_ASSERT(!test, CrossSpecializationComparable<1>>()); + // CrossSpecializationComparable<1> / <2> *do* satisfy common_reference_with. + STATIC_ASSERT(test, CrossSpecializationComparable<2>>()); +} // namespace test_equality_comparable_with + +namespace test_totally_ordered { + using std::totally_ordered; + +#pragma warning(push) +#pragma warning(disable : 4180) // qualifier applied to function type has no meaning; ignored + template + constexpr bool test() { + constexpr bool result = totally_ordered; + STATIC_ASSERT(totally_ordered == result); + if constexpr (!std::is_same_v>) { + STATIC_ASSERT(totally_ordered == result); + STATIC_ASSERT(totally_ordered == result); + STATIC_ASSERT(totally_ordered == result); + STATIC_ASSERT(totally_ordered == result); + } + return result; + } +#pragma warning(pop) + + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + constexpr unsigned int Archetype_max = 6; + template // values in [0, Archetype_max) select a requirement to violate + struct Archetype {}; + + template + bool operator==(Archetype const&); + void operator==(Archetype<0> const&, Archetype<0> const&); + + template + bool operator!=(Archetype const&); + void operator!=(Archetype<1> const&, Archetype<1> const&); + + template + bool operator<(Archetype const&); + void operator<(Archetype<2> const&, Archetype<2> const&); + + template + bool operator>(Archetype const&); + void operator>(Archetype<3> const&, Archetype<3> const&); + + template + bool operator<=(Archetype const&); + void operator<=(Archetype<4> const&, Archetype<4> const&); + + template + bool operator>=(Archetype const&); + void operator>=(Archetype<5> const&, Archetype<5> const&); + + template + constexpr void test_archetype_single() { + STATIC_ASSERT(!test>()); + } + + template + constexpr bool test_Archetype(std::index_sequence) { + STATIC_ASSERT(std::is_same_v, std::make_index_sequence>); + (test_archetype_single(), ...); + STATIC_ASSERT(test>()); + return true; + } + STATIC_ASSERT(test_Archetype(std::make_index_sequence{})); +} // namespace test_totally_ordered + +namespace test_totally_ordered_with { + using std::totally_ordered_with; + +#pragma warning(push) +#pragma warning(disable : 4180) // qualifier applied to function type has no meaning; ignored + template + constexpr bool test() { + constexpr bool result = totally_ordered_with; + STATIC_ASSERT(totally_ordered_with == result); + if constexpr (!std::is_same_v>) { + STATIC_ASSERT(totally_ordered_with == result); + STATIC_ASSERT(totally_ordered_with == result); + STATIC_ASSERT(totally_ordered_with == result); + STATIC_ASSERT(totally_ordered_with == result); + } + + if constexpr (!std::is_same_v>) { + STATIC_ASSERT(totally_ordered_with == result); + STATIC_ASSERT(totally_ordered_with == result); + STATIC_ASSERT(totally_ordered_with == result); + STATIC_ASSERT(totally_ordered_with == result); + } + + if constexpr (!std::is_same_v> && !std::is_same_v>) { + STATIC_ASSERT(totally_ordered_with == result); + STATIC_ASSERT(totally_ordered_with == result); + STATIC_ASSERT(totally_ordered_with == result); + STATIC_ASSERT(totally_ordered_with == result); + + STATIC_ASSERT(totally_ordered_with == result); + STATIC_ASSERT(totally_ordered_with == result); + STATIC_ASSERT(totally_ordered_with == result); + STATIC_ASSERT(totally_ordered_with == result); + + STATIC_ASSERT(totally_ordered_with == result); + STATIC_ASSERT(totally_ordered_with == result); + STATIC_ASSERT(totally_ordered_with == result); + STATIC_ASSERT(totally_ordered_with == result); + + STATIC_ASSERT(totally_ordered_with == result); + STATIC_ASSERT(totally_ordered_with == result); + STATIC_ASSERT(totally_ordered_with == result); + STATIC_ASSERT(totally_ordered_with == result); + } + + return result; + } +#pragma warning(pop) + + STATIC_ASSERT(!test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(!test()); + + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + + STATIC_ASSERT(test()); + + STATIC_ASSERT(test()); + + template + struct Ordered { + bool operator==(Ordered const&) const; + bool operator!=(Ordered const&) const; + bool operator<(Ordered const&) const; + bool operator>(Ordered const&) const; + bool operator<=(Ordered const&) const; + bool operator>=(Ordered const&) const; + }; + STATIC_ASSERT(test, Ordered<0>>()); + STATIC_ASSERT(test, Ordered<1>>()); + STATIC_ASSERT(test, Ordered<2>>()); + + template + bool operator==(Ordered const&, Ordered const&); + template + bool operator!=(Ordered const&, Ordered const&); + template + bool operator<(Ordered const&, Ordered const&); + template + bool operator>(Ordered const&, Ordered const&); + template + bool operator<=(Ordered const&, Ordered const&); + template + bool operator>=(Ordered const&, Ordered const&); + + struct Common { // a common type for Ordered<1> / <2> + Common(Ordered<1>); + Common(Ordered<2>); + friend bool operator==(Common const&, Common const&); + friend bool operator!=(Common const&, Common const&); + friend bool operator<(Common const&, Common const&); + friend bool operator>(Common const&, Common const&); + friend bool operator<=(Common const&, Common const&); + friend bool operator>=(Common const&, Common const&); + }; + STATIC_ASSERT(test()); +} // namespace test_totally_ordered_with + +template <> +struct std::common_type, test_totally_ordered_with::Ordered<2>> { + using type = test_totally_ordered_with::Common; +}; +template <> +struct std::common_type, test_totally_ordered_with::Ordered<1>> { + using type = test_totally_ordered_with::Common; +}; + +namespace test_totally_ordered_with { + // Ordered<0> / <1> have all the necessary operators, but fail common_reference_with + STATIC_ASSERT(!test, Ordered<1>>()); + // Common is the common type of (Ordered<1>, Common) and (Ordered<2>, Common) + STATIC_ASSERT(test, Common>()); + STATIC_ASSERT(test, Common>()); + // Ordered<1> / <2> have all the necessary operators, and model common_reference_with + STATIC_ASSERT(test, Ordered<2>>()); +} // namespace test_totally_ordered_with + +namespace test_invocable_concepts { + // Tests both invocable and regular_invocable concepts (since they're syntactically identical) + + using std::invocable, std::regular_invocable; + + template + constexpr bool test() { + constexpr bool result = invocable; + STATIC_ASSERT(regular_invocable == result); + return result; + } + + struct tag {}; + struct NotDerived {}; + + void cc_independent_tests() { + // PMD tests, which don't depend on calling conventions + { + using Fn = int tag::*; + STATIC_ASSERT(!test()); + { + // N4849 [func.require]/1.4: "... N == 1 and f is a pointer to data member of a class T and + // is_base_of_v> is true" + STATIC_ASSERT(test()); + STATIC_ASSERT(test&>()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + } + { + // N4849 [func.require]/1.5: "... N == 1 and f is a pointer to data member of a class T and + // remove_cvref_t is a specialization of reference_wrapper" + using T = std::reference_wrapper; + using DT = std::reference_wrapper>; + using CT = std::reference_wrapper; + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + } + { + // N4849 [func.require]/1.6: "... N == 1 and f is a pointer to data member of a class T and t_1 does not + // satisfy the previous two items" + using T = tag*; + using DT = DerivesFrom*; + using CT = tag const*; + using ST = std::unique_ptr; + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + } + } + { // pointer to member data + struct S {}; + using PMD = char S::*; + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test()); + STATIC_ASSERT(test&>()); + STATIC_ASSERT(test const&>()); + STATIC_ASSERT(test*>()); + STATIC_ASSERT(test const*>()); + STATIC_ASSERT(test>()); + STATIC_ASSERT(test>()); + STATIC_ASSERT(test>()); + STATIC_ASSERT(test>()); + STATIC_ASSERT(!test()); + } + } + +#define NAME test_default_cc +#define CALLCONV /* default convention */ +#define MCALLCONV /* default convention */ +#include "invocable_cc.hpp" + +#define NAME test_cdecl_cdecl +#define CALLCONV __cdecl +#define MCALLCONV __cdecl +#include "invocable_cc.hpp" + +#define NAME test_fast_fast +#define CALLCONV __fastcall +#define MCALLCONV __fastcall +#include "invocable_cc.hpp" + +#define NAME test_std_std +#define CALLCONV __stdcall +#define MCALLCONV __stdcall +#include "invocable_cc.hpp" + +#define NAME test_this +#define CALLCONV +#define MCALLCONV __thiscall +#include "invocable_cc.hpp" + +#if !defined(_M_ARM) && !defined(_M_ARM64) +#define NAME test_vector_vector +#define CALLCONV __vectorcall +#define MCALLCONV __vectorcall +#include "invocable_cc.hpp" +#endif // ^^^ !ARM && !ARM64 ^^^ + +} // namespace test_invocable_concepts + +namespace test_predicate { + using std::predicate; + + struct Bool { + operator bool() const; + }; + + struct tag {}; + + struct NotCallableWithInt { + int operator()(int) = delete; + Bool operator()(tag); + }; + + struct S { + using FreeFunc = Bool (*)(long); + operator FreeFunc() const; + Bool operator()(char, int&); + Bool const& operator()(char, int&) const; + Bool volatile& operator()(char, int&) volatile; + Bool const volatile& operator()(char, int&) const volatile; + }; + + struct NotDerived {}; + + void test() { + { + using Fn = Bool (tag::*)(int); + using RFn = Bool (tag::*)(int)&&; + { + // N4849 [func.require]/1.1: "... f is a pointer to member function of a class T and + // is_base_of_v> is true" + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate&, int>); + STATIC_ASSERT(predicate); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate); + } + { + // N4849 [func.require]/1.2: "... f is a pointer to a member function of a class T and + // remove_cvref_t is a specialization of reference_wrapper" + using T = std::reference_wrapper; + using DT = std::reference_wrapper>; + using CT = std::reference_wrapper; + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate); + } + { + // N4849 [func.require]/1.3: "... f is a pointer to a member function of a class T and t_1 does not + // satisfy the previous two items" + using T = tag*; + using DT = DerivesFrom*; + using CT = tag const*; + using ST = std::unique_ptr; + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate); + } + } + { + using Fn = Bool(tag::*); + STATIC_ASSERT(!predicate); + { + // N4849 [func.require]/1.4: "... N == 1 and f is a pointer to data member of a class T and + // is_base_of_v> is true" + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate&>); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + } + { + // N4849 [func.require]/1.5: "... N == 1 and f is a pointer to data member of a class T and + // remove_cvref_t is a specialization of reference_wrapper" + using T = std::reference_wrapper; + using DT = std::reference_wrapper>; + using CT = std::reference_wrapper; + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + } + { + // N4849 [func.require]/1.6: "... N == 1 and f is a pointer to data member of a class T and t_1 does not + // satisfy the previous two items" + using T = tag*; + using DT = DerivesFrom*; + using CT = tag const*; + using ST = std::unique_ptr; + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + } + } + {// N4849 [func.require]/1.7: "f(t_1, t_2, ..., t_N) in all other cases" + {// function pointer + using Fp = Bool(*)(tag&, int); + STATIC_ASSERT(predicate); // TRANSITION, clang-format damage (not yet reported) + STATIC_ASSERT(predicate&, int>); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate); + } + { // function reference + using Fp = Bool (&)(tag&, int); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate&, int>); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate); + } + { // function object + using Fn = NotCallableWithInt; + STATIC_ASSERT(predicate); + STATIC_ASSERT(!predicate); + } +} // namespace test_predicate + +{ // function object + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate); + + STATIC_ASSERT(predicate, int>); + STATIC_ASSERT(predicate, char>); + STATIC_ASSERT(predicate, float>); + STATIC_ASSERT(!predicate, char const*>); + STATIC_ASSERT(!predicate, S const&>); + + auto omega_mu = [x = 42](int i, double) { return x == i; }; + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate); +} + +{ // pointer to function + using RF0 = bool (&)(); + using RF1 = bool* (&) (int); + using RF2 = bool& (&) (int, int); + using RF3 = bool const& (&) (int, int, int); + using RF4 = bool (&)(int, ...); + using PF0 = bool (*)(); + using PF1 = bool* (*) (int); + using PF2 = bool& (*) (int, int); + using PF3 = bool const& (*) (int, int, int); + using PF4 = bool (*)(int, ...); + using RPF0 = bool (*&)(); + using RPF1 = bool* (*&) (int); + using RPF2 = bool& (*&) (int, int); + using RPF3 = bool const& (*&) (int, int, int); + using RPF4 = bool (*&)(int, ...); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); +} + +{ // pointer to member function + using PMF0 = Bool (S::*)(); + using PMF1 = Bool (S::*)(long); + using PMF2 = Bool& (S::*) (long, int); + using PMF1P = Bool const& (S::*) (int, ...); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate>); + STATIC_ASSERT(predicate const&>); + STATIC_ASSERT(predicate>>); + STATIC_ASSERT(predicate> const&>); + STATIC_ASSERT(predicate>); + STATIC_ASSERT(predicate>>); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate>); + STATIC_ASSERT(!predicate>); + STATIC_ASSERT(!predicate>); + STATIC_ASSERT(!predicate>); + + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate, int>); + STATIC_ASSERT(predicate>, int>); + STATIC_ASSERT(predicate, int>); + STATIC_ASSERT(predicate const&, int>); + STATIC_ASSERT(predicate>, int>); + STATIC_ASSERT(predicate> const&, int>); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate, int>); + STATIC_ASSERT(!predicate, int>); + STATIC_ASSERT(!predicate, int>); + STATIC_ASSERT(!predicate, int>); + + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate, int, int>); + STATIC_ASSERT(predicate>, int, int>); + STATIC_ASSERT(predicate, int, int>); + STATIC_ASSERT(predicate const&, int, int>); + STATIC_ASSERT(predicate>, int, int>); + STATIC_ASSERT(predicate> const&, int, int>); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate, int, int>); + STATIC_ASSERT(!predicate, int, int>); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate, int, int>); + STATIC_ASSERT(!predicate, int, int>); + + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + + using PMF0C = bool (S::*)() const; + using PMF1C = bool (S::*)(long) const; + using PMF2C = bool (S::*)(long, int) const; + using PMF1PC = bool const& (S::*) (int, ...) const; + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate>); + STATIC_ASSERT(predicate>>); + STATIC_ASSERT(predicate>); + STATIC_ASSERT(predicate>); + STATIC_ASSERT(predicate const&>); + STATIC_ASSERT(predicate const&>); + STATIC_ASSERT(predicate>>); + STATIC_ASSERT(predicate const>>); + STATIC_ASSERT(predicate> const&>); + STATIC_ASSERT(predicate const> const&>); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate); + + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate, int>); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate); + + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate, int, int>); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate); + + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + + using PMF0V = bool (S::*)() volatile; + using PMF1V = bool (S::*)(long) volatile; + using PMF2V = bool (S::*)(long, int) volatile; + using PMF1PV = bool const& (S::*) (int, ...) volatile; + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate>); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate); + + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate, int>); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate); + + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate, int, int>); + STATIC_ASSERT(!predicate); + STATIC_ASSERT(!predicate); + + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + + using PMF0CV = Bool (S::*)() const volatile; + using PMF1CV = Bool (S::*)(long) const volatile; + using PMF2CV = Bool (S::*)(long, int) const volatile; + using PMF1PCV = Bool const& (S::*) (int, ...) const volatile; + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate>); + + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate, int>); + + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate, int, int>); + + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); +} + +{ // pointer to member data + using PMD = bool S::*; + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate); + STATIC_ASSERT(predicate&>); + STATIC_ASSERT(predicate const&>); + STATIC_ASSERT(predicate*>); + STATIC_ASSERT(predicate const*>); + STATIC_ASSERT(predicate>); + STATIC_ASSERT(predicate>); + STATIC_ASSERT(predicate>); + STATIC_ASSERT(predicate>); + STATIC_ASSERT(!predicate); +} +} +} // namespace test_predicate + +namespace test_relation { + // Tests relation, equivalence_relation, and strict_weak_order (since they are syntactically identical) + + using std::relation, std::equivalence_relation, std::strict_weak_order; + + template + constexpr bool test() { + constexpr bool result = relation; + STATIC_ASSERT(relation == result); + STATIC_ASSERT(equivalence_relation == result); + STATIC_ASSERT(equivalence_relation == result); + STATIC_ASSERT(strict_weak_order == result); + STATIC_ASSERT(strict_weak_order == result); + return result; + } + + STATIC_ASSERT(test, int, long>()); + STATIC_ASSERT(test, int*, void*>()); + + struct Equivalent { + // clang-format off + template + constexpr decltype(auto) operator()(T&& t, U&& u) const + requires requires { static_cast(t) == static_cast(u); } { + return static_cast(t) == static_cast(u); + } + // clang-format on + }; + STATIC_ASSERT(test()); + + struct Bool { + operator bool() const; + }; + + template + struct A {}; + // clang-format off + template + requires (0 < U) + Bool operator==(A, A); // A<0> == A<0> is invalid + // clang-format on + STATIC_ASSERT(!test>()); + STATIC_ASSERT(test>()); + + template + struct B {}; + void operator==(B<1>, B<1>); // B<1> == B<1> does not model __boolean_testable + template + bool operator==(B, B); + STATIC_ASSERT(test>()); + STATIC_ASSERT(!test>()); + + // clang-format off + template + requires (2 != I) + bool operator==(A, B); // A<2> == B<2> rewrites to B<2> == A<2> + template + requires (3 != I) + bool operator==(B, A); // B<3> == A<3> rewrites to A<3> == B<3> + // clang-format on + + STATIC_ASSERT(!test, B<0>>()); + STATIC_ASSERT(!test, B<1>>()); + STATIC_ASSERT(test, B<2>>()); + STATIC_ASSERT(test, B<3>>()); + STATIC_ASSERT(test, B<4>>()); + + template + struct C {}; + enum E : bool { No, Yes }; + E operator==(C<0>&, C<0>&); // const C<0> == const C<0> is invalid + // clang-format off + template + requires (0 != I) + E operator==(C, C); + // clang-format on + + STATIC_ASSERT(!test>()); + STATIC_ASSERT(test>()); +} // namespace test_relation + +namespace test_uniform_random_bit_generator { + using std::uniform_random_bit_generator; + + STATIC_ASSERT(uniform_random_bit_generator); + STATIC_ASSERT(uniform_random_bit_generator); + STATIC_ASSERT(uniform_random_bit_generator); + STATIC_ASSERT(uniform_random_bit_generator); + STATIC_ASSERT(uniform_random_bit_generator); + STATIC_ASSERT(uniform_random_bit_generator); + STATIC_ASSERT(uniform_random_bit_generator); + STATIC_ASSERT(uniform_random_bit_generator); + STATIC_ASSERT(uniform_random_bit_generator); + STATIC_ASSERT(uniform_random_bit_generator); + STATIC_ASSERT(uniform_random_bit_generator); + + struct NoCall { + static constexpr unsigned int min() { + return 0; + } + static constexpr unsigned int max() { + return 42; + } + }; + STATIC_ASSERT(!uniform_random_bit_generator); + + struct NoLvalueCall { + static constexpr unsigned int min() { + return 0; + } + static constexpr unsigned int max() { + return 42; + } + unsigned int operator()() &&; + }; + STATIC_ASSERT(!uniform_random_bit_generator); + + struct SignedValue { + static constexpr int min() { + return 0; + } + static constexpr int max() { + return 42; + } + int operator()(); + }; + STATIC_ASSERT(!uniform_random_bit_generator); + + struct NoMin { + static constexpr unsigned int max() { + return 42; + } + unsigned int operator()(); + }; + STATIC_ASSERT(!uniform_random_bit_generator); + + struct NonConstexprMin { + static unsigned int min() { + return 0; + } + static constexpr unsigned int max() { + return 42; + } + unsigned int operator()(); + }; + STATIC_ASSERT(!uniform_random_bit_generator); + + struct BadMin { + static constexpr int min() { + return 0; + } + static constexpr unsigned int max() { + return 42; + } + unsigned int operator()(); + }; + STATIC_ASSERT(!uniform_random_bit_generator); + + struct NoMax { + static constexpr unsigned int min() { + return 0; + } + unsigned int operator()(); + }; + STATIC_ASSERT(!uniform_random_bit_generator); + + struct NonConstexprMax { + static constexpr unsigned int min() { + return 0; + } + static unsigned int max() { + return 42; + } + unsigned int operator()(); + }; + STATIC_ASSERT(!uniform_random_bit_generator); + + struct BadMax { + static constexpr unsigned int min() { + return 0; + } + static constexpr int max() { + return 42; + } + unsigned int operator()(); + }; + STATIC_ASSERT(!uniform_random_bit_generator); + + struct EmptyRange { + static constexpr unsigned int min() { + return 0; + } + static constexpr unsigned int max() { + return 0; + } + unsigned int operator()(); + }; + STATIC_ASSERT(!uniform_random_bit_generator); + + struct ReversedRange { + static constexpr unsigned int min() { + return 42; + } + static constexpr unsigned int max() { + return 0; + } + unsigned int operator()(); + }; + STATIC_ASSERT(!uniform_random_bit_generator); + + struct URBG { + static constexpr unsigned int min() { + return 0; + } + static constexpr unsigned int max() { + return 42; + } + unsigned int operator()(); + }; + STATIC_ASSERT(uniform_random_bit_generator); + STATIC_ASSERT(!uniform_random_bit_generator); + + struct ConstURBG { + static constexpr unsigned int min() { + return 0; + } + static constexpr unsigned int max() { + return 42; + } + unsigned int operator()() const; + }; + STATIC_ASSERT(uniform_random_bit_generator); + STATIC_ASSERT(uniform_random_bit_generator); +} // namespace test_uniform_random_bit_generator + +int main() { + test_ranges_swap::runtime_tests(); + test_swappable_with::example::test(); +} +// clang-format on diff --git a/libcxx/test/msvc-stl/P0898R3_identity/test.pass.cpp b/libcxx/test/msvc-stl/P0898R3_identity/test.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/msvc-stl/P0898R3_identity/test.pass.cpp @@ -0,0 +1,62 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// clang-format off + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunknown-pragmas" +#pragma clang diagnostic ignored "-Wdeprecated-volatile" + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunknown-pragmas" + +#include +#include +#include + +using namespace std; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +struct S { + S() = delete; + S(const S&) = delete; + S& operator=(const S&) = delete; +}; + +template +using test = typename T::is_transparent; + +int main() { + STATIC_ASSERT(identity{}(42) == 42); + STATIC_ASSERT(identity{}(4.2) == 4.2); + + constexpr identity i; + assert(i(42) == 42); + assert(i(4.2) == 4.2); + static_assert(i(42) == 42); + static_assert(i(4.2) == 4.2); + + STATIC_ASSERT(noexcept(identity{}(42))); + STATIC_ASSERT(noexcept(identity{}(4.2))); + + vector v = {42, 42, 42}; + assert(identity{}(v) == v); + assert(i(v) == v); + assert(&i(v) == &v); + assert(noexcept(identity{}(v))); + + STATIC_ASSERT(is_same_v()))>); + STATIC_ASSERT(is_same_v()))>); + STATIC_ASSERT(is_same_v()))>); + STATIC_ASSERT(is_same_v()))>); + STATIC_ASSERT(is_same_v()))>); + STATIC_ASSERT(is_same_v()))>); + STATIC_ASSERT(is_same_v()))>); + STATIC_ASSERT(is_same_v()))>); + + STATIC_ASSERT(is_same_v, test>); +} +// clang-format on diff --git a/libcxx/test/msvc-stl/README.md b/libcxx/test/msvc-stl/README.md new file mode 100644 --- /dev/null +++ b/libcxx/test/msvc-stl/README.md @@ -0,0 +1,25 @@ +# Alterations + +The tests in this directory have been copied from [Microsoft's STL][1] test directory. Only the +following alterations have been made to the files (including the path structure): + +## Common alterations + +* `test.cpp` files have been renamed to `test.pass.cpp`. +* LIT directives have been applied to all `test.pass.cpp` files. +* A single `// clang-format off` has been added to each file underneath LIT directives. +* Pragma directives disabling `-Wunknown-pragmas` (Clang, GCC) and `-Wdeprecated-volatile` (Clang) + have been added. + +## Specific alterations + +| Path | Change | +| ---------------------------------|----------------------------------------------------| +| `P0898R3_concepts/test.pass.cpp` | `_Boolean_testable` edited to `__boolean_testable` | + +# Changes + +All changes to the contents in this directory should first be merged into [Microsoft/STL], then +copied across verbatim. + +[1]: https://github.com/microsoft/STL