1 // Copyright Louis Dionne 2013-2016
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/assert.hpp>
6 #include <boost/hana/core/tag_of.hpp>
7 #include <boost/hana/integral_constant.hpp>
8 #include <boost/hana/minus.hpp>
9 #include <boost/hana/not_equal.hpp>
10 #include <boost/hana/tuple.hpp>
15 namespace hana
= boost::hana
;
19 template <typename Tag
>
22 static void apply(std::ostream
&, X
const&) {
23 // possibly some default implementation
28 void print(std::ostream
& os
, X x
) {
29 using Tag
= typename
hana::tag_of
<X
>::type
;
30 print_impl
<Tag
>::apply(os
, x
);
38 using hana_tag
= vector_tag
;
39 static constexpr std::size_t size
= 0;
42 template <typename T1
>
45 using hana_tag
= vector_tag
;
46 static constexpr std::size_t size
= 1;
48 template <typename Index
>
49 auto const& operator[](Index i
) const {
50 static_assert(i
== 0u, "index out of bounds");
55 template <typename T1
, typename T2
>
58 using hana_tag
= vector_tag
;
59 static constexpr std::size_t size
= 2;
61 // Using Hana as a backend to simplify the example.
62 template <typename Index
>
63 auto const& operator[](Index i
) const {
64 return *hana::make_tuple(&t1
, &t2
)[i
];
73 struct print_impl
<vector_tag
> {
74 template <typename vectorN
>
75 static void apply(std::ostream
& os
, vectorN xs
) {
76 constexpr auto N
= hana::size_c
<vectorN::size
>;
79 N
.times
.with_index([&](auto i
) {
81 if (i
!= N
- hana::size_c
<1>) os
<< ", ";
90 template <typename Tag
>
91 struct print_impl
<Tag
, hana::when
<Tag represents some kind of sequence
>> {
92 template <typename Seq
>
93 static void apply(std::ostream
& os
, Seq xs
) {
94 // Some implementation for any sequence
102 std::stringstream ss
;
105 BOOST_HANA_RUNTIME_CHECK(ss
.str() == "[]");
109 std::stringstream ss
;
112 BOOST_HANA_RUNTIME_CHECK(ss
.str() == "[1]");
116 std::stringstream ss
;
117 vector2
<int, char> v2
{1, 'x'};
119 BOOST_HANA_RUNTIME_CHECK(ss
.str() == "[1, x]");
125 void print(std::ostream
& os
, vector0
)
128 template <typename T1
>
129 void print(std::ostream
& os
, vector1
<T1
> v
)
130 { os
<< "[" << v
.t1
<< "]"; }
132 template <typename T1
, typename T2
>
133 void print(std::ostream
& os
, vector2
<T1
, T2
> v
)
134 { os
<< "[" << v
.t1
<< ", " << v
.t2
<< "]"; }
140 namespace preconditions
{
142 template <typename X
>
143 void print(std::ostream
& os
, X x
) {
144 // **** check some precondition ****
146 // The precondition only has to be checked here; implementations
147 // can assume their arguments to always be sane.
149 using Tag
= typename
hana::tag_of
<X
>::type
;
150 print_impl
<Tag
>::apply(os
, x
);
155 namespace function_objects
{
156 //! [function_objects]
157 // Defining a function object is only needed once and implementations do not
158 // have to worry about static initialization and other painful tricks.
160 template <typename X
>
161 void operator()(std::ostream
& os
, X x
) const {
162 using Tag
= typename
hana::tag_of
<X
>::type
;
163 print_impl
<Tag
>::apply(os
, x
);
166 constexpr print_t print
{};
167 //! [function_objects]
169 static_assert(sizeof(print
) || true, "remove unused variable print warning");