Metaprogramming and Lambda Expressions
Subjects
autoshow in cppinsightsTemplates with constants (fib,sum,array)
Template specialization
Template Metaprogramming (TMP) Physics
Lambdas
auto
vector example

list example

Fixed vector example
Lets make up a new container called fixed_vector
TODO add iterators
Specialization
Sometimes we just want to feel special 😂
notice the emty <> in template<> on then the struct SpecializedStruct<double>
There are 2 types of c++ developers:
those who like TMP
and those who don't
Template metaprogramming
Template metaprogramming (TMP) in C++ is a technique for expressing and executing arbitrary algorithms in compile-time using C++ templates.
TMP is a form of declarative programming in which the logic of computation is expressed without the use of explicit control flow statements (if, else, for). Some of these languages include SQL,cypher and sparql
So remember:
no mutability
no virtual functions
no RTTI,etc.
Sum recursion


The run-time isn't the run-time but rather the compiler is the run-time.
Fibonacci recursion
VS

Show C++ Insights
more than 700x speedup (the compilation took 2x the amout so really 350x)
The entire recursion is done by the compiler, while the final program just contain a constant.
Fib with tail recursion (skip this)
The first 300 Fibonacci numbers, factored to check :)
Physics example
Velocity=sec1meter, Acceleration=sec2meter, Energy=J=sec2kg2∗meter
The code above allows us to only add + the same units.This is because they have the same m,k and s
But we can divide / and multiply * different unit
Use TMP (Template Meta-Programming) when:
A macro is not enough. You need something more complex than a macro, and you need it expanded before compiled.
Using recursive function with a predetermined number of loops. In this case the overhead of function calls and setting up stack variables can be avoided and runtime will significantly decrease.
Using loops that can be unrolled at compile time. For example hash-algorithms like MD5 and SHA1 contains well-defined block processing loops that can be unrolled with TMP.
When calculating constant values. If you have constants that depend on other constants in your program, they might be a candidate for TMP.
When the program should be portable to other platforms. In this case TMP might be an alternative to macros.
Don't use TMP when:
When a macro will do. In most cases a macro will be enough. And a macro is often easier to understand than TMP.
You want a small executable. Templates in general, and TMP in particular will in often increase the code size.
Your program already takes a long time to compile. TMP might significantly increase compile time.
You are on a strict deadline. As noted above the complier will be very unfriendly when working with Template Metaprograms. Unless the changes you intend to make are very simple, you might want to save yourself a few hours of banging your head in the wall.
Functors - Overriding Function call operator
Understanding Lambdas
What does a lambda really look like?
main- is the function, v- is void.
Here the lambda l is similar to the following struct:
Remove the double underscores to compile
Now if we were to add a int param like this
It would be similar to this
If we add a capture it would look like this:
It is similar to this:
First call the ctor with val, then call the functor with 3.
Now if we replace val with ++val wouldn't work, here is why
this is because our structs () operater is const in auto operator()(int i) const {
mutable
Now If we add the mutable specifier we would remove the const
lets use the cpp insights to see what is really happening here.
auto in param
Using auto i:
Would result to this:
Lets Review
Basically a lamba is an object.
The capture list is init list of the ctor.
The params are a functor that is by default const unless we use the keyword
mutable
Lambda syntaxes:
[ captures ] ( params ) -> ret { body }[ captures ] ( params ) { body }[ captures ] { body }
Added C++20 syntax
[ captures ] <tparams>( params ) specifiers exception-> { body }
Lambda capture
Capture Many
&: by reference=: by value
Capture individual:
&var_name: by-reference capturethis: by-reference capture of the current object
Mixing up captures:
More about lambdas
Examples of Lambdas
Next we'll use the find_if function
InputIterator find_if (InputIterator first, InputIterator last, UnaryPredicate predicate); Returns: an iterator to the first element in the range [first, last] for which pred(function) returns true
Lets change our main function to find first number greater than N. [N] denotes, can access only N by value
if we were to change it to this we would get an error
Because k cannot be implicitly captured because no default capture mode has been specified.
Finally, lets use the count_if function in our main, which will count numbers greater than or equal to N.
This code also works without spefically defining the return type ->bool on line 6.
We could clean this up to be one line:
Here we also used [=] to access all the variables by value
Last updated