Skip to content

Commit 2560003

Browse files
committed
added structured binding support for types derived from product type
1 parent d3e61b5 commit 2560003

File tree

3 files changed

+38
-8
lines changed

3 files changed

+38
-8
lines changed

include/beman/execution26/detail/product_type.hpp

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
// ----------------------------------------------------------------------------
1111

1212
namespace beman::execution26::detail {
13-
template <::std::size_t, typename T>
13+
14+
template <::std::size_t I, typename T>
1415
struct product_type_element {
1516
T value;
1617
auto operator==(const product_type_element&) const -> bool = default;
@@ -23,6 +24,7 @@ template <::std::size_t... I, typename... T>
2324
struct product_type_base<::std::index_sequence<I...>, T...>
2425
: ::beman::execution26::detail::product_type_element<I, T>... {
2526
static constexpr ::std::size_t size() { return sizeof...(T); }
27+
static constexpr bool is_product_type{true};
2628

2729
template <::std::size_t J, typename S>
2830
static auto element_get(::beman::execution26::detail::product_type_element<J, S>& self) noexcept -> S& {
@@ -64,6 +66,10 @@ struct product_type_base<::std::index_sequence<I...>, T...>
6466
auto operator==(const product_type_base&) const -> bool = default;
6567
};
6668

69+
template <typename T>
70+
concept is_product_type_c = requires(T const& t){ T::is_product_type; };
71+
72+
6773
template <typename... T>
6874
struct product_type : ::beman::execution26::detail::product_type_base<::std::index_sequence_for<T...>, T...> {
6975
template <typename Allocator, typename Product, std::size_t... I>
@@ -108,13 +114,16 @@ constexpr auto is_product_type(const ::beman::execution26::detail::product_type<
108114
} // namespace beman::execution26::detail
109115

110116
namespace std {
111-
template <typename... T>
112-
struct tuple_size<::beman::execution26::detail::product_type<T...>>
113-
: ::std::integral_constant<std::size_t, sizeof...(T)> {};
114-
template <::std::size_t I, typename... T>
115-
struct tuple_element<I, ::beman::execution26::detail::product_type<T...>> {
117+
template <typename T>
118+
requires ::beman::execution26::detail::is_product_type_c<T>
119+
struct tuple_size<T>
120+
: ::std::integral_constant<std::size_t, T::size()> {};
121+
122+
template <::std::size_t I, typename T>
123+
requires ::beman::execution26::detail::is_product_type_c<T>
124+
struct tuple_element<I, T> {
116125
using type =
117-
::std::decay_t<decltype(::std::declval<::beman::execution26::detail::product_type<T...>>().template get<I>())>;
126+
::std::decay_t<decltype(::std::declval<T>().template get<I>())>;
118127
};
119128
} // namespace std
120129

tests/beman/execution26/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ foreach(test ${execution_tests})
129129
add_test(NAME ${TEST_EXE} COMMAND $<TARGET_FILE:${TEST_EXE}>)
130130
endforeach()
131131

132-
if(PROJECT_IS_TOP_LEVEL)
132+
if(NOT PROJECT_IS_TOP_LEVEL)
133133
# test if the targets are findable from the build directory
134134
# cmake-format: off
135135
add_test(NAME find-package-test

tests/beman/execution26/exec-snd-expos.test.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,27 @@ auto test_product_type() -> void {
858858
ASSERT(p5.get<2>() == nm(3));
859859
ASSERT(p5.get<3>() == nm(4));
860860
ASSERT(p5.get<4>() == nm(5));
861+
862+
test_detail::product_type prod{1, true, 'c'};
863+
static_assert(test_detail::is_product_type_c<decltype(prod)>);
864+
static_assert(3u == std::tuple_size<decltype(prod)>::value);
865+
static_assert(std::same_as<int, std::tuple_element<0u, decltype(prod)>::type>);
866+
static_assert(std::same_as<bool, std::tuple_element<1u, decltype(prod)>::type>);
867+
static_assert(std::same_as<char, std::tuple_element<2u, decltype(prod)>::type>);
868+
auto&&[i, b, c] = prod;
869+
test::use(i, b, c);
870+
871+
struct derived: decltype(prod) {};
872+
static_assert(3u == std::tuple_size<derived>::value);
873+
static_assert(std::same_as<int, std::tuple_element<0u, derived>::type>);
874+
static_assert(std::same_as<bool, std::tuple_element<1u, derived>::type>);
875+
static_assert(std::same_as<char, std::tuple_element<2u, derived>::type>);
876+
derived d{1, true, 'c'};
877+
auto&&[di, db, dc] = d;
878+
assert(di == d.get<0>());
879+
assert(db == d.get<1>());
880+
assert(dc == d.get<2>());
881+
test::use(di, db, dc);
861882
}
862883
auto test_connect_all() -> void {
863884
static_assert(test_std::operation_state<operation_state<receiver>>);

0 commit comments

Comments
 (0)