Skip to content

Commit 77caff1

Browse files
ricejasonfldionne
authored andcommitted
[view] cartesian_product
- Adds cartesian_product_view_t and cartesian_product_element_view_t with specializations for the following: - at_impl - is_empty_impl - length_impl - unpack_impl
1 parent b8c5848 commit 77caff1

File tree

7 files changed

+570
-11
lines changed

7 files changed

+570
-11
lines changed

include/boost/hana/cartesian_product.hpp

+65-10
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ BOOST_HANA_NAMESPACE_BEGIN
4949
template <std::size_t ...Lengths>
5050
struct cartesian_product_indices {
5151
static constexpr std::size_t total_length() {
52-
std::size_t lengths[] = {Lengths...};
52+
std::size_t lengths[sizeof...(Lengths)] = {Lengths...};
5353
std::size_t r = 1;
5454
for (std::size_t len: lengths)
5555
r *= len;
@@ -59,31 +59,85 @@ BOOST_HANA_NAMESPACE_BEGIN
5959
static constexpr std::size_t length = total_length();
6060

6161
static constexpr auto indices_of(std::size_t i) {
62-
constexpr std::size_t lengths[] = {Lengths...};
6362
constexpr std::size_t n = sizeof...(Lengths);
63+
constexpr std::size_t lengths[n] = {Lengths...};
6464
detail::array<std::size_t, n> result{};
65+
if (length == 0) {
66+
return result;
67+
}
6568
for (std::size_t j = n; j--;) {
6669
result[j] = i % lengths[j];
6770
i /= lengths[j];
6871
}
6972
return result;
7073
}
7174

72-
template <typename S, std::size_t n, std::size_t ...k, typename ...Xs>
75+
template <std::size_t n, typename F, std::size_t ...k, typename ...Xs>
7376
static constexpr auto
74-
product_element(std::index_sequence<k...>, Xs&& ...xs) {
77+
product_element(std::index_sequence<k...>, F&& f, Xs&& ...xs) {
7578
constexpr auto indices = indices_of(n);
76-
return hana::make<S>(hana::at_c<indices[k]>(xs)...);
79+
return static_cast<F&&>(f)(hana::at_c<indices[k]>(xs)...);
7780
}
7881

79-
template <typename S, std::size_t ...n, typename ...Xs>
82+
template <std::size_t ...n, typename F, typename ...Xs>
8083
static constexpr auto
81-
create_product(std::index_sequence<n...>, Xs&& ...xs) {
82-
return hana::make<S>(product_element<S, n>(
83-
std::make_index_sequence<sizeof...(Xs)>{}, xs...
84+
create_product(std::index_sequence<n...>, F&& f, Xs&& ...xs) {
85+
return F{}(product_element<n>(
86+
std::make_index_sequence<sizeof...(Xs)>{},
87+
static_cast<F&&>(f), xs...
8488
)...);
8589
}
8690
};
91+
92+
template <>
93+
struct cartesian_product_indices<> {
94+
static constexpr std::size_t total_length()
95+
{ return 0; }
96+
97+
static constexpr std::size_t length = 0;
98+
};
99+
100+
struct make_cartesian_product_indices_helper_t {
101+
template <typename ...Xs>
102+
constexpr auto operator()(Xs&& ...xs) const
103+
-> detail::cartesian_product_indices<
104+
decltype(hana::length(xs))::value...
105+
>
106+
{ return {}; }
107+
};
108+
109+
struct make_cartesian_product_indices_t {
110+
template <typename Xs>
111+
constexpr auto operator()(Xs&& xs) const {
112+
return hana::unpack(
113+
static_cast<Xs&&>(xs),
114+
make_cartesian_product_indices_helper_t{});
115+
}
116+
};
117+
118+
constexpr make_cartesian_product_indices_t make_cartesian_product_indices{};
119+
120+
template <typename F, std::size_t n>
121+
struct make_cartesian_product_element_t {
122+
F const& f;
123+
124+
constexpr auto operator()() const {
125+
return f();
126+
}
127+
128+
template <typename X1, typename ...Xs>
129+
constexpr auto operator()(X1&& x1, Xs&& ...xs) const {
130+
constexpr auto indices = detail::cartesian_product_indices<
131+
decltype(hana::length(x1))::value,
132+
decltype(hana::length(xs))::value...
133+
>{};
134+
return indices.template product_element<n>(
135+
std::make_index_sequence<sizeof...(Xs) + 1>{}, f,
136+
static_cast<X1&&>(x1),
137+
static_cast<Xs&&>(xs)...
138+
);
139+
}
140+
};
87141
}
88142

89143
// Credits: implementation adapted from http://github.com/alexk7/hel.
@@ -99,8 +153,9 @@ BOOST_HANA_NAMESPACE_BEGIN
99153
using indices = detail::cartesian_product_indices<
100154
decltype(hana::length(xs))::value...
101155
>;
102-
return indices::template create_product<S>(
156+
return indices::template create_product(
103157
std::make_index_sequence<indices::length>{},
158+
hana::make<S>,
104159
static_cast<Xs&&>(xs)...);
105160
}
106161

include/boost/hana/view.hpp

+110-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Distributed under the Boost Software License, Version 1.0.
1616
#include <boost/hana/and.hpp>
1717
#include <boost/hana/at.hpp>
1818
#include <boost/hana/bool.hpp>
19+
#include <boost/hana/cartesian_product.hpp>
1920
#include <boost/hana/config.hpp>
2021
#include <boost/hana/detail/algorithm.hpp>
2122
#include <boost/hana/detail/decay.hpp>
@@ -58,6 +59,43 @@ BOOST_HANA_NAMESPACE_BEGIN
5859
detail::is_view<Sequence>::value, Sequence, Sequence&
5960
>::type;
6061

62+
//////////////////////////////////////////////////////////////////////
63+
// cartesian_product_element_view
64+
//////////////////////////////////////////////////////////////////////
65+
template <typename Sequences, std::size_t i>
66+
struct cartesian_product_element_view_t {
67+
detail::view_storage<Sequences> sequences_;
68+
using hana_tag = view_tag;
69+
};
70+
71+
template <typename Sequences, std::size_t i>
72+
struct is_view<cartesian_product_element_view_t<Sequences, i>> {
73+
static constexpr bool value = true;
74+
};
75+
76+
//////////////////////////////////////////////////////////////////////
77+
// cartesian_product_view
78+
//////////////////////////////////////////////////////////////////////
79+
template <typename Sequences>
80+
struct cartesian_product_view_t {
81+
detail::view_storage<Sequences> sequences_;
82+
using hana_tag = view_tag;
83+
};
84+
85+
struct make_cartesian_product_view_t {
86+
template <typename Sequences>
87+
constexpr cartesian_product_view_t<Sequences> operator()(Sequences& s) const {
88+
return {s};
89+
}
90+
};
91+
92+
constexpr make_cartesian_product_view_t cartesian_product_view{};
93+
94+
template <typename Sequences>
95+
struct is_view<cartesian_product_view_t<Sequences>> {
96+
static constexpr bool value = true;
97+
};
98+
6199
//////////////////////////////////////////////////////////////////////
62100
// sliced_view
63101
//////////////////////////////////////////////////////////////////////
@@ -212,6 +250,33 @@ BOOST_HANA_NAMESPACE_BEGIN
212250
//////////////////////////////////////////////////////////////////////////
213251
template <>
214252
struct unpack_impl<hana::view_tag> {
253+
// cartesian_product_element_view
254+
template <typename Sequences, std::size_t i, typename F>
255+
static constexpr decltype(auto)
256+
apply(detail::cartesian_product_element_view_t<Sequences, i> view, F const& f) {
257+
using Indices = decltype(detail::make_cartesian_product_indices(view.sequences_));
258+
return hana::unpack(view.sequences_,
259+
detail::make_cartesian_product_element_t<F, i>{f});
260+
}
261+
262+
// cartesian_product_view
263+
template <typename View, typename F, std::size_t ...i>
264+
static constexpr decltype(auto)
265+
unpack_cartesian_product(View view, F&& f, std::index_sequence<i...>) {
266+
return static_cast<F&&>(f)(
267+
detail::cartesian_product_element_view_t<decltype(view.sequences_), i>{
268+
view.sequences_
269+
}...);
270+
}
271+
272+
template <typename Sequences, typename F>
273+
static constexpr decltype(auto)
274+
apply(detail::cartesian_product_view_t<Sequences> view, F&& f) {
275+
using Indices = decltype(detail::make_cartesian_product_indices(view.sequences_));
276+
return unpack_cartesian_product(view, static_cast<F&&>(f),
277+
std::make_index_sequence<Indices::length>{});
278+
}
279+
215280
// sliced_view
216281
template <typename Sequence, std::size_t ...i, typename F>
217282
static constexpr decltype(auto)
@@ -279,6 +344,22 @@ BOOST_HANA_NAMESPACE_BEGIN
279344
//////////////////////////////////////////////////////////////////////////
280345
template <>
281346
struct at_impl<hana::view_tag> {
347+
// cartesian_product_element_view
348+
template <typename Sequences, std::size_t i, typename N>
349+
static constexpr decltype(auto)
350+
apply(detail::cartesian_product_element_view_t<Sequences, i> view, N const&) {
351+
using Indices = decltype(detail::make_cartesian_product_indices(view.sequences_));
352+
return hana::at_c<Indices::indices_of(i)[N::value]>(
353+
hana::at_c<N::value>(view.sequences_));
354+
}
355+
356+
// cartesian_product_view
357+
template <typename Sequences, typename N>
358+
static constexpr decltype(auto)
359+
apply(detail::cartesian_product_view_t<Sequences> view, N const&) {
360+
return detail::cartesian_product_element_view_t<Sequences, N::value>{view.sequences_};
361+
}
362+
282363
// sliced_view
283364
template <typename Sequence, std::size_t ...i, typename N>
284365
static constexpr decltype(auto)
@@ -368,6 +449,19 @@ BOOST_HANA_NAMESPACE_BEGIN
368449

369450
template <>
370451
struct length_impl<hana::view_tag> {
452+
// cartesian_product_view_element
453+
template <typename Sequences, std::size_t i>
454+
static constexpr auto apply(detail::cartesian_product_element_view_t<Sequences, i> view) {
455+
return hana::length(view.sequences_);
456+
}
457+
458+
// cartesian_product_view
459+
template <typename Sequences>
460+
static constexpr auto apply(detail::cartesian_product_view_t<Sequences> view) {
461+
using Indices = decltype(detail::make_cartesian_product_indices(view.sequences_));
462+
return hana::size_c<Indices::length>;
463+
}
464+
371465
// sliced_view
372466
template <typename Sequence, std::size_t ...i>
373467
static constexpr auto
@@ -394,11 +488,12 @@ BOOST_HANA_NAMESPACE_BEGIN
394488
struct sum_lengths {
395489
template <typename ...S>
396490
constexpr auto operator()(S const& ...s) const {
397-
constexpr std::size_t lengths[] = {decltype(hana::length(s))::value...};
491+
constexpr std::size_t lengths[sizeof...(S)] = {decltype(hana::length(s))::value...};
398492
constexpr std::size_t sum = detail::accumulate(lengths, lengths+sizeof...(S), 0);
399493
return hana::size_t<sum>{};
400494
}
401495
};
496+
402497
template <typename Sequences>
403498
static constexpr auto apply(detail::flattened_view_t<Sequences> view) {
404499
return hana::unpack(view.sequences_, sum_lengths{});
@@ -424,6 +519,20 @@ BOOST_HANA_NAMESPACE_BEGIN
424519

425520
template <>
426521
struct is_empty_impl<hana::view_tag> {
522+
// cartesian_product_view_element
523+
template <typename Sequences, std::size_t i>
524+
static constexpr auto apply(detail::cartesian_product_element_view_t<Sequences, i> view) {
525+
using Indices = decltype(detail::make_cartesian_product_indices(view.sequences_));
526+
return hana::bool_c<Indices::length == 0>;
527+
}
528+
529+
// cartesian_product_view
530+
template <typename Sequences>
531+
static constexpr auto apply(detail::cartesian_product_view_t<Sequences> view) {
532+
using Indices = decltype(detail::make_cartesian_product_indices(view.sequences_));
533+
return hana::bool_c<Indices::length == 0>;
534+
}
535+
427536
// sliced_view
428537
template <typename Sequence, std::size_t ...i>
429538
static constexpr auto

test/view/cartesian_product/at.cpp

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// Copyright Louis Dionne 2013-2016
2+
// Copyright Jason Rice 2017
3+
// Distributed under the Boost Software License, Version 1.0.
4+
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
5+
6+
#include <boost/hana/assert.hpp>
7+
#include <boost/hana/at.hpp>
8+
#include <boost/hana/equal.hpp>
9+
#include <boost/hana/integral_constant.hpp>
10+
#include <boost/hana/view.hpp>
11+
12+
#include <laws/base.hpp>
13+
#include <support/seq.hpp>
14+
namespace hana = boost::hana;
15+
using hana::test::ct_eq;
16+
17+
18+
int main() {
19+
auto container = ::seq;
20+
21+
{
22+
const auto storage = container(
23+
container(ct_eq<0>{})
24+
);
25+
26+
auto view = hana::detail::cartesian_product_view(storage);
27+
BOOST_HANA_CONSTANT_CHECK(hana::equal(
28+
hana::at(view, hana::size_c<0>),
29+
container(ct_eq<0>{})
30+
));
31+
}
32+
33+
{
34+
const auto storage = container(
35+
container(ct_eq<0>{}),
36+
container(ct_eq<0>{})
37+
);
38+
39+
auto view = hana::detail::cartesian_product_view(storage);
40+
BOOST_HANA_CONSTANT_CHECK(hana::equal(
41+
hana::at(view, hana::size_c<0>),
42+
container(ct_eq<0>{}, ct_eq<0>{})
43+
));
44+
}
45+
46+
{
47+
const auto storage = container(
48+
container(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
49+
container(ct_eq<3>{}, ct_eq<4>{})
50+
);
51+
52+
auto view = hana::detail::cartesian_product_view(storage);
53+
54+
auto expected = container(
55+
container(ct_eq<0>{}, ct_eq<3>{}),
56+
container(ct_eq<0>{}, ct_eq<4>{}),
57+
container(ct_eq<1>{}, ct_eq<3>{}),
58+
container(ct_eq<1>{}, ct_eq<4>{}),
59+
container(ct_eq<2>{}, ct_eq<3>{}),
60+
container(ct_eq<2>{}, ct_eq<4>{})
61+
);
62+
63+
BOOST_HANA_CONSTANT_CHECK(hana::equal(
64+
hana::at(view, hana::size_c<0>),
65+
hana::at(expected, hana::size_c<0>)
66+
));
67+
BOOST_HANA_CONSTANT_CHECK(hana::equal(
68+
hana::at(view, hana::size_c<1>),
69+
hana::at(expected, hana::size_c<1>)
70+
));
71+
BOOST_HANA_CONSTANT_CHECK(hana::equal(
72+
hana::at(view, hana::size_c<2>),
73+
hana::at(expected, hana::size_c<2>)
74+
));
75+
BOOST_HANA_CONSTANT_CHECK(hana::equal(
76+
hana::at(view, hana::size_c<3>),
77+
hana::at(expected, hana::size_c<3>)
78+
));
79+
BOOST_HANA_CONSTANT_CHECK(hana::equal(
80+
hana::at(view, hana::size_c<4>),
81+
hana::at(expected, hana::size_c<4>)
82+
));
83+
BOOST_HANA_CONSTANT_CHECK(hana::equal(
84+
hana::at(view, hana::size_c<5>),
85+
hana::at(expected, hana::size_c<5>)
86+
));
87+
}
88+
}

0 commit comments

Comments
 (0)