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
20 changes: 20 additions & 0 deletions docs/type_traits.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,26 @@ NOTE: Detecting structurality of a type is not yet possible in the general case,
so there are certain structural types for which this trait will be `false`. In
practice those types should be rare, and there should be no false positives.

=== `nth_t`

`nth_t` is a type alias that extracts the nth element from a pack of types (starting at 0 of course):

[source,cpp]
----
// nth_t<Index, Ts...>
static_assert(std::is_same_v<stdx::nth_t<1, int, float, bool>, float>);
----

=== `nth_v`

`nth_v` is a `constexpr` variable template that extracts the nth element from a pack of values (starting at 0 of course):

[source,cpp]
----
// nth_v<Index, Vs...>
static_assert(stdx::nth_v<1, 6, 28, 496> == 28);
----

=== `template_for_each`

A xref:type_traits.adoc#_type_list_and_value_list[`type_list` or a `value_list`]
Expand Down
13 changes: 3 additions & 10 deletions include/stdx/env.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ template <typename... Envs> struct env {
CONSTEVAL static auto query(Q) noexcept {
using I = boost::mp11::mp_find_if_q<boost::mp11::mp_list<Envs...>,
_env::has_query<Q>>;
using E = boost::mp11::mp_at<boost::mp11::mp_list<Envs...>, I>;
using E = nth_t<I::value, Envs...>;
return Q{}(E{});
}
};
Expand All @@ -61,18 +61,11 @@ template <std::size_t N> struct autowrap<str_lit_t<N>> {
template <typename T> autowrap(T) -> autowrap<T>;
template <std::size_t N> autowrap(str_lit_t<N>) -> autowrap<str_lit_t<N>>;

template <auto V> struct wrap {
constexpr static auto value = V;
};

template <typename> struct for_each_pair;
template <std::size_t... Is> struct for_each_pair<std::index_sequence<Is...>> {
template <auto... Args>
using type = env<
_env::ct_prop<boost::mp11::mp_at_c<boost::mp11::mp_list<wrap<Args>...>,
2 * Is>::value.value,
boost::mp11::mp_at_c<boost::mp11::mp_list<wrap<Args>...>,
(2 * Is) + 1>::value.value>...>;
using type = env<ct_prop<nth_v<2 * Is, Args...>.value,
nth_v<(2 * Is) + 1, Args...>.value>...>;
};

template <envlike Env = env<>>
Expand Down
9 changes: 4 additions & 5 deletions include/stdx/function_traits.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include <stdx/type_traits.hpp>

#include <boost/mp11/algorithm.hpp>
#include <boost/mp11/utility.hpp>

Expand All @@ -21,11 +23,8 @@ struct function_traits<std::function<R(Args...)>> {
using decayed_args = List<std::decay_t<Args>...>;
using arity = std::integral_constant<std::size_t, sizeof...(Args)>;

template <auto N>
using nth_arg = boost::mp11::mp_at_c<args<boost::mp11::mp_list>, N>;
template <auto N>
using decayed_nth_arg =
boost::mp11::mp_at_c<decayed_args<boost::mp11::mp_list>, N>;
template <auto N> using nth_arg = nth_t<N, Args...>;
template <auto N> using decayed_nth_arg = std::decay_t<nth_arg<N>>;
};
} // namespace detail

Expand Down
42 changes: 42 additions & 0 deletions include/stdx/type_traits.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
#pragma once

#include <stdx/compiler.hpp>

#include <boost/mp11/algorithm.hpp>

#include <type_traits>
#include <utility>

Expand Down Expand Up @@ -227,5 +231,43 @@ using shrink_t = decltype([]() -> T (*)() { return nullptr; });

template <typename T> using expand_t = decltype(T{}()());
#endif

STDX_PRAGMA(diagnostic push)
#ifdef __clang__
STDX_PRAGMA(diagnostic ignored "-Wunknown-warning-option")
STDX_PRAGMA(diagnostic ignored "-Wc++26-extensions")
#endif
template <unsigned int N, typename... Ts>
using nth_t =
#if __cpp_pack_indexing >= 202311L
Ts...[N];
#elif __has_builtin(__type_pack_element)
__type_pack_element<N, Ts...>;
#else
boost::mp11::mp_at_c<type_list<Ts...>, N>;
#endif
STDX_PRAGMA(diagnostic pop)

#if __cplusplus >= 202002L
namespace detail {
template <auto V> struct value_wrapper {
constexpr static auto value = V;
};
} // namespace detail

STDX_PRAGMA(diagnostic push)
#ifdef __clang__
STDX_PRAGMA(diagnostic ignored "-Wunknown-warning-option")
STDX_PRAGMA(diagnostic ignored "-Wc++26-extensions")
#endif
template <unsigned int N, auto... Vs>
constexpr auto nth_v =
#if __cpp_pack_indexing >= 202311L
Vs...[N];
#else
boost::mp11::mp_at_c<type_list<detail::value_wrapper<Vs>...>, N>::value;
#endif
STDX_PRAGMA(diagnostic pop)
#endif
} // namespace v1
} // namespace stdx
11 changes: 11 additions & 0 deletions test/type_traits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,3 +258,14 @@ TEST_CASE("type shrinkage", "[type_traits]") {
static_assert(std::same_as<stdx::expand_t<X>, C>);
}
#endif

TEST_CASE("nth type in pack", "[type_traits]") {
static_assert(
std::is_same_v<stdx::nth_t<2, bool, char, float, int>, float>);
}

#if __cplusplus >= 202002L
TEST_CASE("nth value in pack", "[type_traits]") {
static_assert(stdx::nth_v<2, 0, true, 'b', 3> == 'b');
}
#endif