From b083df7e22359f2a8fd643d5d50e5a760b542b88 Mon Sep 17 00:00:00 2001 From: Adrian Kummerlaender Date: Mon, 2 Mar 2015 19:41:58 +0100 Subject: Expanded section on _templates as functions_ * added information on partial template specialization and `tav::Eval` * added title outline of remaining sections --- ...e_as_a_metaphor_for_template_metaprogramming.md | 50 +++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/articles/2015-02-27_using_scheme_as_a_metaphor_for_template_metaprogramming.md b/articles/2015-02-27_using_scheme_as_a_metaphor_for_template_metaprogramming.md index 0cde18d..4ab74ee 100644 --- a/articles/2015-02-27_using_scheme_as_a_metaphor_for_template_metaprogramming.md +++ b/articles/2015-02-27_using_scheme_as_a_metaphor_for_template_metaprogramming.md @@ -92,9 +92,57 @@ using Every = Fold< ~~~ {:.language-cpp} -If we ignore the need to explicitly declare the predicate as a _template template parameter_ i.e. as a function this example is very simmilar to its _Scheme_ equivalent. Concerning the function used to fold the list it is actually less verbose than the _Scheme_ version of `Every` as we can directly pass `tav::And` instead of wrapping it in a lambda expression, which is required in _Scheme_ because it's `and` is a macro. +If we ignore the need to explicitly declare the predicate as a _template template parameter_ i.e. as a function this example is very simmilar to its _Scheme_ equivalent. Concerning the function used to fold the list it is actually less verbose than the _Scheme_ version of `Every` as we can directly pass `tav::And` instead of wrapping it in a lambda expression as is required in _Scheme_ [^1]. + +Sadly the actual implementations of e.g. `tav::Fold` are not as easily expressed. The recursive nature of folding a list or even constructing its underlying pair based structure using the variadic `tav::List` requires partial template specializations which are not allowed for template aliases[^2]. + +~~~ +template < + template class Function, + typename Initial, + typename Pair +> +struct fold_pair { + typedef Function< + Car, + Eval>> + > type; +}; + +template < + template class Function, + typename Initial +> +struct fold_pair { + typedef Initial type; +}; +~~~ +{:.language-cpp} + +While the listing of `tav::detail::fold_pair` shows how the partial specialization of its `Pair` parameter allows recursion until the list ends[^3], it also forces us to define it's actual type in terms of a public `type` member `typedef`. Such a member type definition can lead to cluttering the code with `typename` keywords which is why [TypeAsValue] employs a simple `tav::Eval` template alias to hide all `typename *::type` constructs. + +~~~ +template < + template class Function, + typename Initial, + typename List +> +using Fold = Eval>; +~~~ +{:.language-cpp} + +Hiding member type defintions behind template aliases enables most _higher_ functionality and applications built using it's functions to be written in a reasonably minimalistic - _Scheme_ like - fashion as we can see in e.g. the listing of `Every`. This also explains why `tav::Pair` recursively defines it's own type, as we would otherwise have to be quite careful where to resolve `tav::Eval`. + +## Partial function application + +## Examples + +## Summary [^0]: ISO C++ Standard draft, N3797, § 3.9.1 _Fundamental types_, Section 7 +[^1]: `and` needs to be wrapped in anonymous function in _Scheme_ because it is not a function but a macro +[^2]: ISO C++ Standard draft, N3797, § 14.5 _Template declarations_, Section 3 +[^3]: _TypeAsValue_ currently represents _Scheme_'s empty list `'()` as `void` [appropriate article]: /article/a_look_at_compile_time_computation_in_cpp/ [ConstList]: /page/const_list/ -- cgit v1.2.3