diff --git a/nth/debug/contracts/internal/contracts.h b/nth/debug/contracts/internal/contracts.h index 1565e17..7ed0d6c 100644 --- a/nth/debug/contracts/internal/contracts.h +++ b/nth/debug/contracts/internal/contracts.h @@ -26,17 +26,19 @@ inline constexpr char const EnsureLogLine[] = #define NTH_DEBUG_INTERNAL_CONTRACT_CHECK(log_line, verbosity, responder_type, \ action_prefix, ...) \ - if (::nth::debug::internal_contracts::responder_type NthInternalResponder; \ - NTH_DEBUG_INTERNAL_VERBOSITY_DISABLED(verbosity) or \ - [&](::nth::source_location NthInternalourceLocation) \ - -> decltype(auto) { \ - static ::nth::internal_debug::LogLineWithArity<3> const \ - NthInternalLogLine(log_line, NthInternalourceLocation); \ - NthInternalResponder.set_log_line(NthInternalLogLine); \ - return (NthInternalResponder); \ - }(::nth::source_location::current()) \ - .set((#__VA_ARGS__), \ - NTH_DEBUG_INTERNAL_TRACE_INJECTED_EXPR(__VA_ARGS__))) { \ + if (NTH_DEBUG_INTERNAL_VERBOSITY_DISABLED(verbosity)) { \ + } else if (::nth::debug::internal_contracts::responder_type \ + NthInternalResponder; \ + [&](::nth::source_location NthInternalourceLocation) \ + -> decltype(auto) { \ + static ::nth::internal_debug::LogLineWithArity<3> const \ + NthInternalLogLine(log_line, NthInternalourceLocation); \ + NthInternalResponder.set_log_line(NthInternalLogLine); \ + return (NthInternalResponder); \ + }(::nth::source_location::current()) \ + .set((#__VA_ARGS__), \ + NTH_DEBUG_INTERNAL_TRACE_INJECTED_EXPR( \ + __VA_ARGS__))) { \ } else \ switch (0) \ default: \ diff --git a/nth/meta/sequence.h b/nth/meta/sequence.h index 9b26147..cbfc061 100644 --- a/nth/meta/sequence.h +++ b/nth/meta/sequence.h @@ -79,6 +79,18 @@ struct Sequence { Sequence<>()); } + template + static constexpr auto chunk() requires(size() % N == 0) { + if constexpr (empty()) { + return Sequence<>{}; + } else { + return [](std::integer_sequence) { + return Sequence()>{} + drop().template chunk(); + } + (std::make_index_sequence{}); + } + } + static constexpr auto unique() { if constexpr (empty()) { return Sequence<>{}; @@ -102,6 +114,19 @@ struct Sequence { return typename split_type::template tail{}; } + template + [[nodiscard]] static constexpr auto drop() requires(sizeof...(Vs) >= N) { + if constexpr (N == 1) { + using split_type = SplitFirst; + return typename split_type::template tail{}; + } else { + return [](std::integer_sequence) { + return select<(N + Ns)...>(); + } + (std::make_index_sequence{}); + } + } + template static constexpr auto select() { return Sequence<__type_pack_element...>::value...>{}; @@ -207,8 +232,7 @@ template inline constexpr internal_meta::Sequence sequence; template -static constexpr auto index_sequence = - internal_meta::IndexSequence::value; +static constexpr auto index_sequence = internal_meta::IndexSequence::value; } // namespace nth diff --git a/nth/meta/sequence_test.cc b/nth/meta/sequence_test.cc index ef1ef1c..9a8252c 100644 --- a/nth/meta/sequence_test.cc +++ b/nth/meta/sequence_test.cc @@ -50,6 +50,11 @@ static_assert(nth::sequence<1>.head() == 1); static_assert(nth::sequence<2, 3, 4>.head() == 2); static_assert(nth::sequence<1>.tail() == nth::sequence<>); static_assert(nth::sequence<2, 3, 4>.tail() == nth::sequence<3, 4>); +static_assert(nth::sequence<1>.drop<1>() == nth::sequence<>); +static_assert(nth::sequence<2, 3, 4>.drop<1>() == nth::sequence<3, 4>); +static_assert(nth::sequence<1>.drop<0>() == nth::sequence<1>); +static_assert(nth::sequence<2, 3, 4>.drop<0>() == nth::sequence<2, 3, 4>); +static_assert(nth::sequence<2, 3, 4>.drop<2>() == nth::sequence<4>); static_assert(not nth::sequence<>.any<[](auto x) { return x % 2 == 0; }>()); static_assert(not nth::sequence<1>.any<[](auto x) { return x % 2 == 0; }>()); @@ -61,9 +66,9 @@ static_assert(nth::sequence<>.all<[](auto x) { return x % 2 == 0; }>()); static_assert(not nth::sequence<1>.all<[](auto x) { return x % 2 == 0; }>()); static_assert(not nth::sequence<1, 3>.all<[](auto x) { return x % 2 == 0; }>()); -static_assert( nth::sequence<2>.all<[](auto x) { return x % 2 == 0; }>()); -static_assert( nth::sequence<2, 4>.all<[](auto x) { return x % 2 == 0; }>()); -static_assert(not nth::sequence<1, 2>.all<[](auto x) { return x % 2 == 0; }>()); +static_assert(nth::sequence<2>.all<[](auto x) { return x % 2 == 0; }>()); +static_assert(nth::sequence<2, 4>.all<[](auto x) { return x % 2 == 0; }>()); +static_assert(not nth::sequence<1, 2>.all<[](auto x) { return x % 2 == 0; }>()); static_assert(nth::sequence<>.unique() == nth::sequence<>); static_assert(nth::sequence<1>.unique() == nth::sequence<1>); @@ -103,6 +108,15 @@ static_assert(nth::sequence<1, 2>.get<0>() == 1); static_assert(nth::sequence<1, 2, 3>.get<1>() == 2); static_assert(nth::sequence<1, 2, 3, 1, 2, 3>.get<4>() == 2); +static_assert(nth::sequence<>.chunk<1>() == nth::sequence<>); +static_assert(nth::sequence<>.chunk<2>() == nth::sequence<>); +static_assert(nth::sequence<0, 1, 2, 3>.chunk<2>() == + nth::sequence, nth::sequence<2, 3>>); +static_assert(nth::sequence<0, 1, 2, 3, 4, 5>.chunk<2>() == + nth::sequence, nth::sequence<2, 3>, + nth::sequence<4, 5>>); +static_assert(nth::sequence<0, 1, 2, 3, 4, 5>.chunk<3>() == + nth::sequence, nth::sequence<3, 4, 5>>); } // namespace int main() { diff --git a/nth/meta/type.h b/nth/meta/type.h index d83831d..72ecff4 100644 --- a/nth/meta/type.h +++ b/nth/meta/type.h @@ -73,6 +73,11 @@ struct Type { return TypeId(+[] { return std::string_view(Name); }); } + template U> + static constexpr auto cast(U&& u) { + return static_cast(std::forward(u)); + } + static constexpr Type> decayed() { return {}; } static constexpr Type> without_reference() { @@ -116,8 +121,8 @@ struct Type { return os << std::string_view(name()); } - private: - static constexpr auto Name = Type::name(); + private: + static constexpr auto Name = Type::name(); }; template @@ -127,7 +132,7 @@ std::false_type IsTypeImpl(...); template struct FunctionSignature { static constexpr Type return_type; - static constexpr auto parameters = sequence{}...>; + static constexpr auto parameters = sequence{}...>; }; } // namespace internal_type @@ -149,7 +154,7 @@ using type_t = typename decltype(t)::type; // useful in two common scenarios: First, when the you need to retrieve the // first element of a pack (which could alternately be computed via // `nth::type_t.head()>`). Second, when you want to -// repeat the same type for each element of a pack, you can use +// repeat the same type for each element of a pack, you can use // // ``` // nth::first_t... @@ -157,7 +162,8 @@ using type_t = typename decltype(t)::type; // where you might otherwise need to coerce the cumbersome // // ``` -// nth::type_sequence.template transform<[](auto) { return nth::type; }>(); +// nth::type_sequence.template transform<[](auto) { return +// nth::type; }>(); // ``` // back into a pack. template diff --git a/nth/meta/type_test.cc b/nth/meta/type_test.cc index 1f1a6c4..888b761 100644 --- a/nth/meta/type_test.cc +++ b/nth/meta/type_test.cc @@ -30,6 +30,15 @@ static_assert(nth::type.decayed() == nth::type); static_assert(nth::type.decayed() == nth::type); +// cast +static_assert(nth::type.cast(true) == 1); +struct A {}; +struct B { + constexpr B(A) : value(17) {} + int value; +}; +static_assert(nth::type.cast(A{}).value == 17); + // type_t static_assert(nth::type>> == nth::type); static_assert(nth::type>> == nth::type);