Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 22 additions & 38 deletions include/stdx/algorithm.hpp
Original file line number Diff line number Diff line change
@@ -1,33 +1,23 @@
#pragma once

#include <stdx/tuple.hpp>

#include <functional>
#include <iterator>
#if __cplusplus >= 202002L
#include <stdx/tuple.hpp>
#else
#include <tuple>
#endif
#include <type_traits>

namespace stdx {
inline namespace v1 {
namespace detail {
#if __cplusplus >= 202002L
template <typename... Ts> using result_tuple_t = stdx::tuple<Ts...>;
#define CONSTEXPR_INVOKE constexpr
#else
template <typename... Ts> using result_tuple_t = std::tuple<Ts...>;
#define CONSTEXPR_INVOKE
#endif
} // namespace detail

template <typename O, typename... Is>
using transform_result = detail::result_tuple_t<O, Is...>;

template <typename InputIt, typename OutputIt, typename Operation,
typename... InputItN>
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<OutputIt, InputIt, InputItN...> {
while (first != last) {
*d_first = std::invoke(op, *first, *first_n...);
Expand All @@ -39,8 +29,8 @@ CONSTEXPR_INVOKE auto transform(InputIt first, InputIt last, OutputIt d_first,

template <typename InputIt, typename Size, typename OutputIt,
typename Operation, typename... InputItN>
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<OutputIt, InputIt, InputItN...> {
while (n-- > 0) {
*d_first = std::invoke(op, *first, *first_n...);
Expand All @@ -54,8 +44,8 @@ template <typename Op, typename... Is>
using for_each_result = detail::result_tuple_t<Op, Is...>;

template <typename InputIt, typename Operation, typename... InputItN>
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<Operation, InputItN...> {
while (first != last) {
std::invoke(op, *first, *first_n...);
Expand All @@ -66,8 +56,8 @@ CONSTEXPR_INVOKE auto for_each(InputIt first, InputIt last, Operation op,

template <typename InputIt, typename Size, typename Operation,
typename... InputItN>
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<Operation, InputIt, InputItN...> {
while (n-- > 0) {
std::invoke(op, *first, *first_n...);
Expand All @@ -78,9 +68,9 @@ CONSTEXPR_INVOKE auto for_each_n(InputIt first, Size n, Operation op,

namespace detail {
template <typename FwdIt, typename N, typename Operation, typename... FwdItN>
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<Operation, FwdIt, FwdItN...> {
auto adv_it = first;
for (auto i = N{}; i < n; ++i) {
Expand All @@ -99,46 +89,40 @@ CONSTEXPR_INVOKE auto for_each_butlastn(std::forward_iterator_tag, FwdIt first,
}

template <typename RandIt, typename N, typename Operation, typename... RandItN>
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<decltype(sz)>(n), op, first_n...);
}
} // namespace detail

template <typename FwdIt, typename N, typename Operation, typename... FwdItN>
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<FwdIt>::iterator_category{}, first, last,
n, op, first_n...);
}

template <typename FwdIt, typename Operation, typename... FwdItN>
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 <typename FwdIt, typename IOp, typename MOp, typename FOp>
CONSTEXPR_INVOKE auto initial_medial_final(FwdIt first, FwdIt last, IOp iop,
MOp mop, FOp fop)
-> for_each_result<IOp, MOp, FOp> {
constexpr auto initial_medial_final(FwdIt first, FwdIt last, IOp iop, MOp mop,
FOp fop) -> for_each_result<IOp, MOp, FOp> {
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);
}
return {iop, get<0>(r), fop};
}
return {iop, mop, fop};
}

#undef CONSTEXPR_INVOKE
} // namespace v1
} // namespace stdx
39 changes: 11 additions & 28 deletions include/stdx/atomic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,6 @@
#include <atomic>
#include <type_traits>

// 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)
Expand Down Expand Up @@ -49,7 +42,8 @@ template <typename T> class atomic {
public:
using value_type = T;

constexpr atomic() CPP20(requires std::is_default_constructible_v<elem_t>)
constexpr atomic()
requires std::is_default_constructible_v<elem_t>
: value{} {}
constexpr explicit atomic(T t) : value{static_cast<elem_t>(t)} {}
atomic(atomic const &) = delete;
Expand Down Expand Up @@ -78,53 +72,44 @@ template <typename T> 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<elem_t>(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<elem_t>(t), mo);
}

auto operator+=(T t) -> T { return fetch_add(t) + t; }
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<elem_t>(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<elem_t>(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<elem_t>(t), mo);
}

Expand All @@ -134,5 +119,3 @@ template <typename T> class atomic {
};
} // namespace v1
} // namespace stdx

// NOLINTEND(cppcoreguidelines-macro-usage)
4 changes: 0 additions & 4 deletions include/stdx/atomic_bitset.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<N + 1> s)
: atomic_bitset{static_cast<std::string_view>(s)} {}
#endif

template <typename T>
[[nodiscard]] auto
Expand Down Expand Up @@ -238,8 +236,6 @@ class atomic_bitset {
}
};

#if __cplusplus >= 202002L
template <std::size_t N> atomic_bitset(ct_string<N>) -> atomic_bitset<N - 1>;
#endif
} // namespace v1
} // namespace stdx
11 changes: 0 additions & 11 deletions include/stdx/bitset.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -192,10 +185,8 @@ class bitset {
}
}

