diff options
author | Adrian Kummerlaender | 2015-01-25 20:35:38 +0100 |
---|---|---|
committer | Adrian Kummerlaender | 2015-01-25 20:35:38 +0100 |
commit | 8b6de4c8c89d31c5d0e16548767ef21f242aadd1 (patch) | |
tree | 021f5dc4b7c72114614bdfe38065ad962ec5d4f9 | |
parent | 4f2aa4218ec63107b4624e576ff391c2019690a1 (diff) | |
download | TypeAsValue-8b6de4c8c89d31c5d0e16548767ef21f242aadd1.tar TypeAsValue-8b6de4c8c89d31c5d0e16548767ef21f242aadd1.tar.gz TypeAsValue-8b6de4c8c89d31c5d0e16548767ef21f242aadd1.tar.bz2 TypeAsValue-8b6de4c8c89d31c5d0e16548767ef21f242aadd1.tar.lz TypeAsValue-8b6de4c8c89d31c5d0e16548767ef21f242aadd1.tar.xz TypeAsValue-8b6de4c8c89d31c5d0e16548767ef21f242aadd1.tar.zst TypeAsValue-8b6de4c8c89d31c5d0e16548767ef21f242aadd1.zip |
Implemented partial function application prototype
* function `Apply` enables partial supply of the template parameters of a given _function_
** unsupplied parameters may be marked by _placeholders_, i.e. approach is similar to `std::bind`
** returns a template type taking the remaining, unsupplied parameters of the partially applied _function_
* this is a prototype in the sense, that neither full application using `Apply` or partial application of higher order functions is currently supported
** e.g. a `single_type` alias type declaration is required as the variadic template `template<typename...>` doesn't directly map to `template<typename>`
* appropriate test cases document current feature set
* the goal is to enable a concise defintion of _lambda-like_ expressions for easy specialization of e.g. functors provided to higher order functions
-rw-r--r-- | src/function/apply.h | 64 | ||||
-rw-r--r-- | test.cc | 23 |
2 files changed, 87 insertions, 0 deletions
diff --git a/src/function/apply.h b/src/function/apply.h new file mode 100644 index 0000000..d353169 --- /dev/null +++ b/src/function/apply.h @@ -0,0 +1,64 @@ +#ifndef TYPEASVALUE_SRC_FUNCTION_APPLY_H_ +#define TYPEASVALUE_SRC_FUNCTION_APPLY_H_ + +#include <type_traits> + +namespace tav { + +namespace detail { + +struct placeholder_tag { }; + +template <typename Type> +using is_placeholder = tav::Boolean< + std::is_base_of<placeholder_tag, Type>::value +>; + +template <int Index> +struct placeholder : placeholder_tag { }; + +template < + typename Partials, + typename Argument +> +struct resolve_placeholder { + typedef Argument type; +}; + +template < + typename Partials, + int Index +> +struct resolve_placeholder<Partials, placeholder<Index>> { + typedef typename Nth<Size<Index>, Partials>::type type; +}; + +} + +typedef detail::placeholder<0> _0; +typedef detail::placeholder<1> _1; +typedef detail::placeholder<2> _2; +typedef detail::placeholder<3> _3; + +template < + template<typename...> class Function, + typename... Arguments +> +struct Apply { + typedef typename tav::List<Arguments...>::type argument_list; + + template <typename... Partials> + using type = Function< + typename detail::resolve_placeholder< + typename tav::List<Partials...>::type, + Arguments + >::type... + >; + + template <typename Partials> + using single_type = type<Partials>; +}; + +} + +#endif // TYPEASVALUE_SRC_FUNCTION_APPLY_H_ @@ -14,6 +14,8 @@ #include "list/generator/make_list.h" #include "list/generator/higher/list_tabulate.h" +#include "function/apply.h" + int main(int, char **) { } // equality @@ -631,3 +633,24 @@ static_assert( >::value, "(count even? (list 1 3 5)) != 0" ); + +// function apply + +static_assert( + std::is_same< + tav::Int<42>, + tav::Apply<tav::Multiply, tav::Int<21>, tav::_0>::type<tav::Int<2>>::type + >::value, + "((lambda (x) (* 21 x)) 2) != 42" +); + +static_assert( + std::is_same< + tav::List<tav::Int<10>, tav::Int<12>, tav::Int<14>>::type, + tav::Map< + tav::Apply<tav::Add, tav::_0, tav::Int<10>>::single_type, + tav::List<tav::Int<0>, tav::Int<2>, tav::Int<4>>::type + >::type + >::value, + "(map (lambda (x) (+ x 10)) (list 0 2 4)) != (list 10 12 14)" +); |