├── .gitattributes ├── .gitignore ├── README.md ├── arity ├── arity_increasing.hpp ├── arity_matches.hpp ├── function_operator_exists.hpp ├── function_traits.hpp └── tuple_arity.hpp ├── composition └── wrap_fn.hpp ├── fn.hpp ├── fn ├── apply_arguments.hpp ├── apply_tuple_to_function.hpp ├── invoke.hpp └── process.hpp ├── list └── immutable_list.hpp ├── main.cpp ├── monads ├── boxed_collection.hpp ├── get_first_box_argument_index.hpp ├── isabox.hpp └── maybe.hpp ├── operators └── operators.hpp ├── placeholders ├── add_anonymous_placeholder_support.hpp └── placeholder.hpp ├── std_wrappers.hpp ├── switch.hpp └── util ├── arg_category.hpp ├── arg_positions.hpp ├── arg_start_indices.hpp ├── fn_fwd.hpp ├── get_conditionally.hpp ├── int_list.hpp ├── pointer_to_member.hpp └── real_arguments_before_i.hpp /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # VS files 21 | *.opensdf 22 | *.sdf 23 | *.sln 24 | *.suo 25 | *.vcxproj 26 | *.filters 27 | *.exe 28 | *.ilk 29 | *.log 30 | *.pdb 31 | *.obj 32 | *.idb 33 | *.tlog 34 | *.lastbuildstate 35 | 36 | Debug/ 37 | Release/ 38 | fn.sln.ide/ 39 | 40 | *.jrs 41 | *.chk 42 | *.ide 43 | 44 | # ========================= 45 | # Operating System Files 46 | # ========================= 47 | 48 | # OSX 49 | # ========================= 50 | 51 | .DS_Store 52 | .AppleDouble 53 | .LSOverride 54 | 55 | # Thumbnails 56 | ._* 57 | 58 | # Files that might appear on external disk 59 | .Spotlight-V100 60 | .Trashes 61 | 62 | # Directories potentially created on remote AFP share 63 | .AppleDB 64 | .AppleDesktop 65 | Network Trash Folder 66 | Temporary Items 67 | .apdisk 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ###Support for Curry and Function Composition in C++ 2 | 3 | ####What is this? 4 | Functional programming languages such as Haskell has features such as currying, function composition etc. This library is an attempt to bring such features into C++ using modern techniques available in C++14. 5 | 6 | ####Usage 7 | This is a header only library. Just include the file fn.hpp in your source code. The main function 'fn' and the related components are available inside the namespace 'curry' 8 | 9 | ####Tools needed 10 | This project uses C++ 14 language features. It is successfully compiled under MSVC 2015, Clang 3.6.0 and GCC 4.92 (using the std=c++1y switch) 11 | 12 | ####Notes 13 | #####1. Enabling currying - Global, Member, Functor and Lambda Functions as well as Member Variables. 14 | 15 | ```cpp 16 | auto f1 = fn(foo); //Global function. 17 | auto f2 = fn(&A::bar); //Member function of a class. 18 | auto f3 = fn(B()); //Functor 19 | 20 | auto lambda = [](auto arg1) { 21 | return arg1*10.0; 22 | }; 23 | auto f4 = fn(lambda); //Lambda. Anonymous lambda works too. 24 | 25 | //Binding a member variable. Creates a one argument function. 26 | auto f5 = fn(&std::pair::second); 27 | ``` 28 | 29 | #####2. Partial application of Functions 30 | 31 | ```cpp 32 | //foo is a function that takes four arguments. Two are partially applied here. 33 | auto partially_applied = fn(foo, arg1, arg2); 34 | 35 | //The remaining two arguments are supplied here. Calls foo(arg1, arg2, arg3, arg4); 36 | partially_applied(arg3, arg4); 37 | ``` 38 | 39 | #####3. Currying of Functions 40 | 41 | ```cpp 42 | //foo is a function that takes four arguments. 43 | auto curried_function = fn(foo); 44 | 45 | auto one_arg_applied = curried_function(arg1); 46 | auto some_more_applied = one_arg_applied(arg2, arg3); 47 | auto the_rest_applied_and_invoked = some_more_applied(arg4); 48 | ``` 49 | 50 | #####4. Placeholders 51 | 52 | ```cpp 53 | auto f1 = fn(foo); //foo takes four arguments. 54 | auto f2 = f1(_4, _1, _3, _2); //Reorder arguments. 55 | auto f3 = f2(arg1, arg2, arg3, arg4); //Calls foo(arg4, arg1, arg3, arg2) 56 | ``` 57 | 58 | #####5. Anonymous Placeholders 59 | 60 | ```cpp 61 | auto f1 = fn(foo); //foo takes four arguments. 62 | auto f2 = f1(_, arg1, arg2, _); //Some arguments are applied. It waits for more. 63 | 64 | //Remaining arguments provided. Invokes foo(arg3, arg1, arg2, arg4) 65 | auto f3 = f2(arg3, arg4); 66 | ``` 67 | 68 | #####6. Function Composition ( Using composition operator '*' ) 69 | 70 | ```cpp 71 | //foo takes four arguments 72 | auto f1 = fn(foo); 73 | 74 | //bar is a function that takes two arguments. It is composed in. 75 | auto f2 = f1(arg1, _, arg2, arg3) * bar; 76 | 77 | //Calls foo(arg1, bar(arg4, arg5), arg2, arg3) 78 | auto f3 = f2(arg4, arg5); 79 | ``` 80 | 81 | #####7. With Each ( Binding containers to values just like Monads and Applicative Functors ) 82 | 83 | ```cpp 84 | int add_three_numbers(int a, int b, int c) { 85 | return a + b + c; 86 | } 87 | 88 | std::vector v1 = { 19,17,21 }; 89 | std::vector v2 = { 23,49 }; 90 | std::vector v3 = { 7, 13 }; 91 | 92 | auto adder = fn(add_three_numbers); 93 | auto result = adder(with_each(v1), with_each(v2), with_each(v3)); 94 | 95 | //result will be a vector with 12 values {49, 55, 75, 81, 47, 53, 73, 79, 51, 57, 77, 83} 96 | ``` 97 | 98 | 99 | #####8. Maybe 100 | 101 | ```cpp 102 | int add_three_numbers(int a, int b, int c) { 103 | return a + b + c; 104 | } 105 | 106 | auto value1 = maybe(10); 107 | auto value2 = maybe(20); 108 | auto value3 = maybe(30); 109 | 110 | auto adder = fn(add_three_numbers); 111 | auto result = adder(value1, value2, value3); 112 | 113 | //result will be maybe_t(60) 114 | 115 | auto value4 = maybe(10); 116 | auto value5 = maybe_t(); 117 | auto value6 = maybe(30); 118 | 119 | auto adder = fn(add_three_numbers); 120 | auto result = adder(value4, value5, value6); 121 | 122 | //result will be maybe_t() which is empty since value5 is empty 123 | 124 | ``` 125 | 126 | #####9. Pipe Operator '|' 127 | 128 | ```cpp 129 | auto print = fn([](const std::string& str) { std::cout << str << std::endl; }); 130 | auto world = _ + std::string("world"); 131 | "hello " | world | print; //prints "hello world" to the console 132 | ``` 133 | 134 | #####10. On the fly function creation with placeholders 135 | 136 | ```cpp 137 | auto times10 = _ * 10; 138 | auto result1 = times10(4.2); //result1 will be 42.0 139 | 140 | auto greaterThan42 = 42 < _; 141 | auto result2 = 32 | greaterThan42; //result2 will be false 142 | ``` 143 | 144 | #####11. Immutable list (Code inspired by Bartosz Milewski's SimpleList) 145 | 146 | ```cpp 147 | auto lst = make_list({1,2,3,4,5,6,7,8,9}); 148 | 149 | auto lst2 = tail(lst); //lst2 will be [2,3,4,5,6,7,8,9] 150 | auto val = head(lst2); //val will be 2 151 | auto lst3 = 1 + lst2; //lst3 will be [1,2,3,4,5,6,7,8,9] 152 | 153 | auto is_lst_empty = empty(lst); //result will be false 154 | 155 | auto second_item_of_lst3 = head(tail(lst3)); //result will be 2 156 | ``` 157 | 158 | #####12. Higher Order Functions 159 | 160 | ```cpp 161 | auto lst = make_list({1,2,3,4,5,6,7,8,9}); 162 | 163 | auto square = fmap(_1*_1); //on the fly function creation with curried fmap application 164 | auto fmap_result = square(lst); //result will be [1,2,9,16,25,36,49,64,81] 165 | 166 | auto sum = foldl(_+_, 0); //curried foldl application 167 | auto product = foldr(_*_, 1); //curried foldr application 168 | 169 | auto sum_result = sum(lst); //result will be 45 170 | std::cout << sum_result << std::endl; 171 | 172 | auto product_result = lst | product; //result will be 362880 173 | std::cout << product_result << std::endl; 174 | ``` 175 | -------------------------------------------------------------------------------- /arity/arity_increasing.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _ARITY_INCREASING_HPP_ 2 | #define _ARITY_INCREASING_HPP_ 3 | 4 | #include "..\placeholders\placeholder.hpp" 5 | #include "..\util\fn_fwd.hpp" 6 | 7 | namespace curry { 8 | 9 | template 10 | struct arity_increasing; 11 | 12 | template 13 | struct arity_increasing { 14 | static const bool value = arity_increasing::value; 15 | }; 16 | 17 | template<> 18 | struct arity_increasing<> { 19 | static const bool value = false; 20 | }; 21 | 22 | template 23 | struct arity_increasing, Rest...> { 24 | static const bool value = true; 25 | }; 26 | 27 | template 28 | struct arity_increasing, Rest...> { 29 | static const bool value = true; 30 | }; 31 | 32 | template 33 | struct arity_increasing&, Rest...> { 34 | static const bool value = true; 35 | }; 36 | 37 | } 38 | 39 | #endif//_ARITY_INCREASING_HPP_ 40 | -------------------------------------------------------------------------------- /arity/arity_matches.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _ARITY_MATCHES_HPP_ 2 | #define _ARITY_MATCHES_HPP_ 3 | 4 | #include "..\arity\tuple_arity.hpp" 5 | #include "..\arity\arity_increasing.hpp" 6 | 7 | namespace curry { 8 | 9 | template 10 | struct arity_matches { 11 | static const bool value = !arity_increasing::value && (tuple_arity::value == sizeof...(A)); 12 | }; 13 | 14 | } 15 | 16 | #endif//_ARITY_MATCHES_HPP_ 17 | -------------------------------------------------------------------------------- /arity/function_operator_exists.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _FUNCTION_OPERATOR_EXISTS_HPP_ 2 | #define _FUNCTION_OPERATOR_EXISTS_HPP_ 3 | 4 | #include 5 | 6 | namespace curry { 7 | 8 | namespace detail { 9 | 10 | template 11 | struct sfinae_true : std::true_type { 12 | }; 13 | 14 | template 15 | static sfinae_true().operator()))> 16 | function_operator_exists(int); 17 | 18 | template 19 | static std::false_type 20 | function_operator_exists(long); 21 | 22 | template 23 | struct function_operator_test : decltype(function_operator_exists(0)) { 24 | }; 25 | 26 | } 27 | 28 | template 29 | struct function_operator_exists : detail::function_operator_test::type { 30 | }; 31 | 32 | } 33 | 34 | #endif//_FUNCTION_OPERATOR_EXISTS_HPP_ -------------------------------------------------------------------------------- /arity/function_traits.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _FUNCTION_TRAITS_HPP_ 2 | #define _FUNCTION_TRAITS_HPP_ 3 | 4 | #include "..\arity\function_operator_exists.hpp" 5 | #include "..\arity\tuple_arity.hpp" 6 | #include "..\util\fn_fwd.hpp" 7 | #include 8 | 9 | namespace curry { 10 | 11 | template 12 | struct function_traits_helper { 13 | static const bool is_function = b; 14 | static const int arity = a; 15 | }; 16 | 17 | template 18 | struct function_traits_impl 19 | : function_traits_helper { 20 | }; 21 | 22 | template 23 | struct function_traits_impl 24 | : function_traits_impl::operator())> { 25 | static const int arity = function_traits_impl::operator())>::arity - 1; 26 | }; 27 | 28 | template 29 | struct function_traits_impl> 30 | : function_traits_helper{ 31 | }; 32 | 33 | template 34 | struct function_traits_impl 35 | : function_traits_helper { 36 | }; 37 | 38 | template 39 | struct function_traits_impl 40 | : function_traits_helper { 41 | }; 42 | 43 | template 44 | struct function_traits_impl 45 | : function_traits_helper { 46 | }; 47 | 48 | template 49 | struct function_traits_impl 50 | : function_traits_helper { 51 | }; 52 | 53 | template 54 | struct function_traits_impl 55 | : function_traits_helper { 56 | }; 57 | 58 | template 59 | struct function_traits_impl> 60 | : function_traits_helper::value> { 61 | }; 62 | 63 | template 64 | struct function_traits 65 | : function_traits_impl::value, std::decay_t> { 66 | }; 67 | 68 | } 69 | 70 | #endif//_FUNCTION_TRAITS_HPP_ 71 | -------------------------------------------------------------------------------- /arity/tuple_arity.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _TUPLE_ARITY_HPP_ 2 | #define _TUPLE_ARITY_HPP_ 3 | 4 | #include "..\util\fn_fwd.hpp" 5 | #include "..\placeholders\placeholder.hpp" 6 | #include 7 | 8 | namespace curry { 9 | 10 | template 11 | struct tuple_arity { 12 | static const int value = function_traits::arity; 13 | }; 14 | 15 | template 16 | struct tuple_arity> { 17 | static const int value = tuple_arity>::value; 18 | }; 19 | 20 | template 21 | struct tuple_arity, Rest...>> { 22 | static const int rest_arity = tuple_arity>::value; 23 | static const int value = (I > rest_arity) ? I : rest_arity; 24 | }; 25 | 26 | template 27 | struct tuple_arity, F, A...>, Rest...>> { 28 | static const int this_arity = (I - 1) + function_traits::arity - sizeof...(A); 29 | static const int rest_arity = tuple_arity>::value; 30 | static const int value = this_arity + rest_arity; 31 | }; 32 | 33 | template 34 | struct tuple_arity, Rest...>> { 35 | static const int this_arity = 0; 36 | static const int rest_arity = tuple_arity>::value; 37 | static const int value = (this_arity > rest_arity) ? this_arity : rest_arity; 38 | }; 39 | 40 | template<> 41 | struct tuple_arity> { 42 | static const int value = 0; 43 | }; 44 | 45 | } 46 | 47 | #endif//_TUPLE_ARITY_HPP_ 48 | -------------------------------------------------------------------------------- /composition/wrap_fn.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _WRAP_FN_HPP_ 2 | #define _WRAP_FN_HPP_ 3 | 4 | #include "..\util\fn_fwd.hpp" 5 | #include "..\arity\function_operator_exists.hpp" 6 | #include 7 | 8 | namespace curry { 9 | 10 | template 11 | typename std::enable_if::is_function, cfn_t>::type wrap_fn(F&& f) { 12 | return cfn_t(std::forward(f)); 13 | } 14 | 15 | template 16 | typename std::enable_if::is_function, T&&>::type wrap_fn(T&& t) { 17 | return std::forward(t); 18 | } 19 | 20 | } 21 | 22 | #endif//_WRAP_FN_HPP_ -------------------------------------------------------------------------------- /fn.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _FN_HPP_ 2 | #define _FN_HPP_ 3 | 4 | #include "fn\process.hpp" 5 | #include "arity\function_traits.hpp" 6 | #include "util\fn_fwd.hpp" 7 | #include "util\arg_positions.hpp" 8 | #include "util\pointer_to_member.hpp" 9 | #include "composition\wrap_fn.hpp" 10 | #include 11 | #include 12 | 13 | namespace curry { 14 | 15 | template 16 | struct fn_t { 17 | 18 | fn_t(F&& f) 19 | : _f(std::move(f)) { 20 | } 21 | 22 | fn_t(F&& f, T&& t) 23 | : _f(std::move(f)), _t(std::move(t)) { 24 | } 25 | 26 | template 27 | CONSTEXPR decltype(auto) operator()(A&&... a) const& { 28 | return process(F(_f), T(_t), std::forward(a)...); 29 | } 30 | 31 | template 32 | decltype(auto) operator()(A&&... a) && { 33 | return process(std::forward(_f), std::forward(_t), std::forward(a)...); 34 | } 35 | 36 | template 37 | CONSTEXPR decltype(auto) compose(A&&... a) const& { 38 | return process(F(_f), T(_t), wrap_fn(std::forward(a))...); 39 | } 40 | 41 | template 42 | decltype(auto) compose(A&&... a) && { 43 | return process(std::forward(_f), std::forward(_t), wrap_fn(std::forward(a))...); 44 | } 45 | 46 | private: 47 | F _f; 48 | T _t; 49 | }; 50 | 51 | template 52 | CONSTEXPR decltype(auto) fn(F&& f) { 53 | return fn_t::arity>::type>(std::forward(f)); 54 | } 55 | 56 | template 57 | CONSTEXPR decltype(auto) fn(F&& f) { 58 | return fn_t::type>(std::forward(f)); 59 | } 60 | 61 | template 62 | CONSTEXPR decltype(auto) fn(F&& f, A&& a, Rest&& ...rest) { 63 | return fn_t::arity>::type>(std::forward(f))(std::forward(a), std::forward(rest)...); 64 | } 65 | 66 | template 67 | CONSTEXPR decltype(auto) fn(R T::* const f, A&& ...a) { 68 | using F = pointer_to_member; 69 | return fn(F(f), std::forward(a)...); 70 | } 71 | 72 | template 73 | struct cfn_t { 74 | cfn_t(F&& f) : _f(std::forward(f)) { 75 | } 76 | F&& _f; 77 | }; 78 | 79 | } 80 | 81 | #endif//_FN_HPP_ 82 | -------------------------------------------------------------------------------- /fn/apply_arguments.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _APPLY_ARGUMENTS_HPP_ 2 | #define _APPLY_ARGUMENTS_HPP_ 3 | 4 | #include "..\util\get_conditionally.hpp" 5 | #include "..\util\arg_start_indices.hpp" 6 | #include "..\util\int_list.hpp" 7 | #include 8 | 9 | namespace curry { 10 | 11 | template 12 | CONSTEXPR decltype(auto) apply_arguments(int_list, T&& t, A&& a) { 13 | return std::make_tuple(get_conditionally::type> 15 | > 16 | (arg_category(t))>(), 17 | std::get(std::forward(t)), 18 | std::forward(a) 19 | )... 20 | ); 21 | } 22 | 23 | } 24 | 25 | #endif//_APPLY_ARGUMENTS_HPP_ -------------------------------------------------------------------------------- /fn/apply_tuple_to_function.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _APPLY_TUPLE_TO_FUNCTION_HPP_ 2 | #define _APPLY_TUPLE_TO_FUNCTION_HPP_ 3 | 4 | #include "..\util\fn_fwd.hpp" 5 | #include "..\util\int_list.hpp" 6 | #include "..\placeholders\placeholder.hpp" 7 | #include "..\monads\isabox.hpp" 8 | #include 9 | #include 10 | 11 | namespace curry { 12 | 13 | template 14 | CONSTEXPR decltype(auto) get_value(A&& a) { 15 | return std::forward(a); 16 | } 17 | 18 | template 19 | CONSTEXPR decltype(auto) get_value_impl(int_list, F&& f, A&& a) { 20 | return f(std::get(std::forward(a))...); 21 | } 22 | 23 | template 24 | CONSTEXPR decltype(auto) get_value(std::tuple&& a) { 25 | return get_value_impl(typename make_int_list::type(), std::get<0>(std::forward>(a)), std::forward>(a)); 26 | } 27 | 28 | template 29 | CONSTEXPR decltype(auto) selective_get(std::integral_constant, std::integral_constant, T&& t) { 30 | return std::get(std::forward(t)); 31 | } 32 | 33 | template 34 | CONSTEXPR decltype(auto) selective_get(std::integral_constant, std::integral_constant, T&& t) { 35 | return ph<1>(); 36 | } 37 | 38 | template 39 | CONSTEXPR decltype(auto) apply_tuple_to_function(std::integral_constant selected_index, int_list, F&& f, T&& t) { 40 | using boxtype = std::decay_t(std::forward(t)))>; 41 | return isabox::box_map(std::get(std::forward(t)), fn(f)(get_value(selective_get(std::integral_constant(), selected_index, std::forward(t)))...)); 42 | } 43 | 44 | template 45 | CONSTEXPR decltype(auto) apply_tuple_to_function(std::integral_constant selected_index, int_list, fn_t&& f, T2&& t) { 46 | using boxtype = std::decay_t(std::forward(t)))>; 47 | return isabox::box_map(std::get(std::forward(t)), f(get_value(selective_get(std::integral_constant(), selected_index, std::forward(t)))...)); 48 | } 49 | 50 | template 51 | CONSTEXPR decltype(auto) apply_tuple_to_function(std::integral_constant, int_list, F&& f, T&& t) { 52 | return f(get_value(std::get(std::forward(t)))...); 53 | } 54 | 55 | template 56 | CONSTEXPR decltype(auto) apply_tuple_to_function(std::integral_constant, int_list, fn_t&& f, T2&& t) { 57 | return f(get_value(std::get(std::forward(t)))...); 58 | } 59 | 60 | } 61 | 62 | #endif//_APPLY_TUPLE_TO_FUNCTION_HPP_ 63 | -------------------------------------------------------------------------------- /fn/invoke.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _INVOKE_HPP_ 2 | #define _INVOKE_HPP_ 3 | 4 | #include "..\fn\apply_tuple_to_function.hpp" 5 | #include "..\monads\get_first_box_argument_index.hpp" 6 | #include "..\util\fn_fwd.hpp" 7 | #include "..\util\int_list.hpp" 8 | #include 9 | 10 | namespace curry { 11 | 12 | template 13 | CONSTEXPR decltype(auto) invoke(F&& f, std::false_type, T&& t) { 14 | return fn(fn_t(std::forward(f), std::forward(t))); 15 | } 16 | 17 | template 18 | CONSTEXPR decltype(auto) invoke(F&& f, std::true_type, T&& t) { 19 | return apply_tuple_to_function(std::integral_constant::value>(), indices_for(), std::forward(f), std::forward(t)); 20 | } 21 | 22 | } 23 | 24 | #endif//_INVOKE_HPP_ 25 | -------------------------------------------------------------------------------- /fn/process.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _PROCESS_HPP_ 2 | #define _PROCESS_HPP_ 3 | 4 | #include "..\fn\invoke.hpp" 5 | #include "..\fn\apply_arguments.hpp" 6 | #include "..\arity\arity_matches.hpp" 7 | #include "..\placeholders\add_anonymous_placeholder_support.hpp" 8 | #include 9 | #include 10 | 11 | namespace curry { 12 | 13 | template 14 | CONSTEXPR decltype(auto) process(F&& f, T&& t, A&& ...a) { 15 | return invoke(std::forward(f), std::integral_constant::value>(), apply_arguments(indices_for(), std::forward(t), add_anonymous_placeholder_support(std::forward_as_tuple(std::forward(a)...)))); 16 | } 17 | 18 | } 19 | 20 | #endif//_PROCESS_HPP_ 21 | -------------------------------------------------------------------------------- /list/immutable_list.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _IMMUTABLE_LIST_HPP_ 2 | #define _IMMUTABLE_LIST_HPP_ 3 | 4 | #include "..\arity\function_traits.hpp" 5 | #include "..\util\fn_fwd.hpp" 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace curry { 14 | 15 | template 16 | struct immutable_list { 17 | struct immutable_list_item { 18 | immutable_list_item(T v, std::shared_ptr t) : _val(v), _next(t) {} 19 | T _val; 20 | std::shared_ptr _next; 21 | }; 22 | friend immutable_list_item; 23 | explicit immutable_list(std::shared_ptr immutable_list_items) : _head(immutable_list_items) {} 24 | 25 | immutable_list() : _head(nullptr) {} 26 | immutable_list(T v, immutable_list t) : _head(new immutable_list_item(v, t._head)) {} 27 | immutable_list(std::initializer_list init) : _head(nullptr) { 28 | using Iter = decltype(init.begin()); 29 | auto rev_beg = std::reverse_iterator(init.end()); 30 | auto rev_end = std::reverse_iterator(init.begin()); 31 | //rbegin, rend not supported by clang yet 32 | //for (auto it = std::rbegin(init); it != std::rend(init); ++it) { 33 | for (auto it = rev_beg; it != rev_end; ++it) { 34 | _head = std::shared_ptr(new immutable_list_item(*it, _head)); 35 | } 36 | } 37 | 38 | std::shared_ptr _head; 39 | }; 40 | 41 | template 42 | auto make_list() { 43 | return immutable_list(); 44 | } 45 | 46 | template 47 | auto make_list(std::initializer_list init) { 48 | return immutable_list(init); 49 | } 50 | 51 | struct empty_impl { 52 | template 53 | auto operator()(immutable_list lst) const { 54 | return !lst._head.get(); 55 | } 56 | }; 57 | template<> 58 | struct function_traits { 59 | static const bool is_function = true; 60 | static const int arity = 1; 61 | }; 62 | auto empty = fn(empty_impl()); 63 | 64 | struct head_impl { 65 | template 66 | auto operator()(immutable_list lst) const { 67 | assert(!empty(lst)); 68 | return (lst._head)->_val; 69 | } 70 | }; 71 | template<> 72 | struct function_traits { 73 | static const bool is_function = true; 74 | static const int arity = 1; 75 | }; 76 | auto head = fn(head_impl()); 77 | 78 | struct tail_impl { 79 | template 80 | auto operator()(immutable_list lst) const { 81 | assert(!empty(lst)); 82 | return immutable_list(lst._head->_next); 83 | } 84 | }; 85 | template<> 86 | struct function_traits { 87 | static const bool is_function = true; 88 | static const int arity = 1; 89 | }; 90 | auto tail = fn(tail_impl()); 91 | 92 | template 93 | auto operator+(T v, immutable_list lst) { 94 | return immutable_list(std::move(v), lst); 95 | } 96 | 97 | template 98 | auto operator+(immutable_list a, immutable_list b) { 99 | if (empty(a)) { 100 | return b; 101 | } 102 | return immutable_list(head(a), tail(a) + b); 103 | } 104 | 105 | struct fmap_impl { 106 | template 107 | auto operator()(F f, immutable_list lst) const 108 | -> immutable_list()))> { 109 | using U = decltype(f(std::declval())); 110 | static_assert(std::is_convertible>::value, "fmap requires a function type U(T)"); 111 | if (empty(lst)) { 112 | return immutable_list(); 113 | } 114 | else { 115 | return immutable_list(f(head(lst)), fmap_impl()(f, tail(lst))); 116 | } 117 | } 118 | }; 119 | template<> 120 | struct function_traits { 121 | static const bool is_function = true; 122 | static const int arity = 2; 123 | }; 124 | auto fmap = fn(fmap_impl()); 125 | 126 | struct filter_impl { 127 | template 128 | immutable_list operator()(P p, immutable_list lst) const { 129 | if (empty(lst)) { 130 | return immutable_list(); 131 | } 132 | if (p(head(lst))) { 133 | return immutable_list(head(lst), filter_impl()(p, tail(lst))); 134 | } 135 | else { 136 | return filter(p, tail(lst)); 137 | } 138 | } 139 | }; 140 | template<> 141 | struct function_traits { 142 | static const bool is_function = true; 143 | static const int arity = 2; 144 | }; 145 | auto filter = fn(filter_impl()); 146 | 147 | struct foldr_impl { 148 | template 149 | U operator()(F f, U acc, immutable_list lst) const { 150 | if (empty(lst)) { 151 | return acc; 152 | } 153 | else { 154 | return f(head(lst), foldr_impl()(f, acc, tail(lst))); 155 | } 156 | } 157 | template 158 | U operator()(F f, U acc, Container c) const { 159 | //TODO: should iterate in reverse order - later 160 | for (const auto& i : c) { 161 | acc = f(acc, i); 162 | } 163 | return acc; 164 | } 165 | }; 166 | template<> 167 | struct function_traits { 168 | static const bool is_function = true; 169 | static const int arity = 3; 170 | }; 171 | auto foldr = fn(foldr_impl()); 172 | 173 | struct foldl_impl { 174 | template 175 | U operator()(F f, U acc, immutable_list lst) const { 176 | if (empty(lst)) { 177 | return acc; 178 | } 179 | else { 180 | return foldl_impl()(f, f(acc, head(lst)), tail(lst)); 181 | } 182 | } 183 | template 184 | U operator()(F f, U acc, std::vector c) const { 185 | for (const auto& i : c) { 186 | acc = f(acc, i); 187 | } 188 | return acc; 189 | } 190 | }; 191 | template<> 192 | struct function_traits { 193 | static const bool is_function = true; 194 | static const int arity = 3; 195 | }; 196 | auto foldl = fn(foldl_impl()); 197 | 198 | //struct for_each_impl { 199 | // template 200 | // void operator()(immutable_list lst, F f) const { 201 | // using U = decltype(f(std::declval())); 202 | // static_assert(std::is_convertible>::value, "foldl requires a function type U(T)"); 203 | // if (!empty(lst)) { 204 | // f(head(lst)); 205 | // for_each_impl()(tail(lst), f); 206 | // } 207 | // } 208 | //}; 209 | //template<> 210 | //struct function_traits { 211 | // static const bool is_function = true; 212 | // static const int arity = 2; 213 | //}; 214 | //auto for_each = fn(for_each_impl()); 215 | 216 | struct show_impl { 217 | template 218 | void operator()(immutable_list lst) const { 219 | for_each(lst, [](T v) { 220 | std::cout << "(" << v << ") "; 221 | }); 222 | std::cout << std::endl; 223 | } 224 | }; 225 | template<> 226 | struct function_traits { 227 | static const bool is_function = true; 228 | static const int arity = 1; 229 | }; 230 | auto show = fn(show_impl()); 231 | 232 | } 233 | 234 | #endif//_IMMUTABLE_LIST_HPP_ 235 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "fn.hpp" 2 | #include "monads\boxed_collection.hpp" 3 | #include "monads\maybe.hpp" 4 | #include "operators\operators.hpp" 5 | #include "list\immutable_list.hpp" 6 | #include "std_wrappers.hpp" 7 | #include "switch.hpp" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | //using std::string; 19 | // 20 | //struct A { 21 | // A(int value) : _value(value) 22 | // { 23 | // } 24 | // A(const A& a) : _value(a._value) 25 | // { 26 | // } 27 | // A(A&& a) : _value(a._value) 28 | // { 29 | // } 30 | // void operator=(const A& a) 31 | // { 32 | // _value = a._value; 33 | // } 34 | // void operator=(A&& a) 35 | // { 36 | // _value = a._value; 37 | // } 38 | // int _value; 39 | //}; 40 | //int answer_func(int a, int b, A c, string s) { 41 | // return a + b + c._value; 42 | //} 43 | //int simple_func(int a, int b) { 44 | // return a + b; 45 | //} 46 | // 47 | //int add_three_numbers(int a, int b, int c) { 48 | // return a + b + c; 49 | //} 50 | // 51 | //int main() { 52 | // using namespace curry; 53 | // 54 | // auto lst1 = make_list({ 3,4,5,6,7,8,9 }); 55 | // auto lst2 = 2 + lst1; 56 | // auto lst3 = 1 + lst2; 57 | // 58 | // auto is_lst1_empty = empty(lst1); 59 | // auto is_lst2_empty = empty(lst2); 60 | // auto is_lst3_empty = empty(lst3); 61 | // 62 | // auto head2 = head(lst2); 63 | // auto head3 = head(lst3); 64 | // 65 | // auto second_item_of_lst3 = head(tail(lst3)); 66 | // 67 | // auto square = fmap(_1*_1); 68 | // auto fmap_result = square(lst3); 69 | // show(fmap_result); 70 | // 71 | // auto sum = foldl(_+_, 0); 72 | // auto product = foldr(_*_, 1); 73 | // 74 | // auto sum_result = sum(lst3); 75 | // std::cout << sum_result << std::endl; 76 | // 77 | // auto product_result = lst3 | product; 78 | // std::cout << product_result << std::endl; 79 | // 80 | // auto f71 = fn(simple_func); 81 | // auto f711 = f71 * simple_func; 82 | // auto f712 = f711(5); 83 | // auto f72 = f712(7); 84 | // auto f73 = f72(13); 85 | // std::cout << typeid(f73).name() << std::endl; 86 | // 87 | // auto print_vector = [](const auto& v) { 88 | // for (auto&& item : v) { 89 | // std::cout << item << ", "; 90 | // } 91 | // std::cout << std::endl; 92 | // }; 93 | // 94 | // std::vector v1 = { 19,17,21 }; 95 | // std::vector v2 = { 23,49 }; 96 | // std::vector v3 = { 7, 13 }; 97 | // 98 | // auto adder = fn(add_three_numbers); 99 | // auto result = adder(with_each(v1), with_each(v2), with_each(v3)); 100 | // print_vector(result._v); 101 | // 102 | // std::vector result2; 103 | // for (auto&& i : v1) { 104 | // for (auto&& j : v2) { 105 | // for (auto&& k : v3) { 106 | // result2.push_back(add_three_numbers(i, j, k)); 107 | // } 108 | // } 109 | // } 110 | // print_vector(result2); 111 | // 112 | // auto value1 = maybe(10); 113 | // auto value2 = maybe(25); 114 | // auto value3 = maybe(30); 115 | // 116 | // auto added_maybes1 = fn(add_three_numbers)(value1, value2)(value3); 117 | // if (added_maybes1.is_valid()) { 118 | // std::cout << added_maybes1.get() << std::endl; 119 | // } 120 | // else { 121 | // std::cout << "no result" << std::endl; 122 | // } 123 | // 124 | // auto added_maybes2 = fn(add_three_numbers)(value1, maybe())(value3); 125 | // if (added_maybes2.is_valid()) { 126 | // std::cout << added_maybes2.get() << std::endl; 127 | // } 128 | // else { 129 | // std::cout << "no result" << std::endl; 130 | // } 131 | // 132 | // auto added_maybes3 = value1 133 | // | fn(add_three_numbers)(_, maybe(), value3); 134 | // if (added_maybes3.is_valid()) { 135 | // std::cout << added_maybes3.get() << std::endl; 136 | // } 137 | // else { 138 | // std::cout << "no result" << std::endl; 139 | // } 140 | // 141 | // auto added_maybes4 = fn(add_three_numbers)(_, maybe(), value3) * value1; 142 | // if (added_maybes4.is_valid()) { 143 | // std::cout << added_maybes4.get() << std::endl; 144 | // } 145 | // else { 146 | // std::cout << "no result" << std::endl; 147 | // } 148 | // 149 | // auto print = fn([](const std::string& str) { std::cout << str << std::endl; }); 150 | // auto world = _ + std::string("world"); 151 | // "hello " | world | print; 152 | // 153 | // auto times10 = _ * 10; 154 | // auto result21 = times10(4.2); 155 | // 156 | // auto greaterThan42 = 42 < _; 157 | // auto result22 = 32 | greaterThan42; 158 | // 159 | // auto l = [](auto a) {return a * 2; }; 160 | // auto fl = fn<1>(l); 161 | // auto rfl = fl(42.0); 162 | // 163 | // //auto foreach = [](auto f, auto l, auto func) { return std::for_each(f, l, func); }; 164 | // //auto fe = fn<3>(foreach); 165 | // int i = 0; 166 | // auto rfe = for_each(_, v1.end(), [&](auto item) {i += item; }) * begin; 167 | // //auto rfe2 = rfe(v1); 168 | // 169 | // auto sf = switch_(4, 5, 8, 9, 10); 170 | //} 171 | 172 | using namespace curry; 173 | using namespace std::tr2::sys; 174 | using std::string; 175 | using std::vector; 176 | using std::ifstream; 177 | using std::regex; 178 | 179 | struct Point { 180 | double x; 181 | double y; 182 | }; 183 | 184 | auto operator + (Point p1, Point p2) { 185 | return Point{ p1.x + p2.x, p1.y + p2.y }; 186 | }; 187 | 188 | auto operator / (Point p, int scalar) { 189 | return Point{ p.x / scalar, p.y / scalar }; 190 | }; 191 | 192 | int main() { 193 | auto get_input_file_names = [](string path) { 194 | vector file_names; 195 | for (auto it = directory_iterator(path); it != directory_iterator(); ++it) 196 | { 197 | const auto& file = it->path(); 198 | if (file.extension() == ".points") 199 | { 200 | file_names.push_back(file.string()); 201 | } 202 | } 203 | return file_names; 204 | }; 205 | 206 | auto read_file = [](string full_path) { 207 | ifstream file(full_path); 208 | vector lines; 209 | if (file) { 210 | string line; 211 | while (getline(file, line)) { 212 | lines.push_back(line); 213 | } 214 | } 215 | return lines; 216 | }; 217 | 218 | auto parse_point = [](string str) { 219 | regex pattern("(\\d+),(\\d+)"); 220 | std::smatch match; 221 | if (std::regex_match(str, match, pattern)) { 222 | if (match.size() == 3) { 223 | return Point{ double(std::stoi(match[1].str())), double(std::stoi(match[2].str()))}; 224 | } 225 | } 226 | return Point{}; 227 | }; 228 | 229 | auto points_box = get_input_file_names("C:\\Point_Files") 230 | | with_each 231 | | read_file 232 | | parse_point; 233 | auto points = unbox(points_box); 234 | 235 | auto centroid_of_cloud = foldl(_+_, Point{}, points) / points.size(); 236 | 237 | return 0; 238 | } 239 | -------------------------------------------------------------------------------- /monads/boxed_collection.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _BOXED_COLLECTION_HPP_ 2 | #define _BOXED_COLLECTION_HPP_ 3 | 4 | #include "..\monads\isabox.hpp" 5 | #include 6 | 7 | namespace curry { 8 | 9 | template 10 | struct boxed_vector; 11 | 12 | template 13 | struct boxed_vector&> { 14 | using collection_type = std::vector; 15 | boxed_vector(const collection_type& v) : _v(v) { 16 | } 17 | const collection_type& _v; 18 | }; 19 | 20 | template 21 | struct boxed_vector&> { 22 | using collection_type = std::vector; 23 | boxed_vector(collection_type& v) : _v(v) { 24 | } 25 | collection_type& _v; 26 | }; 27 | 28 | template 29 | struct boxed_vector> { 30 | using collection_type = std::vector; 31 | boxed_vector() : _v() { 32 | } 33 | boxed_vector(collection_type&& v) : _v(std::move(v)) { 34 | } 35 | collection_type _v; 36 | }; 37 | 38 | template 39 | struct isabox> : std::true_type { 40 | using collection_type = std::decay_t; 41 | using value_type = typename collection_type::value_type; 42 | 43 | template 44 | struct box_map_value_t { 45 | using type = OtherT; 46 | }; 47 | 48 | template 49 | struct box_map_value_t>> { 50 | using type = typename box_map_value_t::type; 51 | }; 52 | 53 | template 54 | struct box_map_value_t> { 55 | using type = typename box_map_value_t::type; 56 | }; 57 | 58 | template 59 | static void box_map_impl(const Item& item, F f) { 60 | f(item); 61 | } 62 | 63 | template 64 | static void box_map_impl(Item&& item, F f) { 65 | f(std::move(item)); 66 | } 67 | 68 | template 69 | static void add_item(C& c, const I& i) { 70 | c.push_back(i); 71 | } 72 | template 73 | static void add_item(C& c, I&& i) { 74 | c.push_back(std::move(i)); 75 | } 76 | template 77 | static void add_item(C& c, const std::vector& v) { 78 | for (auto& i : v) 79 | c.push_back(i); 80 | } 81 | template 82 | static void add_item(C& c, std::vector&& v) { 83 | for (auto&& i : std::move(v)) 84 | c.push_back(std::move(i)); 85 | } 86 | 87 | template 88 | static void box_map_impl(const boxed_vector& collection, F f) { 89 | //using new_collection_type = std::vector::value_type>::type>; //(std::vector; 90 | //using new_collection_type = std::vector; 91 | using new_collection_type = std::vector()))>::type>; 92 | using return_type = boxed_vector; 93 | new_collection_type ret; 94 | for (auto&& item : collection._v) { 95 | box_map_impl(item, [&ret](auto&& item) {add_item(ret, item); }); 96 | } 97 | for (auto&& item : ret) { 98 | f(item); //why not directly call instead of an intermediate vector? 99 | } 100 | } 101 | 102 | template 103 | static void box_map_impl(boxed_vector&& collection, F f) { 104 | //using new_collection_type = std::vector::value_type>::type>; //(std::vector; 105 | //using new_collection_type = std::vector; 106 | using new_collection_type = std::vector()))>::type>; 107 | using return_type = boxed_vector; 108 | new_collection_type ret; 109 | for (auto&& item : std::move(collection)._v) { 110 | box_map_impl(item, [&ret](auto&& item) {add_item(ret, std::move(item)); }); 111 | } 112 | for (auto&& item : ret) { 113 | f(std::move(item)); //why not directly call instead of an intermediate vector? 114 | } 115 | } 116 | 117 | template 118 | static auto box_map(const boxed_vector& collection, F f) { 119 | //using new_collection_type = std::vector::type>; //(std::vector; 120 | //using new_collection_type = std::vector; 121 | //using new_collection_type = std::vector()))>; 122 | using new_collection_type = std::vector()))>::type>; 123 | using return_type = boxed_vector; 124 | new_collection_type ret; 125 | for (auto&& item : collection._v) { 126 | box_map_impl(f(item), [&ret](auto&& item) {add_item(ret, item); }); 127 | } 128 | return return_type(std::move(ret)); 129 | } 130 | template 131 | static auto box_map(boxed_vector&& collection, F f) { 132 | //using new_collection_type = std::vector::type>; //(std::vector; 133 | //using new_collection_type = std::vector; 134 | using new_collection_type = std::vector()))>::type>; 135 | using return_type = boxed_vector; 136 | new_collection_type ret; 137 | for (auto&& item : collection._v) { 138 | box_map_impl(f(std::move(item)), [&ret](auto&& item) {add_item(ret, std::move(item));}); 139 | } 140 | return return_type(std::move(ret)); 141 | } 142 | }; 143 | 144 | struct with_each_t { 145 | template 146 | auto operator()(T& v) { 147 | return boxed_vector(v); 148 | } 149 | template 150 | auto operator()(T&& v) { 151 | return boxed_vector(std::move(v)); 152 | } 153 | }; 154 | template<> 155 | struct function_traits { 156 | static const bool is_function = true; 157 | static const int arity = 1; 158 | }; 159 | auto with_each = fn(with_each_t()); 160 | 161 | template 162 | auto unbox(Box b) { 163 | return b._v; 164 | } 165 | 166 | } 167 | 168 | #endif//_BOXED_COLLECTION_HPP_ -------------------------------------------------------------------------------- /monads/get_first_box_argument_index.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _GET_FIRST_BOX_ARGUMENT_INDEX_HPP_ 2 | #define _GET_FIRST_BOX_ARGUMENT_INDEX_HPP_ 3 | 4 | #include "..\monads\isabox.hpp" 5 | #include 6 | #include 7 | 8 | namespace curry { 9 | 10 | template 11 | struct get_first_box_argument_index_impl; 12 | 13 | template 14 | struct get_first_box_argument_index_impl, typename std::enable_if::value>::type> { 15 | static const int value = current_index; 16 | }; 17 | 18 | template 19 | struct get_first_box_argument_index_impl, typename std::enable_if::value>::type> { 20 | static const int value = get_first_box_argument_index_impl>::value; 21 | }; 22 | 23 | template 24 | struct get_first_box_argument_index_impl, void> { 25 | static const int value = -1; 26 | }; 27 | 28 | template 29 | struct get_first_box_argument_index : get_first_box_argument_index_impl<0, T> { 30 | }; 31 | 32 | } 33 | 34 | #endif//_GET_FIRST_BOX_ARGUMENT_INDEX_HPP_ -------------------------------------------------------------------------------- /monads/isabox.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _IS_A_BOX_HPP_ 2 | #define _IS_A_BOX_HPP_ 3 | 4 | #include 5 | 6 | namespace curry { 7 | 8 | template 9 | struct isabox : std::false_type { 10 | }; 11 | 12 | } 13 | 14 | #endif//_IS_A_BOX_HPP_ -------------------------------------------------------------------------------- /monads/maybe.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MAYBE_HPP_ 2 | #define _MAYBE_HPP_ 3 | 4 | #include "..\monads\isabox.hpp" 5 | #include 6 | 7 | namespace curry { 8 | 9 | template 10 | struct maybe_t { 11 | maybe_t() : _value(), _is_valid(false) { 12 | } 13 | maybe_t(const maybe_t& other) : _value(), _is_valid(other._is_valid) 14 | { 15 | } 16 | maybe_t(maybe_t&& other) : _value(std::move(other._value)), _is_valid(other._is_valid) { 17 | } 18 | maybe_t(T&& value) : _value(std::move(value)), _is_valid(true) { 19 | } 20 | bool is_valid() const { return _is_valid; } 21 | const T& get() const& { return _value; } 22 | T& get() & { return _value; } 23 | T get() && { return std::move(_value); } 24 | T _value; 25 | bool _is_valid; 26 | }; 27 | 28 | template 29 | struct maybe_t { 30 | maybe_t() : _value(nullptr), _is_valid(false) { 31 | } 32 | maybe_t(const T& value) : _value(&value), _is_valid(true) { 33 | } 34 | maybe_t(const T* value) : _value(value), _is_valid(value ? true : false) { 35 | } 36 | bool is_valid() const { return _is_valid; } 37 | const T& get() const { return *_value; } 38 | const T* _value; 39 | bool _is_valid; 40 | }; 41 | 42 | template 43 | struct maybe_t { 44 | maybe_t() : _value(nullptr), _is_valid(false) { 45 | } 46 | maybe_t(T& value) : _value(&value), _is_valid(true) { 47 | } 48 | maybe_t(T* value) : _value(value), _is_valid(value ? true : false) { 49 | } 50 | bool is_valid() const { return _is_valid; } 51 | T& get() { return *_value; } 52 | const T& get() const { return *_value; } 53 | T* _value; 54 | bool _is_valid; 55 | }; 56 | 57 | template 58 | struct isabox> : std::true_type{ 59 | template 60 | struct box_map_value_t { 61 | using type = OtherT; 62 | }; 63 | 64 | template 65 | struct box_map_value_t> { 66 | using type = typename box_map_value_t::type; 67 | }; 68 | template 69 | static auto box_map_impl(const Item& item, F f) { 70 | f(item); 71 | return true; 72 | } 73 | template 74 | static auto box_map_impl(Item&& item, F f) { 75 | f(std::move(item)); 76 | return true; 77 | } 78 | 79 | template 80 | static auto box_map_impl(const maybe_t& m, F f) { 81 | if (m.is_valid() && box_map_impl(m.get(), [&f](auto&& item) { f(item); })) { 82 | return true; 83 | } 84 | return false; 85 | } 86 | template 87 | static auto box_map_impl(maybe_t&& m, F f) { 88 | if (m.is_valid() && box_map_impl(m.get(), [&f](auto&& item) { f(std::move(item)); })) { 89 | return true; 90 | } 91 | return false; 92 | } 93 | 94 | template 95 | static auto box_map(const maybe_t& m, F f) { 96 | //using ResultT = typename box_map_value_t::type; 97 | using ResultT = typename box_map_value_t::type; 98 | if (m.is_valid()) { 99 | ResultT result; 100 | if (box_map_impl(f(m.get()), [&result](auto&& item) { result = item; })) { 101 | return maybe_t(std::move(result)); 102 | } 103 | } 104 | return maybe_t(); 105 | } 106 | template 107 | static auto box_map(maybe_t&& m, F f) { 108 | //using ResultT = typename box_map_value_t::type; 109 | using ResultT = typename box_map_value_t()))>::type; 110 | if (m.is_valid()) { 111 | ResultT result; 112 | if (box_map_impl(f(std::move(m).get()), [&result](auto&& item) { result = std::move(item); })) { 113 | return maybe_t(std::move(result)); 114 | } 115 | } 116 | return maybe_t(); 117 | } 118 | }; 119 | 120 | template 121 | auto maybe() { 122 | return maybe_t(); 123 | } 124 | 125 | template 126 | auto maybe(T& value) { 127 | return maybe_t(value); 128 | } 129 | 130 | template 131 | auto maybe(T* value) { 132 | return maybe_t(value); 133 | } 134 | 135 | template 136 | auto maybe(T&& value) { 137 | return maybe_t(std::move(value)); 138 | } 139 | 140 | } 141 | 142 | #endif//_MAYBE_HPP_ -------------------------------------------------------------------------------- /operators/operators.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _OPERATORS_HPP_ 2 | 3 | #include "..\util\fn_fwd.hpp" 4 | #include "..\arity\function_traits.hpp" 5 | #include "..\placeholders\placeholder.hpp" 6 | 7 | namespace curry { 8 | 9 | template 10 | auto compose(F&& f, A&& a, Rest&&... rest) { 11 | return (std::forward(f)).compose(std::forward(a), std::forward(rest)...); 12 | } 13 | 14 | template 15 | auto operator * (const fn_t& f, A&& a) { 16 | return compose(f, std::forward(a)); 17 | } 18 | 19 | template 20 | auto operator * (fn_t&& f, A&& a) { 21 | return compose(std::forward>(f), std::forward(a)); 22 | } 23 | 24 | template 25 | auto operator | (A&& a, const fn_t& f) { 26 | return compose(f, std::forward(a)); 27 | } 28 | 29 | template 30 | auto operator | (A&& a, fn_t&& f) { 31 | return compose(std::forward>(f), std::forward(a)); 32 | } 33 | 34 | template::is_function>> 35 | auto operator | (A&& a, const F& f) { 36 | return compose(fn(f), std::forward(a)); 37 | } 38 | 39 | template::is_function>> 40 | auto operator | (A&& a, F&& f) { 41 | return compose(fn(std::forward(f)), std::forward(a)); 42 | } 43 | 44 | template 45 | auto operator | (const fn_t& f1, const fn_t& f2) { 46 | return compose(f2, f1); 47 | } 48 | 49 | template 50 | struct op_t { 51 | op_t(F&& f) : _f(f) {} 52 | template 53 | auto operator()(T&& t, U&& u) const& { 54 | return _f(std::forward(t), std::forward(u)); 55 | } 56 | template 57 | auto operator()(T&& t, U&& u) && { 58 | return std::forward(_f)(std::forward(t), std::forward(u)); 59 | } 60 | F _f; 61 | }; 62 | 63 | template 64 | auto op(F&& f) { 65 | return op_t(std::forward(f)); 66 | } 67 | 68 | template 69 | struct function_traits> { 70 | using Ret = void; 71 | static const bool is_function = true; 72 | static const int arity = 2; 73 | }; 74 | 75 | template 76 | auto operator + (ph lhs, ph rhs) { 77 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs + rhs; }))(lhs, rhs); 78 | } 79 | 80 | template 81 | auto operator + (ph lhs, Rhs&& rhs) { 82 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs + rhs; }))(lhs, rhs); 83 | } 84 | 85 | template 86 | auto operator + (Lhs&& lhs, ph rhs) { 87 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs + rhs; }))(lhs, rhs); 88 | } 89 | 90 | template 91 | auto operator - (ph lhs, ph rhs) { 92 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs - rhs; }))(lhs, rhs); 93 | } 94 | 95 | template 96 | auto operator - (ph lhs, Rhs&& rhs) { 97 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs - rhs; }))(lhs, rhs); 98 | } 99 | 100 | template 101 | auto operator - (Lhs&& lhs, ph rhs) { 102 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs - rhs; }))(lhs, rhs); 103 | } 104 | 105 | template 106 | auto operator * (ph lhs, ph rhs) { 107 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs * rhs; }))(lhs, rhs); 108 | } 109 | 110 | template 111 | auto operator * (ph lhs, Rhs&& rhs) { 112 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs * rhs; }))(lhs, rhs); 113 | } 114 | 115 | template 116 | auto operator * (Lhs&& lhs, ph rhs) { 117 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs * rhs; }))(lhs, rhs); 118 | } 119 | 120 | template 121 | auto operator / (ph lhs, ph rhs) { 122 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs / rhs; }))(lhs, rhs); 123 | } 124 | 125 | template 126 | auto operator / (ph lhs, Rhs&& rhs) { 127 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs / rhs; }))(lhs, rhs); 128 | } 129 | 130 | template 131 | auto operator / (Lhs&& lhs, ph rhs) { 132 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs / rhs; }))(lhs, rhs); 133 | } 134 | 135 | template 136 | auto operator % (ph lhs, ph rhs) { 137 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs % rhs; }))(lhs, rhs); 138 | } 139 | 140 | template 141 | auto operator % (ph lhs, Rhs&& rhs) { 142 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs % rhs; }))(lhs, rhs); 143 | } 144 | 145 | template 146 | auto operator % (Lhs&& lhs, ph rhs) { 147 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs % rhs; }))(lhs, rhs); 148 | } 149 | 150 | template 151 | auto operator > (ph lhs, ph rhs) { 152 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs > rhs; }))(lhs, rhs); 153 | } 154 | 155 | template 156 | auto operator > (Lhs&& lhs, ph rhs) { 157 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs > rhs; }))(lhs, rhs); 158 | } 159 | 160 | template 161 | auto operator > (ph lhs, Rhs&& rhs) { 162 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs > rhs; }))(lhs, rhs); 163 | } 164 | 165 | template 166 | auto operator < (ph lhs, ph rhs) { 167 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs < rhs; }))(lhs, rhs); 168 | } 169 | 170 | template 171 | auto operator < (ph lhs, Rhs&& rhs) { 172 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs < rhs; }))(lhs, rhs); 173 | } 174 | 175 | template 176 | auto operator < (Lhs&& lhs, ph rhs) { 177 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs < rhs; }))(lhs, rhs); 178 | } 179 | 180 | template 181 | auto operator >=(ph lhs, ph rhs) { 182 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs >= rhs; }))(lhs, rhs); 183 | } 184 | 185 | template 186 | auto operator >=(ph lhs, Rhs&& rhs) { 187 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs >= rhs; }))(lhs, rhs); 188 | } 189 | 190 | template 191 | auto operator >= (Lhs&& lhs, ph rhs) { 192 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs >= rhs; }))(lhs, rhs); 193 | } 194 | 195 | template 196 | auto operator <= (ph lhs, ph rhs) { 197 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs <= rhs; }))(lhs, rhs); 198 | } 199 | 200 | template 201 | auto operator <= (ph lhs, Rhs&& rhs) { 202 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs <= rhs; }))(lhs, rhs); 203 | } 204 | 205 | template 206 | auto operator <= (Lhs&& lhs, ph rhs) { 207 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs <= rhs; }))(lhs, rhs); 208 | } 209 | 210 | template 211 | auto operator == (ph lhs, ph rhs) { 212 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs == rhs; }))(lhs, rhs); 213 | } 214 | 215 | template 216 | auto operator == (ph lhs, Rhs&& rhs) { 217 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs == rhs; }))(lhs, rhs); 218 | } 219 | 220 | template 221 | auto operator == (Lhs&& lhs, ph rhs) { 222 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs == rhs; }))(lhs, rhs); 223 | } 224 | 225 | template 226 | auto operator != (ph lhs, ph rhs) { 227 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs != rhs; }))(lhs, rhs); 228 | } 229 | 230 | template 231 | auto operator != (ph lhs, Rhs&& rhs) { 232 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs != rhs; }))(lhs, rhs); 233 | } 234 | 235 | template 236 | auto operator != (Lhs&& lhs, ph rhs) { 237 | return fn(op([](auto&& lhs, auto&& rhs) {return lhs != rhs; }))(lhs, rhs); 238 | } 239 | 240 | template 241 | auto operator ! (ph rhs) { 242 | return fn(op([](auto&& rhs) {return !rhs; }))(rhs); 243 | } 244 | 245 | template 246 | auto operator ~ (ph rhs) { 247 | return fn(op([](auto&& rhs) {return ~rhs; }))(rhs); 248 | } 249 | 250 | template 251 | auto operator + (ph rhs) { 252 | return fn(op([](auto&& rhs) {return +rhs; }))(rhs); 253 | } 254 | 255 | template 256 | auto operator - (ph rhs) { 257 | return fn(op([](auto&& rhs) {return -rhs; }))(rhs); 258 | } 259 | 260 | } 261 | 262 | #endif 263 | -------------------------------------------------------------------------------- /placeholders/add_anonymous_placeholder_support.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _ADD_ANONYMOUS_PLACEHOLDER_SUPPORT_HPP_ 2 | #define _ADD_ANONYMOUS_PLACEHOLDER_SUPPORT_HPP_ 3 | 4 | #include "..\placeholders\placeholder.hpp" 5 | #include "..\util\real_arguments_before_i.hpp" 6 | #include "..\util\int_list.hpp" 7 | #include 8 | #include 9 | 10 | namespace curry { 11 | 12 | template 13 | CONSTEXPR decltype(auto) correct_anonymous_placeholder_number(Item&& item) { 14 | return std::forward(item); 15 | } 16 | 17 | template 18 | CONSTEXPR decltype(auto) correct_anonymous_placeholder_number(ph<0>) { 19 | return ph::value>(); 20 | } 21 | 22 | template 23 | CONSTEXPR decltype(auto) add_anonymous_placeholder_support_impl(int_list, T&& t) { 24 | return std::forward_as_tuple(correct_anonymous_placeholder_number(std::get(std::forward(t)))...); 25 | } 26 | 27 | template 28 | CONSTEXPR decltype(auto) add_anonymous_placeholder_support(T&& t) { 29 | return add_anonymous_placeholder_support_impl(indices_for(), std::forward(t)); 30 | } 31 | 32 | } 33 | 34 | #endif//_ADD_ANONYMOUS_PLACEHOLDER_SUPPORT_HPP_ 35 | -------------------------------------------------------------------------------- /placeholders/placeholder.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _PLACEHOLDER_HPP_ 2 | #define _PLACEHOLDER_HPP_ 3 | 4 | namespace curry { 5 | 6 | template 7 | struct ph {}; 8 | 9 | ph<0> _; 10 | ph<1> _1; 11 | ph<2> _2; 12 | ph<3> _3; 13 | ph<4> _4; 14 | ph<5> _5; 15 | ph<6> _6; 16 | ph<7> _7; 17 | ph<8> _8; 18 | ph<9> _9; 19 | ph<10> _10; 20 | 21 | template 22 | struct is_placeholder { 23 | static const bool value = false; 24 | }; 25 | 26 | template 27 | struct is_placeholder> { 28 | static const bool value = true; 29 | }; 30 | 31 | } 32 | 33 | #endif//_PLACEHOLDER_HPP_ 34 | -------------------------------------------------------------------------------- /std_wrappers.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _STD_WRAPPERS_HPP_ 2 | #define _STD_WRAPPERS_HPP_ 3 | 4 | #include "util\fn_fwd.hpp" 5 | #include 6 | 7 | namespace curry 8 | { 9 | namespace __detail 10 | { 11 | struct all_of_fn 12 | { 13 | template 14 | decltype(auto) operator()(I f, I l, F func) { 15 | return std::all_of(f, l, func); 16 | } 17 | }; 18 | struct any_of_fn 19 | { 20 | template 21 | decltype(auto) operator()(I f, I l, F func) { 22 | return std::any_of(f, l, func); 23 | } 24 | }; 25 | struct none_of_fn 26 | { 27 | template 28 | decltype(auto) operator()(I f, I l, F func) { 29 | return std::none_of(f, l, func); 30 | } 31 | }; 32 | struct for_each_fn 33 | { 34 | template 35 | decltype(auto) operator()(I f, I l, F func) { 36 | return std::for_each(f, l, func); 37 | } 38 | }; 39 | struct find_fn 40 | { 41 | template 42 | decltype(auto) operator()(I f, I l, F func) { 43 | return std::find(f, l, func); 44 | } 45 | }; 46 | struct find_if_fn 47 | { 48 | template 49 | decltype(auto) operator()(I f, I l, const T& val) { 50 | return std::find_if(f, l, vsl); 51 | } 52 | }; 53 | struct find_if_not_fn 54 | { 55 | template 56 | decltype(auto) operator()(I f, I l, F func) { 57 | return std::find_if_not(f, l, func); 58 | } 59 | }; 60 | struct find_end_fn 61 | { 62 | template 63 | decltype(auto) operator()(I1 f1, I1 l1, I2 f2, I2 l2) { 64 | return std::find_end(f1, l1, f2, l2); 65 | } 66 | }; 67 | struct find_end_pred_fn 68 | { 69 | template 70 | decltype(auto) operator()(I1 f1, I1 l1, I2 f2, I2 l2, P pred) { 71 | return std::find_end(f1, l1, f2, l2, pred); 72 | } 73 | }; 74 | struct find_first_of_fn 75 | { 76 | template 77 | decltype(auto) operator()(I1 f1, I1 l1, I2 f2, I2 l2) { 78 | return std::find_first_of(f1, l1, f2, l2); 79 | } 80 | }; 81 | struct find_first_of_pred_fn 82 | { 83 | template 84 | decltype(auto) operator()(I1 f1, I1 l1, I2 f2, I2 l2, P pred) { 85 | return std::find_first_of(f1, l1, f2, l2, pred); 86 | } 87 | }; 88 | struct adjacent_find_fn 89 | { 90 | template 91 | decltype(auto) operator()(I f, I l) { 92 | return std::adjacent_find(f, l); 93 | } 94 | }; 95 | struct adjacent_find_pred_fn 96 | { 97 | template 98 | decltype(auto) operator()(I f, I l, P pred) { 99 | return std::adjacent_find(f, l, pred); 100 | } 101 | }; 102 | struct count_fn 103 | { 104 | template 105 | decltype(auto) operator()(I f, I l, const T& val) { 106 | return std::count(f, l, val); 107 | } 108 | }; 109 | struct count_if_fn 110 | { 111 | template 112 | decltype(auto) operator()(I f, I l, P pred) { 113 | return std::count_if(f, l, pred); 114 | } 115 | }; 116 | struct mismatch_fn 117 | { 118 | template 119 | decltype(auto) operator()(I1 f1, I1 l1, I2 f2) { 120 | return std::mismatch(f1, l1, f2); 121 | } 122 | }; 123 | struct mismatch_pred_fn 124 | { 125 | template 126 | decltype(auto) operator()(I1 f1, I1 l1, I2 f2, P pred) { 127 | return std::mismatch(f1, l1, f2, pred); 128 | } 129 | }; 130 | struct equal_fn 131 | { 132 | template 133 | decltype(auto) operator()(I1 f1, I1 l1, I2 f2) { 134 | return std::equal(f1, l1, f2); 135 | } 136 | }; 137 | struct equal_pred_fn 138 | { 139 | template 140 | decltype(auto) operator()(I1 f1, I1 l1, I2 f2, P pred) { 141 | return std::equal(f1, l1, f2, pred); 142 | } 143 | }; 144 | struct is_permutation_fn 145 | { 146 | template 147 | decltype(auto) operator()(I1 f1, I1 l1, I2 f2) { 148 | return std::is_permutation(f1, l1, f2); 149 | } 150 | }; 151 | struct is_permutation_pred_fn 152 | { 153 | template 154 | decltype(auto) operator()(I1 f1, I1 l1, I2 f2, P pred) { 155 | return std::is_permutation(f1, l1, f2, pred); 156 | } 157 | }; 158 | struct search_fn 159 | { 160 | template 161 | decltype(auto) operator()(I1 f1, I1 l1, I2 f2) { 162 | return std::search(f1, l1, f2, l2); 163 | } 164 | }; 165 | struct search_pred_fn 166 | { 167 | template 168 | decltype(auto) operator()(I1 f1, I1 l1, I2 f2, P pred) { 169 | return std::search(f1, l1, f2, l2, pred); 170 | } 171 | }; 172 | struct search_n_fn 173 | { 174 | template 175 | decltype(auto) operator()(I f, I l, Size count, const T& val) { 176 | return std::search_n(f, l, count, val); 177 | } 178 | }; 179 | struct search_n_pred_fn 180 | { 181 | template 182 | decltype(auto) operator()(I f, I l, Size count, const T& val, P pred) { 183 | return std::search_n(f, l, count, val, pred); 184 | } 185 | }; 186 | struct copy_fn 187 | { 188 | template 189 | decltype(auto) operator()(I f, I l, F func) { 190 | return std::copy(f, l, func); 191 | } 192 | }; 193 | struct copy_n_fn 194 | { 195 | template 196 | decltype(auto) operator()(I f, I l, F func) { 197 | return std::copy_n(f, l, func); 198 | } 199 | }; 200 | struct copy_if_fn 201 | { 202 | template 203 | decltype(auto) operator()(I f, I l, O d, F func) { 204 | return std::copy_if(f, l, d, func); 205 | } 206 | }; 207 | struct copy_backward_fn 208 | { 209 | template 210 | decltype(auto) operator()(I f, I l, F func) { 211 | return std::copy_backward(f, l, func); 212 | } 213 | }; 214 | struct move_fn 215 | { 216 | template 217 | decltype(auto) operator()(I f, I l, F func) { 218 | return std::move(f, l, func); 219 | } 220 | }; 221 | struct move_backward_fn 222 | { 223 | template 224 | decltype(auto) operator()(I f, I l, F func) { 225 | return std::move_backward(f, l, func); 226 | } 227 | }; 228 | struct swap_fn 229 | { 230 | template 231 | decltype(auto) operator()(I f, I l, F func) { 232 | return std::swap(f, l, func); 233 | } 234 | }; 235 | struct swap_ranges_fn 236 | { 237 | template 238 | decltype(auto) operator()(I f, I l, F func) { 239 | return std::swap_ranges(f, l, func); 240 | } 241 | }; 242 | struct iter_swap_fn 243 | { 244 | template 245 | decltype(auto) operator()(I f, I l, F func) { 246 | return std::iter_swap(f, l, func); 247 | } 248 | }; 249 | struct transform_fn 250 | { 251 | template 252 | decltype(auto) operator()(I f, I l, F func) { 253 | return std::transform(f, l, func); 254 | } 255 | }; 256 | struct replace_fn 257 | { 258 | template 259 | decltype(auto) operator()(I f, I l, F func) { 260 | return std::replace(f, l, func); 261 | } 262 | }; 263 | struct replace_if_fn 264 | { 265 | template 266 | decltype(auto) operator()(I f, I l, F func) { 267 | return std::replace_if(f, l, func); 268 | } 269 | }; 270 | struct replace_copy_fn 271 | { 272 | template 273 | decltype(auto) operator()(I f, I l, F func) { 274 | return std::replace_copy(f, l, func); 275 | } 276 | }; 277 | struct replace_copy_if_fn 278 | { 279 | template 280 | decltype(auto) operator()(I f, I l, F func) { 281 | return std::replace_copy_if(f, l, func); 282 | } 283 | }; 284 | struct fill_fn 285 | { 286 | template 287 | decltype(auto) operator()(I f, I l, F func) { 288 | return std::fill(f, l, func); 289 | } 290 | }; 291 | struct fill_n_fn 292 | { 293 | template 294 | decltype(auto) operator()(I f, I l, F func) { 295 | return std::fill_n(f, l, func); 296 | } 297 | }; 298 | struct generate_fn 299 | { 300 | template 301 | decltype(auto) operator()(I f, I l, F func) { 302 | return std::generate(f, l, func); 303 | } 304 | }; 305 | struct generate_n_fn 306 | { 307 | template 308 | decltype(auto) operator()(I f, I l, F func) { 309 | return std::generate_n(f, l, func); 310 | } 311 | }; 312 | struct remove_fn 313 | { 314 | template 315 | decltype(auto) operator()(I f, I l, F func) { 316 | return std::remove(f, l, func); 317 | } 318 | }; 319 | struct remove_if_fn 320 | { 321 | template 322 | decltype(auto) operator()(I f, I l, F func) { 323 | return std::remove_if(f, l, func); 324 | } 325 | }; 326 | struct remove_copy_fn 327 | { 328 | template 329 | decltype(auto) operator()(I f, I l, F func) { 330 | return std::remove_copy(f, l, func); 331 | } 332 | }; 333 | struct remove_copy_if_fn 334 | { 335 | template 336 | decltype(auto) operator()(I f, I l, F func) { 337 | return std::remove_copy_if(f, l, func); 338 | } 339 | }; 340 | struct unique_fn 341 | { 342 | template 343 | decltype(auto) operator()(I f, I l, F func) { 344 | return std::unique(f, l, func); 345 | } 346 | }; 347 | struct unique_copy_fn 348 | { 349 | template 350 | decltype(auto) operator()(I f, I l, F func) { 351 | return std::unique_copy(f, l, func); 352 | } 353 | }; 354 | struct reverse_fn 355 | { 356 | template 357 | decltype(auto) operator()(I f, I l, F func) { 358 | return std::reverse(f, l, func); 359 | } 360 | }; 361 | struct reverse_copy_fn 362 | { 363 | template 364 | decltype(auto) operator()(I f, I l, F func) { 365 | return std::reverse_copy(f, l, func); 366 | } 367 | }; 368 | struct rotate_fn 369 | { 370 | template 371 | decltype(auto) operator()(I f, I l, F func) { 372 | return std::rotate(f, l, func); 373 | } 374 | }; 375 | struct rotate_copy_fn 376 | { 377 | template 378 | decltype(auto) operator()(I f, I l, F func) { 379 | return std::rotate_copy(f, l, func); 380 | } 381 | }; 382 | struct random_shuffle_fn 383 | { 384 | template 385 | decltype(auto) operator()(I f, I l, F func) { 386 | return std::random_shuffle(f, l, func); 387 | } 388 | }; 389 | struct shuffle_fn 390 | { 391 | template 392 | decltype(auto) operator()(I f, I l, F func) { 393 | return std::shuffle(f, l, func); 394 | } 395 | }; 396 | struct is_partitioned_fn 397 | { 398 | template 399 | decltype(auto) operator()(I f, I l, F func) { 400 | return std::is_partitioned(f, l, func); 401 | } 402 | }; 403 | struct partition_fn 404 | { 405 | template 406 | decltype(auto) operator()(I f, I l, F func) { 407 | return std::partition(f, l, func); 408 | } 409 | }; 410 | struct stable_partition_fn 411 | { 412 | template 413 | decltype(auto) operator()(I f, I l, F func) { 414 | return std::stable_partition(f, l, func); 415 | } 416 | }; 417 | struct partition_copy_fn 418 | { 419 | template 420 | decltype(auto) operator()(I f, I l, F func) { 421 | return std::partition_copy(f, l, func); 422 | } 423 | }; 424 | struct partition_point_fn 425 | { 426 | template 427 | decltype(auto) operator()(I f, I l, F func) { 428 | return std::partition_point(f, l, func); 429 | } 430 | }; 431 | struct sort_fn 432 | { 433 | template 434 | decltype(auto) operator()(I f, I l, F func) { 435 | return std::sort(f, l, func); 436 | } 437 | }; 438 | struct stable_sort_fn 439 | { 440 | template 441 | decltype(auto) operator()(I f, I l, F func) { 442 | return std::stable_sort(f, l, func); 443 | } 444 | }; 445 | struct partial_sort_fn 446 | { 447 | template 448 | decltype(auto) operator()(I f, I l, F func) { 449 | return std::partial_sort(f, l, func); 450 | } 451 | }; 452 | struct partial_sort_copy_fn 453 | { 454 | template 455 | decltype(auto) operator()(I f, I l, F func) { 456 | return std::partial_sort_copy(f, l, func); 457 | } 458 | }; 459 | struct is_sorted_fn 460 | { 461 | template 462 | decltype(auto) operator()(I f, I l, F func) { 463 | return std::is_sorted(f, l, func); 464 | } 465 | }; 466 | struct is_sorted_until_fn 467 | { 468 | template 469 | decltype(auto) operator()(I f, I l, F func) { 470 | return std::is_sorted_until(f, l, func); 471 | } 472 | }; 473 | struct nth_element_fn 474 | { 475 | template 476 | decltype(auto) operator()(I f, I l, F func) { 477 | return std::nth_element(f, l, func); 478 | } 479 | }; 480 | struct lower_bound_fn 481 | { 482 | template 483 | decltype(auto) operator()(I f, I l, F func) { 484 | return std::lower_bound(f, l, func); 485 | } 486 | }; 487 | struct upper_bound_fn 488 | { 489 | template 490 | decltype(auto) operator()(I f, I l, F func) { 491 | return std::upper_bound(f, l, func); 492 | } 493 | }; 494 | struct equal_range_fn 495 | { 496 | template 497 | decltype(auto) operator()(I f, I l, F func) { 498 | return std::equal_range(f, l, func); 499 | } 500 | }; 501 | struct binary_search_fn 502 | { 503 | template 504 | decltype(auto) operator()(I f, I l, F func) { 505 | return std::binary_search(f, l, func); 506 | } 507 | }; 508 | struct merge_fn 509 | { 510 | template 511 | decltype(auto) operator()(I f, I l, F func) { 512 | return std::merge(f, l, func); 513 | } 514 | }; 515 | struct inplace_merge_fn 516 | { 517 | template 518 | decltype(auto) operator()(I f, I l, F func) { 519 | return std::inplace_merge(f, l, func); 520 | } 521 | }; 522 | struct includes_fn 523 | { 524 | template 525 | decltype(auto) operator()(I f, I l, F func) { 526 | return std::includes(f, l, func); 527 | } 528 | }; 529 | struct set_union_fn 530 | { 531 | template 532 | decltype(auto) operator()(I f, I l, F func) { 533 | return std::set_union(f, l, func); 534 | } 535 | }; 536 | struct set_intersection_fn 537 | { 538 | template 539 | decltype(auto) operator()(I f, I l, F func) { 540 | return std::set_intersection(f, l, func); 541 | } 542 | }; 543 | struct set_difference_fn 544 | { 545 | template 546 | decltype(auto) operator()(I f, I l, F func) { 547 | return std::set_difference(f, l, func); 548 | } 549 | }; 550 | struct set_symmetric_difference_fn 551 | { 552 | template 553 | decltype(auto) operator()(I f, I l, F func) { 554 | return std::set_symmetric_difference(f, l, func); 555 | } 556 | }; 557 | struct push_heap_fn 558 | { 559 | template 560 | decltype(auto) operator()(I f, I l, F func) { 561 | return std::push_heap(f, l, func); 562 | } 563 | }; 564 | struct pop_heap_fn 565 | { 566 | template 567 | decltype(auto) operator()(I f, I l, F func) { 568 | return std::pop_heap(f, l, func); 569 | } 570 | }; 571 | struct make_heap_fn 572 | { 573 | template 574 | decltype(auto) operator()(I f, I l, F func) { 575 | return std::make_heap(f, l, func); 576 | } 577 | }; 578 | struct sort_heap_fn 579 | { 580 | template 581 | decltype(auto) operator()(I f, I l, F func) { 582 | return std::sort_heap(f, l, func); 583 | } 584 | }; 585 | struct is_heap_fn 586 | { 587 | template 588 | decltype(auto) operator()(I f, I l, F func) { 589 | return std::is_heap(f, l, func); 590 | } 591 | }; 592 | struct is_heap_until_fn 593 | { 594 | template 595 | decltype(auto) operator()(I f, I l, F func) { 596 | return std::is_heap_until(f, l, func); 597 | } 598 | }; 599 | struct min_fn 600 | { 601 | template 602 | decltype(auto) operator()(I f, I l, F func) { 603 | return std::min(f, l, func); 604 | } 605 | }; 606 | struct max_fn 607 | { 608 | template 609 | decltype(auto) operator()(I f, I l, F func) { 610 | return std::max(f, l, func); 611 | } 612 | }; 613 | struct minmax_fn 614 | { 615 | template 616 | decltype(auto) operator()(I f, I l, F func) { 617 | return std::minmax(f, l, func); 618 | } 619 | }; 620 | struct min_element_fn 621 | { 622 | template 623 | decltype(auto) operator()(I f, I l, F func) { 624 | return std::min_element(f, l, func); 625 | } 626 | }; 627 | struct max_element_fn 628 | { 629 | template 630 | decltype(auto) operator()(I f, I l, F func) { 631 | return std::max_element(f, l, func); 632 | } 633 | }; 634 | struct minmax_element_fn 635 | { 636 | template 637 | decltype(auto) operator()(I f, I l, F func) { 638 | return std::minmax_element(f, l, func); 639 | } 640 | }; 641 | struct lexicographical_compare_fn 642 | { 643 | template 644 | decltype(auto) operator()(I f, I l, F func) { 645 | return std::lexicographical_compare(f, l, func); 646 | } 647 | }; 648 | struct next_permutation_fn 649 | { 650 | template 651 | decltype(auto) operator()(I f, I l, F func) { 652 | return std::next_permutation(f, l, func); 653 | } 654 | }; 655 | struct prev_permutation_fn 656 | { 657 | template 658 | decltype(auto) operator()(I f, I l, F func) { 659 | return std::prev_permutation(f, l, func); 660 | } 661 | }; 662 | struct begin_fn 663 | { 664 | template 665 | decltype(auto) operator()(C&& c) { 666 | return std::begin(std::forward(c)); 667 | } 668 | }; 669 | struct end_fn 670 | { 671 | template 672 | decltype(auto) operator()(C&& c) { 673 | return std::end(std::forward(c)); 674 | } 675 | }; 676 | } 677 | 678 | // To avoid ODR violations: 679 | template 680 | struct __static_const { 681 | static T value; 682 | }; 683 | 684 | template 685 | T __static_const::value; 686 | 687 | namespace 688 | { 689 | auto const& for_each = fn<3>(__static_const<__detail::for_each_fn>::value); 690 | auto const& begin = fn<1>(__static_const<__detail::begin_fn>::value); 691 | auto const& end = fn<1>(__static_const<__detail::end_fn>::value); 692 | } 693 | } 694 | #endif -------------------------------------------------------------------------------- /switch.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _SWITCH_HPP_ 2 | #define _SWITCH_HPP_ 3 | #include "std_wrappers.hpp" 4 | 5 | namespace curry 6 | { 7 | namespace __detail 8 | { 9 | struct switch_fn 10 | { 11 | template 12 | decltype(auto) operator()(Func&& func, Cases&&... cases) { 13 | return process(func, std::forward(cases)...); 14 | } 15 | template 16 | decltype(auto) process(unsigned int index, Case&& c, Cases&&... cases) { 17 | return index ? process(index - 1, std::forward(cases)...) : c; 18 | } 19 | template 20 | auto process(unsigned int /*index*/, Case&& c) { 21 | return c; 22 | } 23 | }; 24 | } 25 | namespace 26 | { 27 | //template 28 | auto const& switch_ = fn<5>(__static_const<__detail::switch_fn>::value); 29 | } 30 | } 31 | #endif//_SWITCH_HPP_ 32 | -------------------------------------------------------------------------------- /util/arg_category.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _ARG_CATEGORY_HPP_ 2 | #define _ARG_CATEGORY_HPP_ 3 | 4 | #include "..\util\int_list.hpp" 5 | #include "..\util\fn_fwd.hpp" 6 | #include "..\placeholders\placeholder.hpp" 7 | #include 8 | 9 | namespace curry { 10 | 11 | enum class ArgCategory { 12 | Regular, 13 | Placeholder, 14 | AppliedFunction, 15 | Function 16 | }; 17 | 18 | template 19 | struct arg_category_impl { 20 | static const ArgCategory value = ArgCategory::Regular; 21 | }; 22 | 23 | template 24 | struct arg_category_impl> { 25 | static const ArgCategory value = ArgCategory::Placeholder; 26 | }; 27 | 28 | template 29 | struct arg_category_impl, F, A...>> { 30 | static const ArgCategory value = ArgCategory::AppliedFunction; 31 | }; 32 | 33 | template 34 | struct arg_category_impl> { 35 | static const ArgCategory value = ArgCategory::Function; 36 | }; 37 | 38 | template 39 | using arg_category = 40 | std::integral_constant::type>::value>; 41 | 42 | } 43 | 44 | #endif//_ARG_CATEGORY_HPP_ -------------------------------------------------------------------------------- /util/arg_positions.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _ARG_POSITIONS_HPP_ 2 | #define _ARG_POSITIONS_HPP_ 3 | 4 | #include 5 | 6 | namespace curry { 7 | 8 | template 9 | struct arg_positions_impl; 10 | 11 | template 12 | struct arg_positions_impl, Count> { 13 | using type = typename arg_positions_impl, Result...>, Count - 1>::type; 14 | }; 15 | 16 | template 17 | struct arg_positions_impl, 0> { 18 | using type = std::tuple; 19 | }; 20 | 21 | template 22 | struct arg_positions { 23 | using type = typename arg_positions_impl, Count>::type; 24 | }; 25 | 26 | } 27 | 28 | #endif//_ARG_POSITIONS_HPP_ -------------------------------------------------------------------------------- /util/arg_start_indices.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _ARG_START_INDICES_HPP_ 2 | #define _ARG_START_INDICES_HPP_ 3 | 4 | #include "..\arity\tuple_arity.hpp" 5 | #include "..\util\int_list.hpp" 6 | #include 7 | 8 | namespace curry { 9 | 10 | template 11 | struct arg_start_indices_impl; 12 | 13 | template 14 | struct arg_start_indices_impl, RunningTotal, std::tuple> { 15 | static const int arg_start_index = RunningTotal; 16 | using type = typename arg_start_indices_impl>, arg_start_index, std::tuple>::type; 17 | }; 18 | 19 | template 20 | struct arg_start_indices_impl, RunningTotal, std::tuple, F, A...>, Rest...>> { 21 | using T = std::tuple, F, A...>; 22 | static const int arg_start_index = RunningTotal + tuple_arity>::value; 23 | using type = typename arg_start_indices_impl>, arg_start_index, std::tuple>::type; 24 | }; 25 | 26 | template 27 | struct arg_start_indices_impl, RunningTotal, std::tuple<>> { 28 | using type = std::tuple; 29 | }; 30 | 31 | template 32 | struct arg_start_indices 33 | : arg_start_indices_impl, 0, T> { 34 | }; 35 | 36 | } 37 | 38 | #endif//_ARG_START_INDICES_HPP_ 39 | -------------------------------------------------------------------------------- /util/fn_fwd.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _FN_FWD_HPP_ 2 | #define _FN_FWD_HPP_ 3 | 4 | #ifdef _MSC_FULL_VER 5 | //MSVC 2015 bug 6 | #define CONSTEXPR 7 | #else 8 | #define CONSTEXPR constexpr 9 | #endif 10 | 11 | namespace curry { 12 | 13 | template 14 | struct fn_t; 15 | 16 | template 17 | CONSTEXPR decltype(auto) fn(F&& f); 18 | 19 | template 20 | CONSTEXPR decltype(auto) fn(F&& f, A&& a, Rest&& ...rest); 21 | 22 | template 23 | CONSTEXPR decltype(auto) fn(R T::* const f, A&& ...a); 24 | 25 | template 26 | struct function_traits; 27 | 28 | template 29 | struct pointer_to_member; 30 | 31 | template 32 | struct cfn_t; 33 | 34 | } 35 | 36 | #endif//_FN_FWD_HPP_ -------------------------------------------------------------------------------- /util/get_conditionally.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _GET_CONDITIONALLY_HPP_ 2 | #define _GET_CONDITIONALLY_HPP_ 3 | 4 | #include "..\util\fn_fwd.hpp" 5 | #include "..\util\arg_category.hpp" 6 | #include "..\util\int_list.hpp" 7 | #include "..\placeholders\placeholder.hpp" 8 | #include 9 | #include 10 | 11 | namespace curry { 12 | 13 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 14 | 15 | template 16 | CONSTEXPR decltype(auto) get_conditionally(std::integral_constant, Item&& item, A&&) { 17 | return std::forward(item); 18 | } 19 | 20 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 21 | 22 | template 23 | CONSTEXPR decltype(auto) decorate_arg(std::integral_constant, A&& a) { 24 | return std::forward(a); 25 | } 26 | 27 | template 28 | CONSTEXPR decltype(auto) decorate_arg(std::integral_constant, A&& a) { 29 | return std::make_tuple(int_list(), std::forward(a._f)); 30 | } 31 | 32 | template 33 | CONSTEXPR decltype(auto) get_conditionally_impl1(std::true_type, int_list, A&& a) { 34 | return decorate_arg(arg_category(std::forward(a)))>(), std::get(std::forward(a))); 35 | } 36 | 37 | template 38 | CONSTEXPR decltype(auto) get_conditionally_impl1(std::false_type, int_list, A&&) { 39 | return ph(); 40 | } 41 | 42 | template 43 | CONSTEXPR decltype(auto) get_conditionally(std::integral_constant, ph item, A&& a) { 44 | return get_conditionally_impl1(std::integral_constant= I)>(), ArgPosition(), std::forward(a)); 45 | } 46 | 47 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 48 | 49 | template 50 | CONSTEXPR decltype(auto) add_arguments_to_function(int_list, int_list, F&& f, A&& a) { 51 | return std::make_tuple(f, std::get(std::forward(a))...); 52 | } 53 | 54 | template 55 | CONSTEXPR decltype(auto) get_conditionally_impl2(std::true_type, std::tuple, F>&& item, A&& a) { 56 | return add_arguments_to_function(ArgPosition(), typename make_int_list::type>::arity>::type(), std::get<1>(std::forward, F>>(item)), std::forward(a)); 57 | } 58 | 59 | template 60 | CONSTEXPR decltype(auto) get_conditionally_impl2(std::false_type, std::tuple, F>&& item, A&&) { 61 | return std::make_tuple(int_list(), std::get<1>(std::forward, F>>(item))); 62 | } 63 | 64 | template 65 | CONSTEXPR decltype(auto) get_conditionally(std::integral_constant, std::tuple, F> item, A&& a) { 66 | return get_conditionally_impl2(std::integral_constant= I >(), std::forward, F>>(item), std::forward(a)); 67 | } 68 | 69 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 70 | 71 | } 72 | 73 | #endif//_GET_CONDITIONALLY_HPP_ -------------------------------------------------------------------------------- /util/int_list.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _INT_LIST_HPP_ 2 | #define _INT_LIST_HPP_ 3 | 4 | #include 5 | 6 | namespace curry { 7 | 8 | template 9 | struct int_list { 10 | }; 11 | 12 | template 13 | struct make_int_list_impl; 14 | 15 | template 16 | struct make_int_list_impl, Count> { 17 | using type = typename make_int_list_impl, Count - 1>::type; 18 | }; 19 | 20 | template 21 | struct make_int_list_impl, 0> { 22 | using type = int_list; 23 | }; 24 | 25 | template 26 | struct make_int_list { 27 | using type = typename make_int_list_impl, Count>::type; 28 | }; 29 | 30 | template 31 | using indices_for = typename make_int_list::value>::type; 32 | 33 | } 34 | 35 | #endif//_INT_LIST_HPP_ -------------------------------------------------------------------------------- /util/pointer_to_member.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _POINTER_TO_MEMBER_HPP_ 2 | #define _POINTER_TO_MEMBER_HPP_ 3 | 4 | namespace curry { 5 | 6 | template 7 | struct pointer_to_member { 8 | 9 | pointer_to_member(const M& m) 10 | : _m(m) { 11 | } 12 | 13 | auto& operator()(T& t) const { 14 | return t.*_m; 15 | } 16 | 17 | const auto& operator()(const T& t) const { 18 | return t.*_m; 19 | } 20 | 21 | volatile auto& operator()(volatile T& t) const { 22 | return t.*_m; 23 | } 24 | 25 | const volatile auto& operator()(const volatile T& t) const { 26 | return t.*_m; 27 | } 28 | 29 | private: 30 | M _m; 31 | }; 32 | 33 | } 34 | 35 | #endif//_POINTER_TO_MEMBER_HPP_ 36 | -------------------------------------------------------------------------------- /util/real_arguments_before_i.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _REAL_ARGUMENTS_BEFORE_I_HPP_ 2 | #define _REAL_ARGUMENTS_BEFORE_I_HPP_ 3 | 4 | #include "..\placeholders\placeholder.hpp" 5 | #include 6 | 7 | namespace curry { 8 | 9 | template 10 | struct real_arguments_before_I_impl; 11 | 12 | template 13 | struct real_arguments_before_I_impl, I, CurrentIndex> { 14 | static const int value = 1 + real_arguments_before_I_impl, I, CurrentIndex + 1>::value; 15 | }; 16 | 17 | template 18 | struct real_arguments_before_I_impl, Rest...>, I, CurrentIndex> { 19 | static const int value = real_arguments_before_I_impl, I, CurrentIndex + 1>::value; 20 | }; 21 | 22 | template 23 | struct real_arguments_before_I_impl&, Rest...>, I, CurrentIndex> { 24 | static const int value = real_arguments_before_I_impl, I, CurrentIndex + 1>::value; 25 | }; 26 | 27 | template 28 | struct real_arguments_before_I_impl, I, I> { 29 | static const int value = 0; 30 | }; 31 | 32 | template 33 | struct real_arguments_before_I_impl, Rest...>, I, I> { 34 | static const int value = 0; 35 | }; 36 | 37 | template 38 | struct real_arguments_before_I_impl&, Rest...>, I, I> { 39 | static const int value = 0; 40 | }; 41 | 42 | template 43 | struct real_arguments_before_I_impl, I, CurrentIndex> { 44 | static const int value = 0; 45 | }; 46 | 47 | template 48 | struct real_arguments_before_I { 49 | static const int value = real_arguments_before_I_impl::value; 50 | }; 51 | 52 | } 53 | 54 | #endif//_REAL_ARGUMENTS_BEFORE_I_HPP_ 55 | --------------------------------------------------------------------------------