summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/hof/example/print.cpp
blob: 0149c870845468589b93d1236ab4784e73cbb237 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/*=============================================================================
    Copyright (c) 2017 Paul Fultz II
    print.cpp
    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/
/*=============================================================================
    Copyright (c) 2016 Paul Fultz II
    print.cpp
    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/

#include "example.h"

using namespace boost::hof;

// ADL Lookup for ranges
namespace adl {

using std::begin;
using std::end;

template<class R>
auto adl_begin(R&& r) BOOST_HOF_RETURNS(begin(r));
template<class R>
auto adl_end(R&& r) BOOST_HOF_RETURNS(end(r));
}

// Iterate over a tuple
BOOST_HOF_STATIC_LAMBDA_FUNCTION(for_each_tuple) = [](const auto& sequence, auto f)
{
    return unpack(proj(f))(sequence);
};

#ifdef _MSC_VER
// On MSVC, trailing decltype doesn't work with generic lambdas, so seperate
// functions can be used instead.
template<class Self, class T>
auto print_with_cout(Self, const T& x) -> decltype(std::cout << x, void())
{
    std::cout << x << std::endl;
}

template<class Self, class T>
auto print_with_range(Self self, const T& range) -> decltype(self(*adl::adl_begin(range)), void())
{
    for(const auto& x:range) self(x);
}

template<class Self, class T>
auto print_with_tuple(Self self, const T& tuple) -> decltype(for_each_tuple(tuple, self), void())
{
    for_each_tuple(tuple, self);
}

// Recursively print everything
BOOST_HOF_STATIC_FUNCTION(simple_print) = fix(first_of(
    BOOST_HOF_LIFT(print_with_cout),
    BOOST_HOF_LIFT(print_with_range),
    BOOST_HOF_LIFT(print_with_tuple)
));
#else
// Recursively print everything
BOOST_HOF_STATIC_LAMBDA_FUNCTION(simple_print) = fix(first_of(
    [](auto, const auto& x) -> decltype(std::cout << x, void())
    {
        std::cout << x << std::endl;
    },
    [](auto self, const auto& range) -> decltype(self(*adl::adl_begin(range)), void())
    {
        for(const auto& x:range) self(x);
    },
    [](auto self, const auto& tuple) -> decltype(for_each_tuple(tuple, self), void())
    {
        for_each_tuple(tuple, self);
    }
));
#endif

// Make print function varidiac
BOOST_HOF_STATIC_LAMBDA_FUNCTION(print) = proj(simple_print);

int main()
{
    print(5, "Hello world");
    print(5);
    std::vector<int> v = { 1, 2, 3, 4 };
    print(v);

    auto t = std::make_tuple(1, 2, 3, 4);
    print(t);

    auto m = std::make_tuple(3, v, t);
    print(m);
}