Blame view

3rdparty/boost_1_81_0/libs/hof/example/sequence.cpp 3.85 KB
73ef4ff3   Hu Chunming   提交三方库
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
  /*=============================================================================
      Copyright (c) 2017 Paul Fultz II
      sequence.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"
  #include <tuple>
  
  using namespace boost::hof;
  
  // Transform each element of a tuple by calling f
  BOOST_HOF_STATIC_LAMBDA_FUNCTION(tuple_transform) = [](auto&& sequence, auto f)
  {
      return unpack(proj(f, construct<std::tuple>()))(std::forward<decltype(sequence)>(sequence));
  };
  // Call f on each element of tuple
  BOOST_HOF_STATIC_LAMBDA_FUNCTION(tuple_for_each) = [](auto&& sequence, auto f)
  {
      return unpack(proj(f))(std::forward<decltype(sequence)>(sequence));
  };
  // Fold over tuple using a f as the binary operator
  BOOST_HOF_STATIC_LAMBDA_FUNCTION(tuple_fold) = [](auto&& sequence, auto f)
  {
      return unpack(fold(f))(std::forward<decltype(sequence)>(sequence));
  };
  // Concat multiple tuples
  BOOST_HOF_STATIC_FUNCTION(tuple_cat) = unpack(construct<std::tuple>());
  // Join a tuple of tuples into just a tuple
  BOOST_HOF_STATIC_FUNCTION(tuple_join) = unpack(tuple_cat);
  // Filter elements in a tuple using a predicate
  BOOST_HOF_STATIC_LAMBDA_FUNCTION(tuple_filter) = [](auto&& sequence, auto predicate)
  {
      return compose(tuple_join, tuple_transform)(
          std::forward<decltype(sequence)>(sequence),
          [&](auto&& x)
          {
              return first_of(
                  if_(predicate(std::forward<decltype(x)>(x)))(pack),
                  always(pack())
              )(std::forward<decltype(x)>(x));
          }
      );
  };
  // Zip two tuples together
  BOOST_HOF_STATIC_LAMBDA_FUNCTION(tuple_zip_with) = [](auto&& sequence1, auto&& sequence2, auto f)
  {
      auto&& functions = tuple_transform(
          std::forward<decltype(sequence1)>(sequence1),
          [&](auto&& x)
          {
              return [&](auto&& y)
              {
                  return f(std::forward<decltype(x)>(x), std::forward<decltype(y)>(y));
              };
          }
      );
      auto combined = unpack(capture(construct<std::tuple>())(combine))(functions);
      return unpack(combined)(std::forward<decltype(sequence2)>(sequence2));
  };
  // Dot product of a tuple
  BOOST_HOF_STATIC_LAMBDA_FUNCTION(tuple_dot) = [](auto&& a, auto&& b)
  {
      auto product = tuple_zip_with(a, b, [](auto x, auto y) { return x*y; });
      return tuple_fold(product, [](auto x, auto y) { return x+y; });
  };
  
  void run_each()
  {
      auto t = std::make_tuple(1, 2);
      tuple_for_each(t, [](int i) { std::cout << i << std::endl; });
  }
  
  void run_transform()
  {
      auto t = std::make_tuple(1, 2);
      auto r = tuple_transform(t, [](int i) { return i*i; });
      assert(r == std::make_tuple(1, 4));
      (void)r;
  }
  
  void run_filter()
  {
      auto t = std::make_tuple(1, 2, 'x', 3);
      auto r = tuple_filter(t, [](auto x) { return std::is_same<int, decltype(x)>(); });
      assert(r == std::make_tuple(1, 2, 3));
      (void)r;
  }
  
  void run_zip()
  {
      auto t1 = std::make_tuple(1, 2);
      auto t2 = std::make_tuple(3, 4);
      auto p = tuple_zip_with(t1, t2, [](auto x, auto y) { return x*y; });
      int r = tuple_fold(p, [](auto x, auto y) { return x+y; });
      assert(r == (1*3 + 4*2));
      (void)r;
  }
  
  void run_dot()
  {
      auto t1 = std::make_tuple(1, 2);
      auto t2 = std::make_tuple(3, 4);
      int r = tuple_dot(t1, t2);
      assert(r == (1*3 + 4*2));
      (void)r;
  }
  
  int main() 
  {
      run_transform();
      run_filter();
      run_zip();
  }