]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/hana/example/misc/restricted_function.cpp
1 // Copyright Louis Dionne 2013-2017
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
5 #include <boost/hana/all_of.hpp>
6 #include <boost/hana/assert.hpp>
7 #include <boost/hana/cartesian_product.hpp>
8 #include <boost/hana/contains.hpp>
9 #include <boost/hana/core/to.hpp>
10 #include <boost/hana/equal.hpp>
11 #include <boost/hana/functional/demux.hpp>
12 #include <boost/hana/fuse.hpp>
13 #include <boost/hana/integral_constant.hpp>
14 #include <boost/hana/minus.hpp>
15 #include <boost/hana/mod.hpp>
16 #include <boost/hana/not.hpp>
17 #include <boost/hana/not_equal.hpp>
18 #include <boost/hana/or.hpp>
19 #include <boost/hana/plus.hpp>
20 #include <boost/hana/set.hpp>
21 #include <boost/hana/transform.hpp>
22 #include <boost/hana/tuple.hpp>
23 namespace hana
= boost::hana
;
24 using namespace hana::literals
;
27 // A function that can have an arbitrary compile-time set of values as a domain
28 // and co-domain. This is most likely purely of theoretical interest, but it
29 // allows creating functions with very complex domains and co-domains that are
30 // computed at compile-time.
34 template <typename Domain
, typename Codomain
, typename F
>
35 struct function_type
{
36 using hana_tag
= Function
;
43 constexpr auto operator()(X x
) const {
44 BOOST_HANA_CONSTANT_ASSERT(boost::hana::contains(domain_
, x
));
49 template <typename
...F
, typename
...G
>
50 constexpr auto operator==(function_type
<F
...> f
, function_type
<G
...> g
)
51 { return hana::equal(f
, g
); }
53 template <typename
...F
, typename
...G
>
54 constexpr auto operator!=(function_type
<F
...> f
, function_type
<G
...> g
)
55 { return hana::not_equal(f
, g
); }
58 auto function
= [](auto domain
, auto codomain
) {
59 return [=](auto definition
) {
60 return function_type
<decltype(domain
), decltype(codomain
), decltype(definition
)>{
61 domain
, codomain
, definition
66 template <typename Function
>
67 constexpr auto domain(Function f
)
70 template <typename Function
>
71 constexpr auto codomain(Function f
)
72 { return f
.codomain_
; }
74 template <typename Function
>
75 constexpr auto range(Function f
) {
76 // We must convert to hana::tuple first because hana::set is not a Functor
77 return hana::to_set(hana::transform(hana::to_tuple(domain(f
)), f
));
80 template <typename P
, typename Q
>
81 constexpr auto implies(P p
, Q q
) {
82 return hana::or_(hana::not_(p
), q
);
86 constexpr auto is_injective(F f
) {
87 auto dom
= hana::to_tuple(domain(f
));
88 auto pairs
= hana::cartesian_product(hana::make_tuple(dom
, dom
));
89 return hana::all_of(pairs
, hana::fuse([&](auto x
, auto y
) {
90 return implies(hana::not_equal(x
, y
), hana::not_equal(f(x
), f(y
)));
95 constexpr auto is_onto(F f
) {
96 return codomain(f
) == range(f
);
99 namespace boost
{ namespace hana
{
101 struct equal_impl
<Function
, Function
> {
102 template <typename F
, typename G
>
103 static constexpr auto apply(F f
, G g
) {
104 return domain(f
) == domain(g
) &&
105 hana::all_of(domain(f
), hana::demux(hana::equal
)(f
, g
));
108 }} // end namespace boost::hana
111 auto f
= function(hana::make_set(1_c
, 2_c
, 3_c
), hana::make_set(1_c
, 2_c
, 3_c
, 4_c
, 5_c
, 6_c
))(
112 [](auto x
) { return x
+ 1_c
; }
115 auto g
= function(hana::make_set(1_c
, 2_c
, 3_c
), hana::make_set(2_c
, 3_c
, 4_c
))(
116 [](auto x
) { return x
+ 1_c
; }
119 auto h
= function(hana::make_set(1_c
, 2_c
, 3_c
), hana::make_set(0_c
, 1_c
, 2_c
))(
120 [](auto x
) { return x
- 1_c
; }
123 BOOST_HANA_CONSTANT_CHECK(f
== g
);
124 BOOST_HANA_CONSTANT_CHECK(f
!= h
);
125 BOOST_HANA_CONSTANT_CHECK(f(1_c
) == 2_c
);
127 BOOST_HANA_CONSTANT_CHECK(range(f
) == hana::make_set(4_c
, 3_c
, 2_c
));
128 BOOST_HANA_CONSTANT_CHECK(range(g
) == hana::make_set(2_c
, 3_c
, 4_c
));
129 BOOST_HANA_CONSTANT_CHECK(range(h
) == hana::make_set(0_c
, 1_c
, 2_c
));
131 BOOST_HANA_CONSTANT_CHECK(hana::not_(is_onto(f
)));
132 BOOST_HANA_CONSTANT_CHECK(is_onto(g
));
133 BOOST_HANA_CONSTANT_CHECK(is_onto(h
));
135 auto even
= function(hana::make_set(1_c
, 2_c
, 3_c
), hana::make_set(hana::true_c
, hana::false_c
))(
136 [](auto x
) { return x
% 2_c
== 0_c
; }
139 BOOST_HANA_CONSTANT_CHECK(is_injective(f
));
140 BOOST_HANA_CONSTANT_CHECK(is_injective(g
));
141 BOOST_HANA_CONSTANT_CHECK(is_injective(h
));
142 BOOST_HANA_CONSTANT_CHECK(hana::not_(is_injective(even
)));