1 /*============================================================================= 2 Copyright (c) 2017 Paul Fultz II 3 fix.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 #include <boost/hof/fix.hpp> 8 #include <boost/hof/static.hpp> 9 #include <boost/hof/reveal.hpp> 10 #include <boost/hof/result.hpp> 11 #include "test.hpp" 12 13 #include <memory> 14 15 struct factorial_t 16 { 17 template<class Self, class T> operator ()factorial_t18 T operator()(Self s, T x) const noexcept 19 { 20 return x == 0 ? 1 : x * s(x-1); 21 } 22 }; 23 24 struct factorial_constexpr_t 25 { 26 template<class Self, class T> operator ()factorial_constexpr_t27 constexpr T operator()(Self s, T x) const noexcept 28 { 29 return x == 0 ? 1 : x * s(x-1); 30 } 31 }; 32 33 struct factorial_move_t 34 { 35 std::unique_ptr<int> i; factorial_move_tfactorial_move_t36 factorial_move_t() : i(new int(1)) 37 {} 38 template<class Self, class T> operator ()factorial_move_t39 T operator()(const Self& s, T x) const 40 { 41 return x == 0 ? *i : x * s(x-1); 42 } 43 }; 44 45 static constexpr boost::hof::fix_adaptor<factorial_t> factorial = {}; 46 static constexpr boost::hof::fix_adaptor<factorial_constexpr_t> factorial_constexpr = {}; 47 static constexpr boost::hof::static_<boost::hof::fix_adaptor<factorial_move_t> > factorial_move = {}; 48 49 #if BOOST_HOF_HAS_NOEXCEPT_DEDUCTION BOOST_HOF_TEST_CASE()50BOOST_HOF_TEST_CASE() 51 { 52 static_assert(noexcept(factorial(5)), "noexcept fix"); 53 } 54 #endif 55 BOOST_HOF_TEST_CASE()56BOOST_HOF_TEST_CASE() 57 { 58 const int r = factorial(5); 59 BOOST_HOF_TEST_CHECK(r == 5*4*3*2*1); 60 } 61 BOOST_HOF_TEST_CASE()62BOOST_HOF_TEST_CASE() 63 { 64 const int r = boost::hof::reveal(factorial)(5); 65 BOOST_HOF_TEST_CHECK(r == 5*4*3*2*1); 66 } 67 68 #if !BOOST_HOF_NO_EXPRESSION_SFINAE BOOST_HOF_TEST_CASE()69BOOST_HOF_TEST_CASE() 70 { 71 const int r = boost::hof::fix(boost::hof::result<int>(factorial_constexpr_t()))(5); 72 BOOST_HOF_TEST_CHECK(r == 5*4*3*2*1); 73 } 74 BOOST_HOF_TEST_CASE()75BOOST_HOF_TEST_CASE() 76 { 77 const int r = boost::hof::result<int>(factorial_constexpr)(5); 78 BOOST_HOF_TEST_CHECK(r == 5*4*3*2*1); 79 } BOOST_HOF_TEST_CASE()80BOOST_HOF_TEST_CASE() 81 { 82 BOOST_HOF_STATIC_TEST_CHECK(boost::hof::fix(boost::hof::result<int>(factorial_constexpr_t()))(5) == 5*4*3*2*1); 83 BOOST_HOF_STATIC_TEST_CHECK(boost::hof::result<int>(factorial_constexpr)(5) == 5*4*3*2*1); 84 } 85 #endif BOOST_HOF_TEST_CASE()86BOOST_HOF_TEST_CASE() 87 { 88 #if BOOST_HOF_HAS_GENERIC_LAMBDA 89 auto factorial_ = boost::hof::fix([](auto s, auto x) -> decltype(x) { return x == 0 ? 1 : x * s(x-1); }); 90 int r = boost::hof::result<int>(factorial_)(5); 91 BOOST_HOF_TEST_CHECK(r == 5*4*3*2*1); 92 #endif 93 } 94 BOOST_HOF_TEST_CASE()95BOOST_HOF_TEST_CASE() 96 { 97 const int r = factorial_move(5); 98 BOOST_HOF_TEST_CHECK(r == 5*4*3*2*1); 99 BOOST_HOF_TEST_CHECK(boost::hof::fix(factorial_move_t())(5) == 5*4*3*2*1); 100 } 101