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