#if __cplusplus >= 202002L
constexpr explicit bitset(ct_string<N + 1> s)
: bitset{static_cast<std::string_view>(s)} {}
#endif

template <typename T> [[nodiscard]] constexpr auto to() const -> T {
if constexpr (N == 0) {
Expand Down Expand Up @@ -479,9 +470,7 @@ template <typename T, typename F, typename R, auto M, typename... S>
}
}

#if __cplusplus >= 202002L
template <std::size_t N> bitset(ct_string<N>) -> bitset<N - 1>;
#endif

namespace detail {
template <typename...> constexpr std::size_t index_of = 0;
Expand Down
89 changes: 0 additions & 89 deletions include/stdx/byterator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ template <typename T> class byterator {
static_cast<void const *>(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;
Expand All @@ -62,94 +61,6 @@ template <typename T> class byterator {
return static_cast<void const *>(x.ptr) <=>
static_cast<void const *>(stdx::to_address(y));
}
#else
template <typename It>
[[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 <typename It>
[[nodiscard]] friend constexpr auto operator!=(byterator const &x, It y)
-> bool {
return not(x == y);
}
template <typename It>
[[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 <typename It,
std::enable_if_t<std::is_same_v<detail::iterator_value_t<It>, T>,
int> = 0>
[[nodiscard]] friend constexpr auto operator<(byterator const &x, It y)
-> bool {
return std::less{}(static_cast<void const *>(x.ptr),
static_cast<void const *>(stdx::to_address(y)));
}
template <typename It,
std::enable_if_t<std::is_same_v<detail::iterator_value_t<It>, T>,
int> = 0>
[[nodiscard]] friend constexpr auto operator<(It x, byterator const &y)
-> bool {
return std::less{}(static_cast<void const *>(stdx::to_address(x)),
static_cast<void const *>(y.ptr));
}

[[nodiscard]] friend constexpr auto operator<=(byterator const &x,
byterator const &y) -> bool {
return not(y < x);
}
template <typename It>
[[nodiscard]] friend constexpr auto operator<=(byterator const &x, It y)
-> bool {
return not(y < x);
}
template <typename It>
[[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 <typename It>
[[nodiscard]] friend constexpr auto operator>(byterator const &x, It y)
-> bool {
return y < x;
}
template <typename It>
[[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 <typename It>
[[nodiscard]] friend constexpr auto operator>=(byterator const &x, It y)
-> bool {
return not(x < y);
}
template <typename It>
[[nodiscard]] friend constexpr auto operator>=(It x, byterator const &y)
-> bool {
return not(x < y);
}
#endif

public:
using difference_type = std::ptrdiff_t;
Expand Down
Loading