print.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  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. #include "example.h"
  14. using namespace boost::hof;
  15. // ADL Lookup for ranges
  16. namespace adl {
  17. using std::begin;
  18. using std::end;
  19. template<class R>
  20. auto adl_begin(R&& r) BOOST_HOF_RETURNS(begin(r));
  21. template<class R>
  22. auto adl_end(R&& r) BOOST_HOF_RETURNS(end(r));
  23. }
  24. // Iterate over a tuple
  25. BOOST_HOF_STATIC_LAMBDA_FUNCTION(for_each_tuple) = [](const auto& sequence, auto f)
  26. {
  27. return unpack(proj(f))(sequence);
  28. };
  29. #ifdef _MSC_VER
  30. // On MSVC, trailing decltype doesn't work with generic lambdas, so seperate
  31. // functions can be used instead.
  32. template<class Self, class T>
  33. auto print_with_cout(Self, const T& x) -> decltype(std::cout << x, void())
  34. {
  35. std::cout << x << std::endl;
  36. }
  37. template<class Self, class T>
  38. auto print_with_range(Self self, const T& range) -> decltype(self(*adl::adl_begin(range)), void())
  39. {
  40. for(const auto& x:range) self(x);
  41. }
  42. template<class Self, class T>
  43. auto print_with_tuple(Self self, const T& tuple) -> decltype(for_each_tuple(tuple, self), void())
  44. {
  45. for_each_tuple(tuple, self);
  46. }
  47. // Recursively print everything
  48. BOOST_HOF_STATIC_FUNCTION(simple_print) = fix(first_of(
  49. BOOST_HOF_LIFT(print_with_cout),
  50. BOOST_HOF_LIFT(print_with_range),
  51. BOOST_HOF_LIFT(print_with_tuple)
  52. ));
  53. #else
  54. // Recursively print everything
  55. BOOST_HOF_STATIC_LAMBDA_FUNCTION(simple_print) = fix(first_of(
  56. [](auto, const auto& x) -> decltype(std::cout << x, void())
  57. {
  58. std::cout << x << std::endl;
  59. },
  60. [](auto self, const auto& range) -> decltype(self(*adl::adl_begin(range)), void())
  61. {
  62. for(const auto& x:range) self(x);
  63. },
  64. [](auto self, const auto& tuple) -> decltype(for_each_tuple(tuple, self), void())
  65. {
  66. for_each_tuple(tuple, self);
  67. }
  68. ));
  69. #endif
  70. // Make print function varidiac
  71. BOOST_HOF_STATIC_LAMBDA_FUNCTION(print) = proj(simple_print);
  72. int main()
  73. {
  74. print(5, "Hello world");
  75. print(5);
  76. std::vector<int> v = { 1, 2, 3, 4 };
  77. print(v);
  78. auto t = std::make_tuple(1, 2, 3, 4);
  79. print(t);
  80. auto m = std::make_tuple(3, v, t);
  81. print(m);
  82. }