diff --git a/include/stdx/algorithm.hpp b/include/stdx/algorithm.hpp index d16d05a9..d2ccb99e 100644 --- a/include/stdx/algorithm.hpp +++ b/include/stdx/algorithm.hpp @@ -1,24 +1,14 @@ #pragma once +#include + #include #include -#if __cplusplus >= 202002L -#include -#else -#include -#endif -#include namespace stdx { inline namespace v1 { namespace detail { -#if __cplusplus >= 202002L template using result_tuple_t = stdx::tuple; -#define CONSTEXPR_INVOKE constexpr -#else -template using result_tuple_t = std::tuple; -#define CONSTEXPR_INVOKE -#endif } // namespace detail template @@ -26,8 +16,8 @@ using transform_result = detail::result_tuple_t; template -CONSTEXPR_INVOKE auto transform(InputIt first, InputIt last, OutputIt d_first, - Operation op, InputItN... first_n) +constexpr auto transform(InputIt first, InputIt last, OutputIt d_first, + Operation op, InputItN... first_n) -> transform_result { while (first != last) { *d_first = std::invoke(op, *first, *first_n...); @@ -39,8 +29,8 @@ CONSTEXPR_INVOKE auto transform(InputIt first, InputIt last, OutputIt d_first, template -CONSTEXPR_INVOKE auto transform_n(InputIt first, Size n, OutputIt d_first, - Operation op, InputItN... first_n) +constexpr auto transform_n(InputIt first, Size n, OutputIt d_first, + Operation op, InputItN... first_n) -> transform_result { while (n-- > 0) { *d_first = std::invoke(op, *first, *first_n...); @@ -54,8 +44,8 @@ template using for_each_result = detail::result_tuple_t; template -CONSTEXPR_INVOKE auto for_each(InputIt first, InputIt last, Operation op, - InputItN... first_n) +constexpr auto for_each(InputIt first, InputIt last, Operation op, + InputItN... first_n) -> for_each_result { while (first != last) { std::invoke(op, *first, *first_n...); @@ -66,8 +56,8 @@ CONSTEXPR_INVOKE auto for_each(InputIt first, InputIt last, Operation op, template -CONSTEXPR_INVOKE auto for_each_n(InputIt first, Size n, Operation op, - InputItN... first_n) +constexpr auto for_each_n(InputIt first, Size n, Operation op, + InputItN... first_n) -> for_each_result { while (n-- > 0) { std::invoke(op, *first, *first_n...); @@ -78,9 +68,9 @@ CONSTEXPR_INVOKE auto for_each_n(InputIt first, Size n, Operation op, namespace detail { template -CONSTEXPR_INVOKE auto for_each_butlastn(std::forward_iterator_tag, FwdIt first, - FwdIt last, N n, Operation op, - FwdItN... first_n) +constexpr auto for_each_butlastn(std::forward_iterator_tag, FwdIt first, + FwdIt last, N n, Operation op, + FwdItN... first_n) -> for_each_result { auto adv_it = first; for (auto i = N{}; i < n; ++i) { @@ -99,38 +89,34 @@ CONSTEXPR_INVOKE auto for_each_butlastn(std::forward_iterator_tag, FwdIt first, } template -CONSTEXPR_INVOKE auto for_each_butlastn(std::random_access_iterator_tag, - RandIt first, RandIt last, N n, - Operation op, RandItN... first_n) { +constexpr auto for_each_butlastn(std::random_access_iterator_tag, RandIt first, + RandIt last, N n, Operation op, + RandItN... first_n) { auto const sz = std::distance(first, last); return for_each_n(first, sz - static_cast(n), op, first_n...); } } // namespace detail template -CONSTEXPR_INVOKE auto for_each_butlastn(FwdIt first, FwdIt last, N n, - Operation op, FwdItN... first_n) { +constexpr auto for_each_butlastn(FwdIt first, FwdIt last, N n, Operation op, + FwdItN... first_n) { return detail::for_each_butlastn( typename std::iterator_traits::iterator_category{}, first, last, n, op, first_n...); } template -CONSTEXPR_INVOKE auto for_each_butlast(FwdIt first, FwdIt last, Operation op, - FwdItN... first_n) { +constexpr auto for_each_butlast(FwdIt first, FwdIt last, Operation op, + FwdItN... first_n) { return for_each_butlastn(first, last, 1, op, first_n...); } template -CONSTEXPR_INVOKE auto initial_medial_final(FwdIt first, FwdIt last, IOp iop, - MOp mop, FOp fop) - -> for_each_result { +constexpr auto initial_medial_final(FwdIt first, FwdIt last, IOp iop, MOp mop, + FOp fop) -> for_each_result { if (first != last) { iop(*first); auto r = for_each_butlast(++first, last, mop); -#if __cplusplus < 202002L - using std::get; -#endif if (auto it = get<1>(r); it != last) { fop(*it); } @@ -138,7 +124,5 @@ CONSTEXPR_INVOKE auto initial_medial_final(FwdIt first, FwdIt last, IOp iop, } return {iop, mop, fop}; } - -#undef CONSTEXPR_INVOKE } // namespace v1 } // namespace stdx diff --git a/include/stdx/atomic.hpp b/include/stdx/atomic.hpp index 48fa7e77..c1a6d9f2 100644 --- a/include/stdx/atomic.hpp +++ b/include/stdx/atomic.hpp @@ -5,13 +5,6 @@ #include #include -// NOLINTBEGIN(cppcoreguidelines-macro-usage) -#if __cplusplus >= 202002L -#define CPP20(...) __VA_ARGS__ -#else -#define CPP20(...) -#endif - namespace stdx { inline namespace v1 { // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions) @@ -49,7 +42,8 @@ template class atomic { public: using value_type = T; - constexpr atomic() CPP20(requires std::is_default_constructible_v) + constexpr atomic() + requires std::is_default_constructible_v : value{} {} constexpr explicit atomic(T t) : value{static_cast(t)} {} atomic(atomic const &) = delete; @@ -78,13 +72,11 @@ template class atomic { } auto fetch_add(T t, std::memory_order mo = std::memory_order_seq_cst) -> T { - CPP20(static_assert( - requires { t + t; }, "T must support operator+(x, y)")); + static_assert(requires { t + t; }, "T must support operator+(x, y)"); return ::atomic::fetch_add(value, static_cast(t), mo); } auto fetch_sub(T t, std::memory_order mo = std::memory_order_seq_cst) -> T { - CPP20(static_assert( - requires { t - t; }, "T must support operator-(x, y)")); + static_assert(requires { t - t; }, "T must support operator-(x, y)"); return ::atomic::fetch_sub(value, static_cast(t), mo); } @@ -92,39 +84,32 @@ template class atomic { auto operator-=(T t) -> T { return fetch_sub(t) - t; } auto operator++() -> T { - CPP20(static_assert( - requires(T t) { ++t; }, "T must support operator++()")); + static_assert(requires(T t) { ++t; }, "T must support operator++()"); return ::atomic::fetch_add(value, 1) + 1; } [[nodiscard]] auto operator++(int) -> T { - CPP20(static_assert( - requires(T t) { t++; }, "T must support operator++(int)")); + static_assert(requires(T t) { t++; }, "T must support operator++(int)"); return ::atomic::fetch_add(value, 1); } auto operator--() -> T { - CPP20(static_assert( - requires(T t) { --t; }, "T must support operator--()")); + static_assert(requires(T t) { --t; }, "T must support operator--()"); return ::atomic::fetch_sub(value, 1) - 1; } [[nodiscard]] auto operator--(int) -> T { - CPP20(static_assert( - requires(T t) { t--; }, "T must support operator--(int)")); + static_assert(requires(T t) { t--; }, "T must support operator--(int)"); return ::atomic::fetch_sub(value, 1); } auto fetch_and(T t, std::memory_order mo = std::memory_order_seq_cst) -> T { - CPP20(static_assert( - requires { t & t; }, "T must support operator&(x, y)")); + static_assert(requires { t & t; }, "T must support operator&(x, y)"); return ::atomic::fetch_and(value, static_cast(t), mo); } auto fetch_or(T t, std::memory_order mo = std::memory_order_seq_cst) -> T { - CPP20(static_assert( - requires { t | t; }, "T must support operator|(x, y)")); + static_assert(requires { t | t; }, "T must support operator|(x, y)"); return ::atomic::fetch_or(value, static_cast(t), mo); } auto fetch_xor(T t, std::memory_order mo = std::memory_order_seq_cst) -> T { - CPP20(static_assert( - requires { t ^ t; }, "T must support operator^(x, y)")); + static_assert(requires { t ^ t; }, "T must support operator^(x, y)"); return ::atomic::fetch_xor(value, static_cast(t), mo); } @@ -134,5 +119,3 @@ template class atomic { }; } // namespace v1 } // namespace stdx - -// NOLINTEND(cppcoreguidelines-macro-usage) diff --git a/include/stdx/atomic_bitset.hpp b/include/stdx/atomic_bitset.hpp index 8195d4c2..0958d8a5 100644 --- a/include/stdx/atomic_bitset.hpp +++ b/include/stdx/atomic_bitset.hpp @@ -80,10 +80,8 @@ class atomic_bitset { char one = '1') : storage{value_from_string(str, pos, n, one)} {} -#if __cplusplus >= 202002L constexpr explicit atomic_bitset(ct_string s) : atomic_bitset{static_cast(s)} {} -#endif template [[nodiscard]] auto @@ -238,8 +236,6 @@ class atomic_bitset { } }; -#if __cplusplus >= 202002L template atomic_bitset(ct_string) -> atomic_bitset; -#endif } // namespace v1 } // namespace stdx diff --git a/include/stdx/bitset.hpp b/include/stdx/bitset.hpp index 011c1eaf..5f9c88f8 100644 --- a/include/stdx/bitset.hpp +++ b/include/stdx/bitset.hpp @@ -70,13 +70,6 @@ class bitset { return lhs.highbits() == rhs.highbits(); } -#if __cpp_impl_three_way_comparison < 201907L - [[nodiscard]] friend constexpr auto operator!=(bitset const &lhs, - bitset const &rhs) -> bool { - return not(lhs == rhs); - } -#endif - friend constexpr auto operator|(bitset lhs, bitset const &rhs) -> bitset { lhs |= rhs; return lhs; @@ -192,10 +185,8 @@ class bitset { } } -#if __cplusplus >= 202002L constexpr explicit bitset(ct_string s) : bitset{static_cast(s)} {} -#endif template [[nodiscard]] constexpr auto to() const -> T { if constexpr (N == 0) { @@ -479,9 +470,7 @@ template } } -#if __cplusplus >= 202002L template bitset(ct_string) -> bitset; -#endif namespace detail { template constexpr std::size_t index_of = 0; diff --git a/include/stdx/byterator.hpp b/include/stdx/byterator.hpp index 4bb1f382..9d46cd85 100644 --- a/include/stdx/byterator.hpp +++ b/include/stdx/byterator.hpp @@ -50,7 +50,6 @@ template class byterator { static_cast(stdx::to_address(y)); } -#if __cpp_impl_three_way_comparison >= 201907L [[nodiscard]] friend constexpr auto operator<=>(byterator const &x, byterator const &y) { return x.ptr <=> y.ptr; @@ -62,94 +61,6 @@ template class byterator { return static_cast(x.ptr) <=> static_cast(stdx::to_address(y)); } -#else - template - [[nodiscard]] friend constexpr auto operator==(It x, byterator const &y) - -> bool { - return y == x; - } - - [[nodiscard]] friend constexpr auto operator!=(byterator const &x, - byterator const &y) -> bool { - return not(x == y); - } - template - [[nodiscard]] friend constexpr auto operator!=(byterator const &x, It y) - -> bool { - return not(x == y); - } - template - [[nodiscard]] friend constexpr auto operator!=(It x, byterator const &y) - -> bool { - return y != x; - } - - [[nodiscard]] friend constexpr auto operator<(byterator const &x, - byterator const &y) -> bool { - return std::less{}(x.ptr, y.ptr); - } - template , T>, - int> = 0> - [[nodiscard]] friend constexpr auto operator<(byterator const &x, It y) - -> bool { - return std::less{}(static_cast(x.ptr), - static_cast(stdx::to_address(y))); - } - template , T>, - int> = 0> - [[nodiscard]] friend constexpr auto operator<(It x, byterator const &y) - -> bool { - return std::less{}(static_cast(stdx::to_address(x)), - static_cast(y.ptr)); - } - - [[nodiscard]] friend constexpr auto operator<=(byterator const &x, - byterator const &y) -> bool { - return not(y < x); - } - template - [[nodiscard]] friend constexpr auto operator<=(byterator const &x, It y) - -> bool { - return not(y < x); - } - template - [[nodiscard]] friend constexpr auto operator<=(It x, byterator const &y) - -> bool { - return not(y < x); - } - - [[nodiscard]] friend constexpr auto operator>(byterator const &x, - byterator const &y) -> bool { - return y < x; - } - template - [[nodiscard]] friend constexpr auto operator>(byterator const &x, It y) - -> bool { - return y < x; - } - template - [[nodiscard]] friend constexpr auto operator>(It x, byterator const &y) - -> bool { - return y < x; - } - - [[nodiscard]] friend constexpr auto operator>=(byterator const &x, - byterator const &y) -> bool { - return not(x < y); - } - template - [[nodiscard]] friend constexpr auto operator>=(byterator const &x, It y) - -> bool { - return not(x < y); - } - template - [[nodiscard]] friend constexpr auto operator>=(It x, byterator const &y) - -> bool { - return not(x < y); - } -#endif public: using difference_type = std::ptrdiff_t; diff --git a/include/stdx/concepts.hpp b/include/stdx/concepts.hpp index bb90c97d..17414b96 100644 --- a/include/stdx/concepts.hpp +++ b/include/stdx/concepts.hpp @@ -14,109 +14,6 @@ namespace stdx { inline namespace v1 { - -#if __cplusplus < 202002L - -// Before C++20 we can't use concepts directly, but we can still allow the -// names to be used in constexpr contexts - -template constexpr auto integral = std::is_integral_v; -template -constexpr auto floating_point = std::is_floating_point_v; - -template -constexpr auto signed_integral = integral and std::is_signed_v; - -template -constexpr auto unsigned_integral = integral and std::is_unsigned_v; - -template -constexpr auto convertible_to = std::is_convertible_v; - -template -constexpr auto derived_from = - std::is_base_of_v and - std::is_convertible_v; - -template -constexpr auto same_as = std::is_same_v and std::is_same_v; - -template -constexpr auto same_any = (... or same_as); - -template -constexpr auto same_none = not same_any; - -template -constexpr auto same_as_unqualified = - is_same_unqualified_v and is_same_unqualified_v; - -// NOLINTBEGIN(bugprone-macro-parentheses, cppcoreguidelines-macro-usage) -#define DETECTOR(name, expr) \ - namespace detail::detect { \ - template constexpr auto name = false; \ - template \ - constexpr auto name> = true; \ - } -// NOLINTEND(bugprone-macro-parentheses, cppcoreguidelines-macro-usage) - -DETECTOR(eq_compare, (std::declval() == std::declval())) -DETECTOR(neq_compare, (std::declval() != std::declval())) - -template -constexpr auto equality_comparable = - detail::detect::eq_compare and detail::detect::neq_compare; - -DETECTOR(lt_compare, (std::declval() < std::declval())) -DETECTOR(lte_compare, (std::declval() <= std::declval())) -DETECTOR(gt_compare, (std::declval() > std::declval())) -DETECTOR(gte_compare, (std::declval() >= std::declval())) - -template -constexpr auto totally_ordered = - equality_comparable and detail::detect::lt_compare and - detail::detect::lte_compare and detail::detect::gt_compare and - detail::detect::gte_compare; - -namespace detail::detect { -template struct arg_list { - template - using invoke_result_t = std::invoke_result_t; -}; -template -constexpr auto invocable = false; -template -constexpr auto invocable< - F, Args, std::void_t>> = true; -} // namespace detail::detect - -template -constexpr auto invocable = - detail::detect::invocable>; - -template -constexpr auto predicate = - invocable and - std::is_convertible_v, bool>; - -template constexpr auto callable = is_callable_v; - -template typename TypeTrait> -constexpr auto has_trait = TypeTrait::value; - -#undef DETECTOR - -template constexpr auto structural = is_structural_v; - -template constexpr auto complete = is_complete_v; - -template -constexpr auto same_template_as = is_same_template_v; - -#else - -// After C++20, we can define concepts that are lacking in the library - template concept integral = std::is_integral_v; @@ -204,9 +101,6 @@ concept complete = is_complete_v; template concept same_template_as = is_same_template_v; - -#endif - } // namespace v1 } // namespace stdx diff --git a/include/stdx/ct_format.hpp b/include/stdx/ct_format.hpp index b0234830..dc99c44b 100644 --- a/include/stdx/ct_format.hpp +++ b/include/stdx/ct_format.hpp @@ -1,7 +1,5 @@ #pragma once -#if __cplusplus >= 202002L - #include #include #include @@ -449,5 +447,3 @@ constexpr auto num_fmt_specifiers = stdx::ct_format(STDX_MAP(CX_WRAP __VA_OPT__(, ) __VA_ARGS__)) // NOLINTEND(cppcoreguidelines-macro-usage) - -#endif diff --git a/include/stdx/ct_string.hpp b/include/stdx/ct_string.hpp index a8570898..00100286 100644 --- a/include/stdx/ct_string.hpp +++ b/include/stdx/ct_string.hpp @@ -1,7 +1,5 @@ #pragma once -#if __cplusplus >= 202002L - #include #include #include @@ -189,5 +187,3 @@ template CONSTEVAL_UDL auto operator""_ctst() { } // namespace literals } // namespace v1 } // namespace stdx - -#endif diff --git a/include/stdx/cx_vector.hpp b/include/stdx/cx_vector.hpp index 550c9477..ae0024d3 100644 --- a/include/stdx/cx_vector.hpp +++ b/include/stdx/cx_vector.hpp @@ -162,14 +162,6 @@ template class cx_vector { } return true; } - -#if __cpp_impl_three_way_comparison < 201907L - [[nodiscard]] friend constexpr auto operator!=(cx_vector const &lhs, - cx_vector const &rhs) - -> bool { - return not(lhs == rhs); - } -#endif }; template diff --git a/include/stdx/detail/list_common.hpp b/include/stdx/detail/list_common.hpp index d197ce70..2b4f3a7d 100644 --- a/include/stdx/detail/list_common.hpp +++ b/include/stdx/detail/list_common.hpp @@ -10,7 +10,6 @@ namespace stdx { inline namespace v1 { -#if __cpp_concepts >= 201907L namespace detail { template concept base_single_linkable = requires(T node) { @@ -37,13 +36,6 @@ concept double_linkable = not complete or requires(T *node) { std::remove_cvref_tprev)>>; }; -#define STDX_SINGLE_LINKABLE single_linkable -#define STDX_DOUBLE_LINKABLE double_linkable -#else -#define STDX_SINGLE_LINKABLE typename -#define STDX_DOUBLE_LINKABLE typename -#endif - namespace detail::detect { template constexpr auto has_prev_pointer = false; template diff --git a/include/stdx/env.hpp b/include/stdx/env.hpp index 112a87ea..2924733d 100644 --- a/include/stdx/env.hpp +++ b/include/stdx/env.hpp @@ -1,7 +1,5 @@ #pragma once -#if __cplusplus >= 202002L - #include #include #include @@ -109,5 +107,3 @@ constexpr auto query(Q q, [[maybe_unused]] Default &&d) -> decltype(auto) { } // namespace v1 } // namespace stdx - -#endif diff --git a/include/stdx/for_each_n_args.hpp b/include/stdx/for_each_n_args.hpp index 97580f92..5039028d 100644 --- a/include/stdx/for_each_n_args.hpp +++ b/include/stdx/for_each_n_args.hpp @@ -1,16 +1,7 @@ #pragma once #include - -#if __cplusplus >= 202002L #include -#define TUPLE_T stdx::tuple -#define TUPLE_GET stdx::get -#else -#include -#define TUPLE_T std::tuple -#define TUPLE_GET std::get -#endif #include #include @@ -32,7 +23,7 @@ struct for_each_n_args, private: template static auto exec(F &&f, T &&t) -> void { - std::invoke(f, TUPLE_GET(std::forward(t))...); + std::invoke(f, get(std::forward(t))...); } }; } // namespace detail @@ -50,7 +41,7 @@ void for_each_n_args(F &&f, Args &&...args) { "for_each_n_args: number of args must be a multiple of the " "given N (or function arity)"); - using tuple_t = TUPLE_T; + using tuple_t = tuple; detail::for_each_n_args< std::make_index_sequence, std::make_index_sequence>::apply(std::forward(f), @@ -59,6 +50,3 @@ void for_each_n_args(F &&f, Args &&...args) { } } // namespace v1 } // namespace stdx - -#undef TUPLE_T -#undef TUPLE_GET diff --git a/include/stdx/intrusive_forward_list.hpp b/include/stdx/intrusive_forward_list.hpp index c231fc9e..ee323649 100644 --- a/include/stdx/intrusive_forward_list.hpp +++ b/include/stdx/intrusive_forward_list.hpp @@ -3,13 +3,10 @@ #include #include -#if __cplusplus < 202002L -#include -#endif namespace stdx { inline namespace v1 { -template typename P = node_policy::checked> class intrusive_forward_list { friend P; @@ -19,9 +16,6 @@ class intrusive_forward_list { using value_type = N; using pointer = value_type *; using reference = value_type &; -#if __cplusplus < 202002L - using iterator_category = std::forward_iterator_tag; -#endif constexpr iterator_t() = default; constexpr explicit iterator_t(pointer n) : node{n} {} @@ -44,19 +38,8 @@ class intrusive_forward_list { private: pointer node{}; -#if __cpp_impl_three_way_comparison < 201907L - friend constexpr auto operator==(iterator_t lhs, iterator_t rhs) - -> bool { - return lhs.node == rhs.node; - } - friend constexpr auto operator!=(iterator_t lhs, iterator_t rhs) - -> bool { - return not(lhs == rhs); - } -#else friend constexpr auto operator==(iterator_t, iterator_t) -> bool = default; -#endif }; public: diff --git a/include/stdx/intrusive_list.hpp b/include/stdx/intrusive_list.hpp index 3cee6c14..1a42baef 100644 --- a/include/stdx/intrusive_list.hpp +++ b/include/stdx/intrusive_list.hpp @@ -3,14 +3,10 @@ #include #include -#if __cplusplus < 202002L -#include -#endif -#include namespace stdx { inline namespace v1 { -template typename P = node_policy::checked> class intrusive_list { friend P; @@ -20,9 +16,6 @@ class intrusive_list { using value_type = N; using pointer = value_type *; using reference = value_type &; -#if __cplusplus < 202002L - using iterator_category = std::forward_iterator_tag; -#endif constexpr iterator_t() = default; constexpr explicit iterator_t(pointer n) : node{n} {} @@ -45,19 +38,8 @@ class intrusive_list { private: pointer node{}; -#if __cpp_impl_three_way_comparison < 201907L - friend constexpr auto operator==(iterator_t lhs, iterator_t rhs) - -> bool { - return lhs.node == rhs.node; - } - friend constexpr auto operator!=(iterator_t lhs, iterator_t rhs) - -> bool { - return not(lhs == rhs); - } -#else friend constexpr auto operator==(iterator_t, iterator_t) -> bool = default; -#endif }; public: diff --git a/include/stdx/iterator.hpp b/include/stdx/iterator.hpp index 46bd7cce..7abe1392 100644 --- a/include/stdx/iterator.hpp +++ b/include/stdx/iterator.hpp @@ -42,11 +42,7 @@ struct counting_iterator { using const_reference = T const &; using pointer = T *; using const_pointer = T const *; -#if __cplusplus >= 202002L using iterator_category = std::contiguous_iterator_tag; -#else - using iterator_category = std::random_access_iterator_tag; -#endif auto operator*() -> reference { return i; } auto operator*() const -> const_reference { return i; } @@ -113,39 +109,10 @@ struct counting_iterator { return x.i == y.i; } -#if __cpp_impl_three_way_comparison >= 201907L [[nodiscard]] friend constexpr auto operator<=>(counting_iterator const &x, counting_iterator const &y) { return x.i <=> y.i; } -#else - [[nodiscard]] friend constexpr auto operator!=(counting_iterator const &x, - counting_iterator const &y) - -> bool { - return not(x == y); - } - - [[nodiscard]] friend constexpr auto operator<(counting_iterator const &x, - counting_iterator const &y) - -> bool { - return x.i < y.i; - } - [[nodiscard]] friend constexpr auto operator<=(counting_iterator const &x, - counting_iterator const &y) - -> bool { - return not(y < x); - } - [[nodiscard]] friend constexpr auto operator>(counting_iterator const &x, - counting_iterator const &y) - -> bool { - return y < x; - } - [[nodiscard]] friend constexpr auto operator>=(counting_iterator const &x, - counting_iterator const &y) - -> bool { - return not(x < y); - } -#endif T i{}; }; diff --git a/include/stdx/numeric.hpp b/include/stdx/numeric.hpp index 1fe3db22..27060302 100644 --- a/include/stdx/numeric.hpp +++ b/include/stdx/numeric.hpp @@ -8,17 +8,11 @@ namespace stdx { inline namespace v1 { -#if __cplusplus >= 202002L -#define CONSTEXPR_INVOKE constexpr -#else -#define CONSTEXPR_INVOKE -#endif template -CONSTEXPR_INVOKE auto transform_reduce(InputIt first, InputIt last, T init, - ROp rop, TOp top, InputItN... first_n) - -> T { +constexpr auto transform_reduce(InputIt first, InputIt last, T init, ROp rop, + TOp top, InputItN... first_n) -> T { while (first != last) { init = std::invoke(rop, std::move(init), std::invoke(top, *first, *first_n...)); @@ -29,8 +23,8 @@ CONSTEXPR_INVOKE auto transform_reduce(InputIt first, InputIt last, T init, template -CONSTEXPR_INVOKE auto transform_reduce_n(InputIt first, Size n, T init, ROp rop, - TOp top, InputItN... first_n) -> T { +constexpr auto transform_reduce_n(InputIt first, Size n, T init, ROp rop, + TOp top, InputItN... first_n) -> T { while (n-- != 0) { init = std::invoke(rop, std::move(init), std::invoke(top, *first, *first_n...)); @@ -38,7 +32,6 @@ CONSTEXPR_INVOKE auto transform_reduce_n(InputIt first, Size n, T init, ROp rop, } return init; } -#undef CONSTEXPR_INVOKE template constexpr auto saturate_cast(From from) -> To { diff --git a/include/stdx/optional.hpp b/include/stdx/optional.hpp index 0d7537eb..7542ea6e 100644 --- a/include/stdx/optional.hpp +++ b/include/stdx/optional.hpp @@ -269,14 +269,6 @@ template > class optional { return lhs.val == rhs.val; } -#if __cpp_impl_three_way_comparison < 201907L - [[nodiscard]] friend constexpr auto operator!=(optional const &lhs, - optional const &rhs) - -> bool { - return not(lhs == rhs); - } -#endif - [[nodiscard]] friend constexpr auto operator<(optional const &lhs, optional const &rhs) -> bool { return lhs.has_value() and rhs.has_value() diff --git a/include/stdx/panic.hpp b/include/stdx/panic.hpp index 56467f2c..e7db3937 100644 --- a/include/stdx/panic.hpp +++ b/include/stdx/panic.hpp @@ -10,10 +10,8 @@ struct default_panic_handler { template static auto panic(Args &&...) noexcept -> void {} -#if __cplusplus >= 202002L template static auto panic(Args &&...) noexcept -> void {} -#endif }; template inline auto panic_handler = default_panic_handler{}; @@ -22,25 +20,19 @@ template auto panic(Args &&...args) -> void { panic_handler.panic(std::forward(args)...); } -#if __cplusplus >= 202002L template auto panic(Args &&...args) -> void { panic_handler.template panic(std::forward(args)...); } -#endif } // namespace v1 } // namespace stdx // NOLINTBEGIN(cppcoreguidelines-macro-usage) -#if __cplusplus >= 202002L #define STDX_PANIC(MSG, ...) \ []() -> void { \ using stdx::ct_string_literals::operator""_cts; \ stdx::panic(__VA_ARGS__); \ }() -#else -#define STDX_PANIC(...) stdx::panic(__VA_ARGS__) -#endif // NOLINTEND(cppcoreguidelines-macro-usage) diff --git a/include/stdx/ranges.hpp b/include/stdx/ranges.hpp index 503cbf8e..346eb16e 100644 --- a/include/stdx/ranges.hpp +++ b/include/stdx/ranges.hpp @@ -5,35 +5,11 @@ namespace stdx { inline namespace v1 { -#if __cplusplus < 202002L - -// NOLINTBEGIN(bugprone-macro-parentheses, cppcoreguidelines-macro-usage) -#define DETECTOR(name, expr) \ - namespace detail::detect { \ - template constexpr auto name = false; \ - template \ - constexpr auto name> = true; \ - } -// NOLINTEND(bugprone-macro-parentheses, cppcoreguidelines-macro-usage) - -DETECTOR(range_begin, (std::begin(std::declval()))) -DETECTOR(range_end, (std::end(std::declval()))) - -template -constexpr auto range = - detail::detect::range_begin and detail::detect::range_end; - -#undef DETECTOR - -#else - template concept range = requires(T &t) { std::begin(t); std::end(t); }; -#endif - } // namespace v1 } // namespace stdx diff --git a/include/stdx/static_assert.hpp b/include/stdx/static_assert.hpp index 7f3be39e..6994bb0f 100644 --- a/include/stdx/static_assert.hpp +++ b/include/stdx/static_assert.hpp @@ -1,7 +1,5 @@ #pragma once -#if __cplusplus >= 202002L - #include #include #include @@ -51,5 +49,3 @@ template constexpr auto ct_check = ct_check_t{}; return B; \ }.template operator()() #endif - -#endif diff --git a/include/stdx/tuple.hpp b/include/stdx/tuple.hpp index c5d2edce..b3fccfac 100644 --- a/include/stdx/tuple.hpp +++ b/include/stdx/tuple.hpp @@ -1,7 +1,5 @@ #pragma once -#if __cplusplus >= 202002L - #include #include @@ -529,5 +527,3 @@ template one_of(Ts...) -> one_of; } // namespace v1 } // namespace stdx - -#endif diff --git a/include/stdx/tuple_algorithms.hpp b/include/stdx/tuple_algorithms.hpp index f886b186..f719ff3d 100644 --- a/include/stdx/tuple_algorithms.hpp +++ b/include/stdx/tuple_algorithms.hpp @@ -1,7 +1,5 @@ #pragma once -#if __cplusplus >= 202002L - #include #include #include @@ -446,5 +444,3 @@ template [[nodiscard]] constexpr auto gather(Tuple &&t) { } } // namespace v1 } // namespace stdx - -#endif diff --git a/include/stdx/tuple_destructure.hpp b/include/stdx/tuple_destructure.hpp index 8277b642..97d1edfc 100644 --- a/include/stdx/tuple_destructure.hpp +++ b/include/stdx/tuple_destructure.hpp @@ -1,7 +1,5 @@ #pragma once -#if __cplusplus >= 202002L - #include #include @@ -29,5 +27,3 @@ struct std::tuple_element> IL, Ts...>>()[stdx::index])>> {}; // NOLINTEND(bugprone-std-namespace-modification) - -#endif diff --git a/include/stdx/type_traits.hpp b/include/stdx/type_traits.hpp index 26a9094f..48467ad1 100644 --- a/include/stdx/type_traits.hpp +++ b/include/stdx/type_traits.hpp @@ -227,7 +227,6 @@ template constexpr auto is_cx_value_v = false; template constexpr auto is_cx_value_v> = true; -#if __cplusplus >= 202002L namespace detail { template struct shrinkwrap { using is_shrinkwrapped = void; @@ -291,26 +290,6 @@ template constexpr auto expand(T &&t) -> decltype(auto) { return detail::maybe_expand(std::forward(t)); } -#else -template CONSTEVAL auto shrink() -> T { - static_assert( - always_false_v, - "shrink() should not be called outside an unevaluated context"); -} -template constexpr auto shrink(T &&t) -> decltype(auto) { - return T(std::forward(t)); -} - -template CONSTEVAL auto expand() -> T { - static_assert( - always_false_v, - "expand() should not be called outside an unevaluated context"); -} -template constexpr auto expand(T &&t) -> decltype(auto) { - return T(std::forward(t)); -} -#endif - template using shrink_t = decltype(shrink()); template using expand_t = decltype(expand()); @@ -330,7 +309,6 @@ using nth_t = #endif STDX_PRAGMA(diagnostic pop) -#if __cplusplus >= 202002L namespace detail { template struct value_wrapper { constexpr static auto value = V; @@ -350,7 +328,6 @@ constexpr auto nth_v = boost::mp11::mp_at_c...>, N>::value; #endif STDX_PRAGMA(diagnostic pop) -#endif template constexpr auto is_complete_v = false; template diff --git a/include/stdx/utility.hpp b/include/stdx/utility.hpp index b21c7412..81fa68e9 100644 --- a/include/stdx/utility.hpp +++ b/include/stdx/utility.hpp @@ -256,7 +256,6 @@ constexpr auto is_aligned_with = [](auto v) -> bool { } }; -#if __cplusplus >= 202002L namespace detail { template struct ct_helper { // NOLINTNEXTLINE(google-explicit-constructor) @@ -283,8 +282,6 @@ constexpr auto is_ct_v> = true; template constexpr auto is_ct_v> = true; template constexpr auto is_ct_v = is_ct_v; -#endif - template struct make_integer_sequence : std::make_integer_sequence {}; template @@ -344,8 +341,6 @@ struct std::tuple_element> }() #endif -#if __cplusplus >= 202002L - #ifndef CT_WRAP #define CT_WRAP(...) \ [&](auto f) constexpr { \ @@ -405,7 +400,6 @@ auto cx_detect(auto f) { }) #endif -#endif // NOLINTEND(cppcoreguidelines-macro-usage) // NOLINTEND(modernize-use-constraints) diff --git a/test/atomic.cpp b/test/atomic.cpp index 131f0acc..ba776296 100644 --- a/test/atomic.cpp +++ b/test/atomic.cpp @@ -27,11 +27,9 @@ struct non_dc { }; } // namespace -#if __cplusplus >= 202002L TEST_CASE("atomic is not default constructible when data is not", "[atomic]") { STATIC_REQUIRE(not std::is_default_constructible_v>); } -#endif TEST_CASE("atomic is not copyable or movable", "[atomic]") { STATIC_REQUIRE(not std::is_copy_constructible_v>); diff --git a/test/atomic_bitset.cpp b/test/atomic_bitset.cpp index 2500c525..75b96fee 100644 --- a/test/atomic_bitset.cpp +++ b/test/atomic_bitset.cpp @@ -373,7 +373,6 @@ TEST_CASE("atomic bitset is thread-safe", "[atomic_bitset]") { t2.join(); } -#if __cplusplus >= 202002L TEST_CASE("construct with a ct_string", "[atomic_bitset]") { using namespace stdx::literals; CHECK(stdx::atomic_bitset{"1010"_cts} == @@ -381,4 +380,3 @@ TEST_CASE("construct with a ct_string", "[atomic_bitset]") { CHECK(stdx::atomic_bitset{"101010101"_cts} == stdx::bitset<9ul, std::uint16_t>{0b101010101ul}); } -#endif diff --git a/test/atomic_override.cpp b/test/atomic_override.cpp index 567c368d..4a02b815 100644 --- a/test/atomic_override.cpp +++ b/test/atomic_override.cpp @@ -31,7 +31,6 @@ TEST_CASE("atomic config works with partial specialization", STATIC_REQUIRE(std::is_same_v); } -#if __cplusplus >= 202002L namespace { enum E : std::uint8_t {}; } @@ -41,4 +40,3 @@ TEST_CASE("atomic config works with enum", "[atomic_override]") { STATIC_REQUIRE(sizeof(decltype(bs)) == sizeof(std::uint32_t)); STATIC_REQUIRE(alignof(decltype(bs)) == alignof(std::uint32_t)); } -#endif diff --git a/test/bitset.cpp b/test/bitset.cpp index 065caefc..79d076c7 100644 --- a/test/bitset.cpp +++ b/test/bitset.cpp @@ -490,7 +490,6 @@ TEST_CASE("use bitset with enum struct (lowest_unset)", "[bitset]") { CHECK(bs.lowest_unset() == Bits::ONE); } -#if __cplusplus >= 202002L TEST_CASE("construct with a ct_string", "[bitset]") { using namespace stdx::literals; STATIC_REQUIRE(stdx::bitset{"1010"_cts} == @@ -498,7 +497,6 @@ TEST_CASE("construct with a ct_string", "[bitset]") { STATIC_REQUIRE(stdx::bitset{"101010101"_cts} == stdx::bitset<9ul, std::uint16_t>{0b101010101ul}); } -#endif TEST_CASE("zero size bitset", "[bitset]") { constexpr auto bs1 = stdx::bitset<0>{}; diff --git a/test/cx_queue.cpp b/test/cx_queue.cpp index a789651e..905bfc34 100644 --- a/test/cx_queue.cpp +++ b/test/cx_queue.cpp @@ -12,12 +12,10 @@ struct injected_handler { throw panic_exception{}; } -#if __cplusplus >= 202002L template static auto panic(Args &&...) -> void { throw panic_exception{}; } -#endif }; } // namespace template <> inline auto stdx::panic_handler<> = injected_handler{}; diff --git a/test/default_panic.cpp b/test/default_panic.cpp index c21e87ea..5f527527 100644 --- a/test/default_panic.cpp +++ b/test/default_panic.cpp @@ -7,12 +7,10 @@ TEST_CASE("default panic called with runtime arguments", "[default panic]") { stdx::panic("uh-oh"); } -#if __cplusplus >= 202002L TEST_CASE("default panic called with compile-time strings", "[default panic]") { using namespace stdx::ct_string_literals; stdx::panic<"uh-oh"_cts>(); } -#endif TEST_CASE("default panic called through macro", "[default panic]") { STDX_PANIC("uh-oh"); diff --git a/test/detail/atomic_cfg.hpp b/test/detail/atomic_cfg.hpp index e58f1fd3..6a45bbf3 100644 --- a/test/detail/atomic_cfg.hpp +++ b/test/detail/atomic_cfg.hpp @@ -15,9 +15,7 @@ template struct atomic::atomic_type { using type = std::uintptr_t; }; -#if __cplusplus >= 202002L template requires(std::is_enum_v) struct atomic::atomic_type : atomic::atomic_type> { }; -#endif diff --git a/test/intrusive_forward_list.cpp b/test/intrusive_forward_list.cpp index 2951a023..4e8c71de 100644 --- a/test/intrusive_forward_list.cpp +++ b/test/intrusive_forward_list.cpp @@ -7,9 +7,7 @@ struct int_node { int value{}; int_node *next{}; }; -#if __cpp_concepts >= 201907L static_assert(stdx::single_linkable); -#endif struct single_link_node { single_link_node *next{}; @@ -20,13 +18,11 @@ struct bad_single_link_node { }; } // namespace -#if __cpp_concepts >= 201907L TEST_CASE("single_linkable", "[intrusive_forward_list]") { STATIC_REQUIRE(not stdx::single_linkable); STATIC_REQUIRE(not stdx::single_linkable); STATIC_REQUIRE(stdx::single_linkable); } -#endif TEST_CASE("push_back, pop_front", "[intrusive_forward_list]") { stdx::intrusive_forward_list list{}; @@ -240,32 +236,19 @@ TEST_CASE("checked operation clears pointers on clear", } namespace { -#if __cplusplus >= 202002L int compile_time_calls{}; -#else -int runtime_calls{}; -#endif struct injected_handler { -#if __cplusplus >= 202002L template static auto panic(Ts &&...) noexcept -> void { STATIC_REQUIRE(std::string_view{Why} == "bad list node!"); ++compile_time_calls; } -#else - template - static auto panic(Why why, Ts &&...) noexcept -> void { - CHECK(std::string_view{why} == "bad list node!"); - ++runtime_calls; - } -#endif }; } // namespace template <> inline auto stdx::panic_handler<> = injected_handler{}; -#if __cplusplus >= 202002L TEST_CASE("checked panic when pushing populated node", "[intrusive_forward_list]") { stdx::intrusive_forward_list list{}; @@ -282,24 +265,6 @@ TEST_CASE("checked panic when pushing populated node", list.push_front(&n); CHECK(compile_time_calls == 1); } -#else -TEST_CASE("checked panic when pushing populated node", - "[intrusive_forward_list]") { - stdx::intrusive_forward_list list{}; - int_node n{5}; - - n.next = &n; - runtime_calls = 0; - list.push_back(&n); - CHECK(runtime_calls == 1); - list.pop_front(); - - n.next = &n; - runtime_calls = 0; - list.push_front(&n); - CHECK(runtime_calls == 1); -} -#endif TEST_CASE("unchecked operation doesn't clear pointers", "[intrusive_forward_list]") { diff --git a/test/intrusive_list.cpp b/test/intrusive_list.cpp index c79042b5..eea23482 100644 --- a/test/intrusive_list.cpp +++ b/test/intrusive_list.cpp @@ -12,9 +12,7 @@ struct int_node { int_node *prev{}; int_node *next{}; }; -#if __cpp_concepts >= 201907L static_assert(stdx::double_linkable); -#endif struct double_link_node { double_link_node *prev{}; @@ -27,13 +25,11 @@ struct bad_double_link_node { }; } // namespace -#if __cpp_concepts >= 201907L TEST_CASE("double_linkable", "[intrusive_list]") { STATIC_REQUIRE(not stdx::double_linkable); STATIC_REQUIRE(not stdx::double_linkable); STATIC_REQUIRE(stdx::double_linkable); } -#endif TEST_CASE("push_back, pop_front", "[intrusive_list]") { stdx::intrusive_list list{}; @@ -352,32 +348,19 @@ TEST_CASE("checked operation clears pointers on clear", "[intrusive_list]") { } namespace { -#if __cplusplus >= 202002L int compile_time_calls{}; -#else -int runtime_calls{}; -#endif struct injected_handler { -#if __cplusplus >= 202002L template static auto panic(Ts &&...) noexcept -> void { STATIC_REQUIRE(std::string_view{Why} == "bad list node!"); ++compile_time_calls; } -#else - template - static auto panic(Why why, Ts &&...) noexcept -> void { - CHECK(std::string_view{why} == "bad list node!"); - ++runtime_calls; - } -#endif }; } // namespace template <> inline auto stdx::panic_handler<> = injected_handler{}; -#if __cplusplus >= 202002L TEST_CASE("checked panic when pushing populated node", "[intrusive_list]") { stdx::intrusive_list list{}; int_node n{5}; @@ -393,23 +376,6 @@ TEST_CASE("checked panic when pushing populated node", "[intrusive_list]") { list.push_front(&n); CHECK(compile_time_calls == 1); } -#else -TEST_CASE("checked panic when pushing populated node", "[intrusive_list]") { - stdx::intrusive_list list{}; - int_node n{5}; - - n.prev = &n; - runtime_calls = 0; - list.push_back(&n); - CHECK(runtime_calls == 1); - list.pop_back(); - - n.prev = &n; - runtime_calls = 0; - list.push_front(&n); - CHECK(runtime_calls == 1); -} -#endif TEST_CASE("unchecked operation doesn't clear pointers", "[intrusive_list]") { stdx::intrusive_list list{}; diff --git a/test/iterator.cpp b/test/iterator.cpp index 7e375172..b9bcaae2 100644 --- a/test/iterator.cpp +++ b/test/iterator.cpp @@ -80,14 +80,8 @@ TEST_CASE("default counting_iterator traits", "[iterator]") { STATIC_REQUIRE(std::is_same_v); STATIC_REQUIRE(std::is_same_v); STATIC_REQUIRE(std::is_same_v); - -#if __cplusplus >= 202002L STATIC_REQUIRE(std::is_same_v); -#else - STATIC_REQUIRE(std::is_same_v); -#endif } TEST_CASE("default counting_iterator value is 0, increment is 1", @@ -152,14 +146,12 @@ TEST_CASE("counting_iterator comparison", "[iterator]") { CHECK(i >= j); } -#if __cpp_impl_three_way_comparison >= 201907L TEST_CASE("counting_iterator spaceship comparison", "[iterator]") { auto i = stdx::counting_iterator{}; auto j = i++; CHECK(i <=> i == std::strong_ordering::equal); CHECK(j <=> i == std::strong_ordering::less); } -#endif TEST_CASE("counting_iterator can be given a starting value", "[iterator]") { auto i = stdx::counting_iterator{17}; diff --git a/test/panic.cpp b/test/panic.cpp index 4e67b706..3e1a8f1b 100644 --- a/test/panic.cpp +++ b/test/panic.cpp @@ -8,9 +8,7 @@ namespace { int runtime_calls{}; -#if __cplusplus >= 202002L int compile_time_calls{}; -#endif struct injected_handler { template @@ -19,13 +17,11 @@ struct injected_handler { ++runtime_calls; } -#if __cplusplus >= 202002L template static auto panic(Ts &&...) noexcept -> void { STATIC_REQUIRE(std::string_view{Why} == "uh-oh"); ++compile_time_calls; } -#endif }; } // namespace @@ -37,7 +33,6 @@ TEST_CASE("panic called with runtime arguments", "[panic]") { CHECK(runtime_calls == 1); } -#if __cplusplus >= 202002L TEST_CASE("panic called with compile-time strings", "[panic]") { compile_time_calls = 0; using namespace stdx::ct_string_literals; @@ -50,10 +45,3 @@ TEST_CASE("compile-time panic called through macro", "[panic]") { STDX_PANIC("uh-oh"); CHECK(compile_time_calls == 1); } -#else -TEST_CASE("runtime panic called through macro", "[panic]") { - runtime_calls = 0; - STDX_PANIC("uh-oh"); - CHECK(runtime_calls == 1); -} -#endif diff --git a/test/priority.cpp b/test/priority.cpp index 40222a9f..1e6dde34 100644 --- a/test/priority.cpp +++ b/test/priority.cpp @@ -3,10 +3,7 @@ #include -#include - namespace { -#if __cpp_concepts >= 201907L auto select_priority(auto, stdx::priority_t<0>) -> int { return 0; } auto select_priority(stdx::integral auto, stdx::priority_t<1>) -> int { return 1; @@ -14,19 +11,6 @@ auto select_priority(stdx::integral auto, stdx::priority_t<1>) -> int { auto select_priority(stdx::floating_point auto, stdx::priority_t<2>) -> int { return 2; } -#else -template auto select_priority(T, stdx::priority_t<0>) -> int { - return 0; -} -template >> -auto select_priority(T, stdx::priority_t<1>) -> int { - return 1; -} -template >> -auto select_priority(T, stdx::priority_t<2>) -> int { - return 2; -} -#endif } // namespace TEST_CASE("priority", "[priority]") { diff --git a/test/type_bitset.cpp b/test/type_bitset.cpp index adc774cc..897c1a17 100644 --- a/test/type_bitset.cpp +++ b/test/type_bitset.cpp @@ -161,7 +161,6 @@ TEST_CASE("difference", "[type_bitset]") { STATIC_CHECK((bs1 - bs2) == stdx::type_bitset{0b100ul}); } -#if __cplusplus >= 202002L TEST_CASE("for_each", "[type_bitset]") { constexpr auto bs = stdx::type_bitset{stdx::all_bits}; auto result = std::string{}; @@ -170,4 +169,3 @@ TEST_CASE("for_each", "[type_bitset]") { }); CHECK(result == "int0float1bool2"); } -#endif diff --git a/test/type_traits.cpp b/test/type_traits.cpp index a38db4e6..80583ff4 100644 --- a/test/type_traits.cpp +++ b/test/type_traits.cpp @@ -254,10 +254,8 @@ using C = long_type_name; TEST_CASE("type shrinkage (by type)", "[type_traits]") { using X = stdx::shrink_t; -#if __cplusplus >= 202002L STATIC_CHECK(stdx::type_as_string().size() < stdx::type_as_string().size()); -#endif STATIC_CHECK(std::is_same_v, C>); } @@ -265,10 +263,8 @@ TEST_CASE("type shrinkage (by value)", "[type_traits]") { auto c = C{}; auto x = stdx::shrink(c); auto y = stdx::expand(x); -#if __cplusplus >= 202002L STATIC_CHECK(stdx::type_as_string().size() < stdx::type_as_string().size()); -#endif STATIC_CHECK(std::is_same_v); } @@ -277,11 +273,9 @@ TEST_CASE("nth type in pack", "[type_traits]") { std::is_same_v, float>); } -#if __cplusplus >= 202002L TEST_CASE("nth value in pack", "[type_traits]") { STATIC_REQUIRE(stdx::nth_v<2, 0, true, 'b', 3> == 'b'); } -#endif TEST_CASE("is_complete_v", "[type_traits]") { struct incomplete; diff --git a/test/utility.cpp b/test/utility.cpp index 1c02365d..f59a9b8a 100644 --- a/test/utility.cpp +++ b/test/utility.cpp @@ -248,8 +248,6 @@ TEST_CASE("is_aligned_with (pointer)", "[utility]") { CHECK(stdx::is_aligned_with(p)); } -#if __cplusplus >= 202002L - TEST_CASE("ct (integral)", "[utility]") { constexpr auto vs = stdx::ct<42>(); STATIC_REQUIRE( @@ -431,8 +429,6 @@ TEST_CASE("CX_WRAP non-constexpr expression", "[utility]") { } #endif -#endif - STDX_PRAGMA(diagnostic push) #ifdef __clang__ STDX_PRAGMA(diagnostic ignored "-Wunknown-warning-option")