1 /*=============================================================================
2 Copyright (c) 2017 Paul Fultz II
3 print.cpp
4 Distributed under the Boost Software License, Version 1.0. (See accompanying
5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 ==============================================================================*/
7 /*=============================================================================
8 Copyright (c) 2016 Paul Fultz II
9 print.cpp
10 Distributed under the Boost Software License, Version 1.0. (See accompanying
11 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
12 ==============================================================================*/
13
14 #include "example.h"
15
16 using namespace boost::hof;
17
18 // ADL Lookup for ranges
19 namespace adl {
20
21 using std::begin;
22 using std::end;
23
24 template<class R>
25 auto adl_begin(R&& r) BOOST_HOF_RETURNS(begin(r));
26 template<class R>
27 auto adl_end(R&& r) BOOST_HOF_RETURNS(end(r));
28 }
29
30 // Iterate over a tuple
31 BOOST_HOF_STATIC_LAMBDA_FUNCTION(for_each_tuple) = [](const auto& sequence, auto f)
__anon4c4c58a00102(const auto& sequence, auto f) 32 {
33 return unpack(proj(f))(sequence);
34 };
35
36 #ifdef _MSC_VER
37 // On MSVC, trailing decltype doesn't work with generic lambdas, so seperate
38 // functions can be used instead.
39 template<class Self, class T>
print_with_cout(Self,const T & x)40 auto print_with_cout(Self, const T& x) -> decltype(std::cout << x, void())
41 {
42 std::cout << x << std::endl;
43 }
44
45 template<class Self, class T>
print_with_range(Self self,const T & range)46 auto print_with_range(Self self, const T& range) -> decltype(self(*adl::adl_begin(range)), void())
47 {
48 for(const auto& x:range) self(x);
49 }
50
51 template<class Self, class T>
print_with_tuple(Self self,const T & tuple)52 auto print_with_tuple(Self self, const T& tuple) -> decltype(for_each_tuple(tuple, self), void())
53 {
54 for_each_tuple(tuple, self);
55 }
56
57 // Recursively print everything
58 BOOST_HOF_STATIC_FUNCTION(simple_print) = fix(first_of(
59 BOOST_HOF_LIFT(print_with_cout),
60 BOOST_HOF_LIFT(print_with_range),
61 BOOST_HOF_LIFT(print_with_tuple)
62 ));
63 #else
64 // Recursively print everything
65 BOOST_HOF_STATIC_LAMBDA_FUNCTION(simple_print) = fix(first_of(
66 [](auto, const auto& x) -> decltype(std::cout << x, void())
67 {
68 std::cout << x << std::endl;
69 },
70 [](auto self, const auto& range) -> decltype(self(*adl::adl_begin(range)), void())
71 {
72 for(const auto& x:range) self(x);
73 },
74 [](auto self, const auto& tuple) -> decltype(for_each_tuple(tuple, self), void())
75 {
76 for_each_tuple(tuple, self);
77 }
78 ));
79 #endif
80
81 // Make print function varidiac
82 BOOST_HOF_STATIC_LAMBDA_FUNCTION(print) = proj(simple_print);
83
main()84 int main()
85 {
86 print(5, "Hello world");
87 print(5);
88 std::vector<int> v = { 1, 2, 3, 4 };
89 print(v);
90
91 auto t = std::make_tuple(1, 2, 3, 4);
92 print(t);
93
94 auto m = std::make_tuple(3, v, t);
95 print(m);
96 }
97