aboutsummaryrefslogtreecommitdiff
path: root/articles
diff options
context:
space:
mode:
authorAdrian Kummerlaender2015-01-13 19:50:41 +0100
committerAdrian Kummerlaender2015-01-13 19:50:41 +0100
commitea4c18e36d502e7b7151c01a580c44534cf8f1db (patch)
tree43cb817a580aae7e81a586341e098f097bcda245 /articles
parent193abbac29b36d4c861135abc8e0c74faf0d0de8 (diff)
downloadblog_content-ea4c18e36d502e7b7151c01a580c44534cf8f1db.tar
blog_content-ea4c18e36d502e7b7151c01a580c44534cf8f1db.tar.gz
blog_content-ea4c18e36d502e7b7151c01a580c44534cf8f1db.tar.bz2
blog_content-ea4c18e36d502e7b7151c01a580c44534cf8f1db.tar.lz
blog_content-ea4c18e36d502e7b7151c01a580c44534cf8f1db.tar.xz
blog_content-ea4c18e36d502e7b7151c01a580c44534cf8f1db.tar.zst
blog_content-ea4c18e36d502e7b7151c01a580c44534cf8f1db.zip
Added second _ConstList_ example to new article draft
Diffstat (limited to 'articles')
-rw-r--r--articles/2015-01-11_a_look_at_compile_time_computation_in_cpp.md34
1 files changed, 29 insertions, 5 deletions
diff --git a/articles/2015-01-11_a_look_at_compile_time_computation_in_cpp.md b/articles/2015-01-11_a_look_at_compile_time_computation_in_cpp.md
index 25b3581..345b97f 100644
--- a/articles/2015-01-11_a_look_at_compile_time_computation_in_cpp.md
+++ b/articles/2015-01-11_a_look_at_compile_time_computation_in_cpp.md
@@ -27,15 +27,35 @@ constexpr auto map(const Cons& cons, const Function& function) {
The `foldr` implementation is also quite straightforward and simply applies a given function to each pair of the _Cons_ structure using static recursion. Note that this approach of _lambda expression based_ template metaprogramming would have been much more verbose in C++11 as many list manipulators such as `map` and `foldr` make use of C++14's _generic lambda expressions_. While the [test cases] provide a set of - in my opinion - reasonably nice list transformations and queries they also present the core problem of the particular approach taken in ConstList, as it is impossible to return lists of varying lengths depending on their contents. This pervasive limitation exists because the only way to vary types at compile time depending on values is to use these values as template parameters. That is the _Cons_ list type tree would have to be both list declaration and definition, analogously to e.g. `std::integral_constant`. Obviously this is quite different from how types and values were separated into templates and member constants in ConstList. One would have to think of types as values and templates as functions that modify those values instead.
-To summarize: The approach taken in my implementation of ConstList may be a nice exercise in template metaprogramming and writing functional style C++ code but its practical applications in compile time computation are unreasonably narrow.
+Furthermore the compilation peformance degrades noticeably when manipulating lists with more than a couple of dozen items or plainly fails to execute at compile time at all. What works in a reasonably consistent fashion are list manipulations such as this one, which evaluates down to a hard coded `1056` in GCC's Assembler output:
-## Types as values…
+~~~
+#include "list.h"
-…and templates as functions.
+int main(int, char**) {
+ const auto list = ConstList::make(1, 2, /* [...] */ 31, 32);
+
+ return ConstList::foldr(
+ ConstList::map(
+ list,
+ [](auto x) {
+ return x * 2;
+ }
+ ),
+ [](auto x, auto y){
+ return x + y;
+ },
+ 0
+ );
+}
+~~~
+{: .language-cpp}
+
+To summarize: The approach taken in my implementation of ConstList may be a nice exercise in template metaprogramming and writing functional style C++ code but its practical applications in compile time computation are unreasonably narrow.
## Spectroscopy of `constexpr`
-As was already mentioned, prior to the C++11 standard the only way to perform compile time computations was to rely on macros and template metaprogramming. While both of those can be thought of as separate functional-style languages inside C++, the `constexpr` keyword allows one to declare a normal function as _potentially executable_ at compile time. So contrary to template metaprogramming based solutions we don't have a strong guarantee that our _compile time program_ is actually evaluated at compile time and would have to look at the generated Assembler output when in doubt. Sadly this is actually not much more than what is possible in _normal_ C++ compiled by a _sufficiently smart compiler_, e.g. the listing below is evaluated at compile time by gcc without any usage of `constexpr` or template metaprogramming:
+As was already mentioned, prior to the C++11 standard the only way to perform compile time computations was to rely on macros and template metaprogramming. While both of those can be thought of as separate functional-style languages inside C++, the `constexpr` keyword allows one to declare a normal function as _potentially executable_ at compile time. So contrary to template metaprogramming based solutions we don't have a strong guarantee that our _compile time program_ is actually evaluated at compile time and would have to look at the generated Assembler output when in doubt. Sadly this is actually not much more than what is possible in _normal_ C++ compiled by a _sufficiently smart compiler_, e.g. the listing below is evaluated at compile time by GCC without any usage of `constexpr` or template metaprogramming:
~~~
int example(int x) {
@@ -58,7 +78,7 @@ int main(int, char**) {
~~~
{: .language-cpp}
-Where the verbose Assembler output is aquired as follows (note that the same command also works for Clang):
+Where the verbose Assembler output is acquired as follows (note that the same command also works for Clang):
~~~
> g++ -S -fverbose-asm -O2 example.cc -o example.asm
@@ -67,6 +87,10 @@ Where the verbose Assembler output is aquired as follows (note that the same com
~~~
{: .language-sh}
+## Types as values…
+
+…and templates as functions.
+
[proof]: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.14.3670
[ConstList]: /page/const_list/
[test cases]: https://github.com/KnairdA/ConstList/blob/master/test.cc