<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Blog blog("Baptiste Wicht"); (Posts about C++17)</title><link>https://baptiste-wicht.com/</link><description></description><atom:link href="https://baptiste-wicht.com/categories/c%2B%2B17.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><lastBuildDate>Sun, 15 Feb 2026 06:57:39 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Decrease DLL neural network compilation time with C++17</title><link>https://baptiste-wicht.com/posts/2018/02/decrease-dll-neural-network-compilation-time-with-c%2B%2B17.html</link><dc:creator>Baptiste Wicht</dc:creator><description>&lt;p&gt;Just last week, &lt;a class="reference external" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html"&gt;I've migrated my Expression Templates Library (ETL) library to C++17&lt;/a&gt;,
it is now also done in my Deep Learning Library (DLL) library. In ETL, this
resulted in a &lt;em&gt;much nicer code overall&lt;/em&gt;, but no real improvement in compilation
time.&lt;/p&gt;
&lt;p&gt;The objective of the migration of DLL was two-fold. First, I also wanted to
simplify some code, especially with &lt;code&gt;if constexpr&lt;/code&gt;. But I also especially
wanted to try to reduce the compilation time. In the past,
&lt;a class="reference external" href="https://baptiste-wicht.com/posts/2017/09/how-i-made-deep-learning-library-38-faster-to-compile-optimization-and-cpp17-if-constexpr.html"&gt;I've already tried a few changes with C++17&lt;/a&gt;, with good results on the compilation of the entire test suite.
While this is very good, this is not very representative of users of the library.
Indeed, normally you'll have only one network in your source file not several.
The new changes will especially help in the case of many networks, but less in
the case of a single network per source file.&lt;/p&gt;
&lt;p&gt;This time, I decided to test the compilation on the examples. I've tested the
eight official examples from the DLL library:&lt;/p&gt;
&lt;ol class="arabic simple" start="0"&gt;
&lt;li&gt;&lt;p&gt;mnist_dbn: A fully-connected Deep Belief Network (DBN) on the MNIST data set
with three layers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;char_cnn: A special CNN with embeddings and merge and group layers for text
recognition&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;imagenet_cnn: A 12 layers Convolutional Neural Network (CNN) for Imagenet&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;mnist_ae: A simple two-layers auto-encoder for MNIST&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;mnist_cnn: A simple 6 layers CNN for MNIST&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;mnist_deep_ae: A deep auto-encoder for MNIST, only fully-connected&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;mnist_lstm: A Recurrent Neural Network (RNN) with Long Short Term Memory
(LSTM) cells&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;mnist_mlp: A simple fully-connected network for MNIST, with dropout&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;mnist_rnn: A simple RNN with simple cells for MNIST&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is really representative of what users can do with the library and I think
it's a much better for compilation time.&lt;/p&gt;
&lt;p&gt;For reference, you can find &lt;a class="reference external" href="https://github.com/wichtounet/dll/tree/master/examples/src"&gt;the source code of all the examples online&lt;/a&gt;.&lt;/p&gt;
&lt;section id="results"&gt;
&lt;h2&gt;Results&lt;/h2&gt;
&lt;p&gt;Let's start with the results. I've tested this at different stages of the
migration with clang 5 and GCC 7.2. I tested the following steps:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;The original C++14 version&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Simply compiling in c++17 mode (-std=c++17)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using the C++17 version of the ETL library&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Upgrading DLL to C++17 (without ETL)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ETL and DLL in C++17 versions&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I've compiled each example independently in release_debug mode. Here are the
results for G++ 7.2:&lt;/p&gt;
&lt;table class="align-center"&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th class="head"&gt;&lt;p&gt;Example&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;0&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;1&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;2&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;3&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;4&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;5&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;6&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;7&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;8&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;C++14&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;37.818&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;32.944&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;33.511&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;15.403&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;29.998&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;16.911&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;24.745&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;18.974&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;19.006&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;-std=c++17&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;38.358&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;32.409&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;32.707&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;15.810&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;30.042&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;16.896&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;24.635&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;19.134&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;19.027&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;ETL C++17&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;36.045&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;31.000&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;30.942&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;15.322&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;28.840&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;16.747&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;24.151&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;18.208&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;18.939&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;DLL C++17&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;35.251&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;32.577&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;32.854&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;15.653&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;29.758&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;16.851&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;24.606&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;19.098&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;19.146&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;Final C++17&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;32.289&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;31.133&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;30.939&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;15.232&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;28.753&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;16.526&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;24.326&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;18.116&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;17.819&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;Final Improvement&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;14.62%&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;5.49%&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;7.67%&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;1.11%&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;4.15%&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;2.27%&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;1.69%&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;4.52%&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;6.24%&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The difference by just enabling c++17 is not significant. On the other hand,
some significant gain can be obtained by using the C++17 version of ETL,
especially for the DBN version and for the CNN versions. Except for the DBN
case, the migration of DLL to C++17 did not bring any significant advantage.
When everything is combined, the gains are more important :) In the best case,
the example is 14.6% faster to compile.&lt;/p&gt;
&lt;p&gt;Let's see if it's the same with clang++ 5.0:&lt;/p&gt;
&lt;table class="align-center"&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th class="head"&gt;&lt;p&gt;Example&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;0&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;1&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;2&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;3&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;4&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;5&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;6&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;7&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;8&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;C++14&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;40.690&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;34.753&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;35.488&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;16.146&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;31.926&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;17.708&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;29.806&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;19.207&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;20.858&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;-std=c++17&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;40.502&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;34.664&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;34.990&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;16.027&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;31.510&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;17.630&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;29.465&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;19.161&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;20.860&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;ETL C++17&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;37.386&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;33.008&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;33.896&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;15.519&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;30.269&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;16.995&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;28.897&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;18.383&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;19.809&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;DLL C++17&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;37.252&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;34.592&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;35.250&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;16.131&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;31.782&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;17.606&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;29.595&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;19.126&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;20.782&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;Final C++17&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;34.470&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;33.154&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;33.881&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;15.415&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;30.279&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;17.078&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;28.808&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;18.497&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;19.761&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;Final Improvement&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;15.28%&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;4.60%&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;4.52%&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;4.52%&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;5.15%&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;3.55%&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;3.34%&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;3.69%&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;5.25%&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;First of all, as I have seen time after time, clang is still slower than GCC.
It's a not a big difference, but still significant. Overall, the gains are a bit
higher on clang than on GCC, but not by much. Interestingly, the migration of
DLL to C++17 is less interesting in terms of compilation time for clang. It
seems even to slow down compilation on some examples. On the other hand, the
migration of ETL is more important than on GCC.&lt;/p&gt;
&lt;p&gt;Overall, every example is faster to compile using both libraries in C++17, but
we don't have spectacular speed-ups. With clang, we have speedups from 3.3% to
15.3%. With GCC, we have speedup  from 1.1% to 14.6%. It's not very high, but
I'm already satisfied with these results.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="c-17-in-dll"&gt;
&lt;h2&gt;C++17 in DLL&lt;/h2&gt;
&lt;p&gt;Overall, the migration of DLL to C++17 was quite similar to that of ETL. You can
take a look at my &lt;a class="reference external" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html"&gt;previous article&lt;/a&gt;
if you want more details on C++17 features I've used.&lt;/p&gt;
&lt;p&gt;I've &lt;em&gt;replaced a lot of SFINAE functions&lt;/em&gt; with &lt;code&gt;if constexpr&lt;/code&gt;. I've also
replaced a lot of &lt;code&gt;statif_if&lt;/code&gt; with &lt;code&gt;if constexpr&lt;/code&gt;. There was a large
number of these in DLL's code. I also enabled all the &lt;code&gt;constexpr&lt;/code&gt; that
were commented for this exact time :)&lt;/p&gt;
&lt;p&gt;I was also thinking that I could replace a lot of meta-programming stuff with
&lt;em&gt;fold expressions&lt;/em&gt;. While I was able to replace a few of them, most of them were
harder to replace with fold expressions. Indeed, the variadic pack is often
hidden behind another class and therefore the pack is not directly usable from
the network class or the group and merge layers classes. I didn't want to start
a big refactoring just to use a C++17 feature, the current state of this code is
fine.&lt;/p&gt;
&lt;p&gt;I made some use of structured bindings as well, but again not as much as I was
thinking. In fact, a lot of time, I'm assigning the elements of a pair or tuple
to existing variables not declaring new variables and unfortunately, you can
only use structured bindings with &lt;code&gt;auto&lt;/code&gt; declaration.&lt;/p&gt;
&lt;p&gt;Overall, the &lt;em&gt;code is significantly better now&lt;/em&gt;, but there was less impact than
there was on ETL. It's also a smaller code base, so maybe this is normal and my
expectations were too high ;)&lt;/p&gt;
&lt;/section&gt;
&lt;section id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The trunk of DLL is now a C++17 library :) I think this improve the quality of
the code by a nice margin! Even though, there is still some work to be done to
improve the code, especially for the DBN pretraining code, the quality is quite
good now. Moreover, the switch to C++17 made the compilation of neural networks
using the DLL library &lt;em&gt;faster to compile&lt;/em&gt;, from 1.1% in the worst case to 15.3% in
the best case! I don't know when I will release the next version of DLL, but it
will take some time. I'll especially have to polish the RNN support and add
a sequence to sequence loss before I will release the 1.1 version of DLL.&lt;/p&gt;
&lt;p&gt;I'm quite satisfied with C++17 even if I would have liked a bit more features to
play with! I'm already a big fan of &lt;code&gt;if constexpr&lt;/code&gt;, this can make the code
much nicer and fold expressions are much more intuitive than their previous
recursive template counterpart.&lt;/p&gt;
&lt;p&gt;I may also consider migrating some parts of the cpp-utils library, but if I do,
it will only be through the use of conditionals in order not to break the other
projects that are based on the library.&lt;/p&gt;
&lt;/section&gt;</description><category>C++</category><category>C++17</category><category>clang</category><category>Compilers</category><category>Deep Learning</category><category>dll</category><category>etl</category><category>gcc</category><category>Machine Learning</category><category>Performance</category><category>projects</category><guid>https://baptiste-wicht.com/posts/2018/02/decrease-dll-neural-network-compilation-time-with-c%2B%2B17.html</guid><pubDate>Wed, 07 Feb 2018 10:39:02 GMT</pubDate></item><item><title>C++17 Migration of Expression Templates Library (ETL)</title><link>https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html</link><dc:creator>Baptiste Wicht</dc:creator><description>&lt;p&gt;I've finally decided to migrate my Expression Templates Library (ETL) project to
C++17. I've talking about doing that for a long time and I've released several
releases without doing the change, but the next version will be a C++17 library.
The reason why I didn't want to rush the change was that this means the library
needs a very recent compiler that may not be available to everybody. Indeed,
after this change, the ETL library now needs at least GCC 7.1 or Clang 4.0.&lt;/p&gt;
&lt;p&gt;I've already made some previous experiments in the past. For instance,
&lt;a class="reference external" href="https://baptiste-wicht.com/posts/2017/09/how-i-made-deep-learning-library-38-faster-to-compile-optimization-and-cpp17-if-constexpr.html"&gt;by using if constexpr, I've managed to speed up compilation by 38%&lt;/a&gt; and I've also written an article about &lt;a class="reference external" href="https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html"&gt;the fold expressions introduced in C++17&lt;/a&gt;. But I haven't migrated a full library yet. This is now done with ETL. In this article, I'll try to give some example of improvements by using C++17.&lt;/p&gt;
&lt;p&gt;This will only cover the C++17 features I'm using in the updated ETL library,
I won't cover all of the new C++17 features.&lt;/p&gt;
&lt;section id="if-constexpr"&gt;
&lt;h2&gt;if constexpr&lt;/h2&gt;
&lt;p&gt;The most exciting new thing in C++17 for me is the &lt;code&gt;if constexpr&lt;/code&gt;
statement. This is a really really great thing. In essence, it's a normal
&lt;code&gt;if&lt;/code&gt; statement, but with one very important difference. The statement that
is not taken (the &lt;code&gt;else&lt;/code&gt; if the condition is true, or the &lt;code&gt;if
constexpr&lt;/code&gt; if the condition is false) is &lt;em&gt;discarded&lt;/em&gt;. And what is interesting
is what happens to &lt;em&gt;discarded&lt;/em&gt; statements:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;The body of a &lt;em&gt;discarded&lt;/em&gt; statement does not participate in return type
deduction.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The discarded statement is not instantiated&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The discarded statement can &lt;em&gt;odr-use&lt;/em&gt; a variable that is not defined&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Personally, I'm especially interested by points 1 and 2. Let's start with an
example where point 1 is useful. In ETL, I have a make_temporary function. This
function either forwards an ETL container or creates a temporary container from
an ETL expression. This is based on a compile-time traits. The return type of
the function is the not the same in both cases. What you did in those case
before C++17, is use SFINAE and make two functions:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code cpp"&gt;&lt;a id="rest_code_d048c260ae3644b9b0a6d0e95b472d3b-1" name="rest_code_d048c260ae3644b9b0a6d0e95b472d3b-1" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_d048c260ae3644b9b0a6d0e95b472d3b-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cpp_enable_iff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_dma&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;a id="rest_code_d048c260ae3644b9b0a6d0e95b472d3b-2" name="rest_code_d048c260ae3644b9b0a6d0e95b472d3b-2" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_d048c260ae3644b9b0a6d0e95b472d3b-2"&gt;&lt;/a&gt;&lt;span class="k"&gt;decltype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;make_temporary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_d048c260ae3644b9b0a6d0e95b472d3b-3" name="rest_code_d048c260ae3644b9b0a6d0e95b472d3b-3" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_d048c260ae3644b9b0a6d0e95b472d3b-3"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;forward&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_d048c260ae3644b9b0a6d0e95b472d3b-4" name="rest_code_d048c260ae3644b9b0a6d0e95b472d3b-4" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_d048c260ae3644b9b0a6d0e95b472d3b-4"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;a id="rest_code_d048c260ae3644b9b0a6d0e95b472d3b-5" name="rest_code_d048c260ae3644b9b0a6d0e95b472d3b-5" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_d048c260ae3644b9b0a6d0e95b472d3b-5"&gt;&lt;/a&gt;
&lt;a id="rest_code_d048c260ae3644b9b0a6d0e95b472d3b-6" name="rest_code_d048c260ae3644b9b0a6d0e95b472d3b-6" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_d048c260ae3644b9b0a6d0e95b472d3b-6"&gt;&lt;/a&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cpp_enable_iff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;is_dma&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;a id="rest_code_d048c260ae3644b9b0a6d0e95b472d3b-7" name="rest_code_d048c260ae3644b9b0a6d0e95b472d3b-7" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_d048c260ae3644b9b0a6d0e95b472d3b-7"&gt;&lt;/a&gt;&lt;span class="k"&gt;decltype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;make_temporary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_d048c260ae3644b9b0a6d0e95b472d3b-8" name="rest_code_d048c260ae3644b9b0a6d0e95b472d3b-8" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_d048c260ae3644b9b0a6d0e95b472d3b-8"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;force_temporary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;forward&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;a id="rest_code_d048c260ae3644b9b0a6d0e95b472d3b-9" name="rest_code_d048c260ae3644b9b0a6d0e95b472d3b-9" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_d048c260ae3644b9b0a6d0e95b472d3b-9"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;One version of the function will forward and the other version will force
a temporary and the return type can be different since these are two different
functions. This is not bad, but still requires two functions where you only want
to write one. However, in C++17, we can do much better using &lt;code&gt;if constexpr&lt;/code&gt;:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code cpp"&gt;&lt;a id="rest_code_cc4391c829bb47b3a70aeaba7245c2bc-1" name="rest_code_cc4391c829bb47b3a70aeaba7245c2bc-1" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_cc4391c829bb47b3a70aeaba7245c2bc-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;E&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;a id="rest_code_cc4391c829bb47b3a70aeaba7245c2bc-2" name="rest_code_cc4391c829bb47b3a70aeaba7245c2bc-2" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_cc4391c829bb47b3a70aeaba7245c2bc-2"&gt;&lt;/a&gt;&lt;span class="k"&gt;decltype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;make_temporary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_cc4391c829bb47b3a70aeaba7245c2bc-3" name="rest_code_cc4391c829bb47b3a70aeaba7245c2bc-3" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_cc4391c829bb47b3a70aeaba7245c2bc-3"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;constexpr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_dma&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_cc4391c829bb47b3a70aeaba7245c2bc-4" name="rest_code_cc4391c829bb47b3a70aeaba7245c2bc-4" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_cc4391c829bb47b3a70aeaba7245c2bc-4"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;forward&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_cc4391c829bb47b3a70aeaba7245c2bc-5" name="rest_code_cc4391c829bb47b3a70aeaba7245c2bc-5" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_cc4391c829bb47b3a70aeaba7245c2bc-5"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_cc4391c829bb47b3a70aeaba7245c2bc-6" name="rest_code_cc4391c829bb47b3a70aeaba7245c2bc-6" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_cc4391c829bb47b3a70aeaba7245c2bc-6"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;force_temporary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;forward&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;a id="rest_code_cc4391c829bb47b3a70aeaba7245c2bc-7" name="rest_code_cc4391c829bb47b3a70aeaba7245c2bc-7" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_cc4391c829bb47b3a70aeaba7245c2bc-7"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;a id="rest_code_cc4391c829bb47b3a70aeaba7245c2bc-8" name="rest_code_cc4391c829bb47b3a70aeaba7245c2bc-8" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_cc4391c829bb47b3a70aeaba7245c2bc-8"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I think this version is really superior to the previous one. We only have one
function and the logic is much clearer!&lt;/p&gt;
&lt;p&gt;Let's now see an advantage of the point 2. In ETL, there are two kinds of
matrices, matrices with compile-time dimensions (fast matrices) and matrices
with runtime dimensions (dynamic matrices). When they are used, for instance for
a matrix-multiplication, I use static assertions for fast matrices and runtime
assertions for dynamic matrices. Here is an example for the validation of the
matrix-matrix multiplication:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code cpp"&gt;&lt;a id="rest_code_8faa01fd6b58442989f5edb44c3f654a-1" name="rest_code_8faa01fd6b58442989f5edb44c3f654a-1" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_8faa01fd6b58442989f5edb44c3f654a-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;C&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cpp_disable_iff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;all_fast&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;a id="rest_code_8faa01fd6b58442989f5edb44c3f654a-2" name="rest_code_8faa01fd6b58442989f5edb44c3f654a-2" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_8faa01fd6b58442989f5edb44c3f654a-2"&gt;&lt;/a&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_8faa01fd6b58442989f5edb44c3f654a-3" name="rest_code_8faa01fd6b58442989f5edb44c3f654a-3" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_8faa01fd6b58442989f5edb44c3f654a-3"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;static_assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;all_2d&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Matrix multiplication needs matrices"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_8faa01fd6b58442989f5edb44c3f654a-4" name="rest_code_8faa01fd6b58442989f5edb44c3f654a-4" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_8faa01fd6b58442989f5edb44c3f654a-4"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;cpp_assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;a id="rest_code_8faa01fd6b58442989f5edb44c3f654a-5" name="rest_code_8faa01fd6b58442989f5edb44c3f654a-5" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_8faa01fd6b58442989f5edb44c3f654a-5"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="c1"&gt;//interior dimensions&lt;/span&gt;
&lt;a id="rest_code_8faa01fd6b58442989f5edb44c3f654a-6" name="rest_code_8faa01fd6b58442989f5edb44c3f654a-6" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_8faa01fd6b58442989f5edb44c3f654a-6"&gt;&lt;/a&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;//exterior dimension 1&lt;/span&gt;
&lt;a id="rest_code_8faa01fd6b58442989f5edb44c3f654a-7" name="rest_code_8faa01fd6b58442989f5edb44c3f654a-7" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_8faa01fd6b58442989f5edb44c3f654a-7"&gt;&lt;/a&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;//exterior dimension 2&lt;/span&gt;
&lt;a id="rest_code_8faa01fd6b58442989f5edb44c3f654a-8" name="rest_code_8faa01fd6b58442989f5edb44c3f654a-8" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_8faa01fd6b58442989f5edb44c3f654a-8"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s"&gt;"Invalid sizes for multiplication"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_8faa01fd6b58442989f5edb44c3f654a-9" name="rest_code_8faa01fd6b58442989f5edb44c3f654a-9" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_8faa01fd6b58442989f5edb44c3f654a-9"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;cpp_unused&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_8faa01fd6b58442989f5edb44c3f654a-10" name="rest_code_8faa01fd6b58442989f5edb44c3f654a-10" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_8faa01fd6b58442989f5edb44c3f654a-10"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;cpp_unused&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_8faa01fd6b58442989f5edb44c3f654a-11" name="rest_code_8faa01fd6b58442989f5edb44c3f654a-11" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_8faa01fd6b58442989f5edb44c3f654a-11"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;cpp_unused&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_8faa01fd6b58442989f5edb44c3f654a-12" name="rest_code_8faa01fd6b58442989f5edb44c3f654a-12" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_8faa01fd6b58442989f5edb44c3f654a-12"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;a id="rest_code_8faa01fd6b58442989f5edb44c3f654a-13" name="rest_code_8faa01fd6b58442989f5edb44c3f654a-13" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_8faa01fd6b58442989f5edb44c3f654a-13"&gt;&lt;/a&gt;
&lt;a id="rest_code_8faa01fd6b58442989f5edb44c3f654a-14" name="rest_code_8faa01fd6b58442989f5edb44c3f654a-14" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_8faa01fd6b58442989f5edb44c3f654a-14"&gt;&lt;/a&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;C&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cpp_enable_iff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;all_fast&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;a id="rest_code_8faa01fd6b58442989f5edb44c3f654a-15" name="rest_code_8faa01fd6b58442989f5edb44c3f654a-15" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_8faa01fd6b58442989f5edb44c3f654a-15"&gt;&lt;/a&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_8faa01fd6b58442989f5edb44c3f654a-16" name="rest_code_8faa01fd6b58442989f5edb44c3f654a-16" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_8faa01fd6b58442989f5edb44c3f654a-16"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;static_assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;all_2d&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Matrix multiplication needs matrices"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_8faa01fd6b58442989f5edb44c3f654a-17" name="rest_code_8faa01fd6b58442989f5edb44c3f654a-17" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_8faa01fd6b58442989f5edb44c3f654a-17"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;static_assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;a id="rest_code_8faa01fd6b58442989f5edb44c3f654a-18" name="rest_code_8faa01fd6b58442989f5edb44c3f654a-18" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_8faa01fd6b58442989f5edb44c3f654a-18"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="c1"&gt;//interior dimensions&lt;/span&gt;
&lt;a id="rest_code_8faa01fd6b58442989f5edb44c3f654a-19" name="rest_code_8faa01fd6b58442989f5edb44c3f654a-19" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_8faa01fd6b58442989f5edb44c3f654a-19"&gt;&lt;/a&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;//exterior dimension 1&lt;/span&gt;
&lt;a id="rest_code_8faa01fd6b58442989f5edb44c3f654a-20" name="rest_code_8faa01fd6b58442989f5edb44c3f654a-20" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_8faa01fd6b58442989f5edb44c3f654a-20"&gt;&lt;/a&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;//exterior dimension 2&lt;/span&gt;
&lt;a id="rest_code_8faa01fd6b58442989f5edb44c3f654a-21" name="rest_code_8faa01fd6b58442989f5edb44c3f654a-21" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_8faa01fd6b58442989f5edb44c3f654a-21"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s"&gt;"Invalid sizes for multiplication"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_8faa01fd6b58442989f5edb44c3f654a-22" name="rest_code_8faa01fd6b58442989f5edb44c3f654a-22" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_8faa01fd6b58442989f5edb44c3f654a-22"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;cpp_unused&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_8faa01fd6b58442989f5edb44c3f654a-23" name="rest_code_8faa01fd6b58442989f5edb44c3f654a-23" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_8faa01fd6b58442989f5edb44c3f654a-23"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;cpp_unused&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_8faa01fd6b58442989f5edb44c3f654a-24" name="rest_code_8faa01fd6b58442989f5edb44c3f654a-24" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_8faa01fd6b58442989f5edb44c3f654a-24"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;cpp_unused&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_8faa01fd6b58442989f5edb44c3f654a-25" name="rest_code_8faa01fd6b58442989f5edb44c3f654a-25" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_8faa01fd6b58442989f5edb44c3f654a-25"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Again, we use SFINAE to distinguish the two different cases. In that case, we
cannot use a normal &lt;code&gt;if&lt;/code&gt; since the value of the dimensions cannot be taken
at compile-time for dynamic matrices, more precisely, some templates cannot be
instantiated for dynamic matrices. As for the cpp_unused, we have to use for the
static version because we don't use them and for the dynamic version because
they won't be used if the assertions are not enabled. Let's use &lt;code&gt;if constexpr&lt;/code&gt; to avoid having two functions:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code cpp"&gt;&lt;a id="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-1" name="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-1" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_b5ecdf979fac451bb2d5d62f3fff1056-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;C&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;a id="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-2" name="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-2" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_b5ecdf979fac451bb2d5d62f3fff1056-2"&gt;&lt;/a&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-3" name="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-3" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_b5ecdf979fac451bb2d5d62f3fff1056-3"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;static_assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;all_2d&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Matrix multiplication needs matrices"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-4" name="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-4" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_b5ecdf979fac451bb2d5d62f3fff1056-4"&gt;&lt;/a&gt;
&lt;a id="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-5" name="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-5" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_b5ecdf979fac451bb2d5d62f3fff1056-5"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;constexpr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;all_fast&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-6" name="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-6" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_b5ecdf979fac451bb2d5d62f3fff1056-6"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;static_assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="c1"&gt;//interior dimensions&lt;/span&gt;
&lt;a id="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-7" name="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-7" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_b5ecdf979fac451bb2d5d62f3fff1056-7"&gt;&lt;/a&gt;&lt;span class="w"&gt;                          &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;//exterior dimension 1&lt;/span&gt;
&lt;a id="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-8" name="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-8" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_b5ecdf979fac451bb2d5d62f3fff1056-8"&gt;&lt;/a&gt;&lt;span class="w"&gt;                          &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;//exterior dimension 2&lt;/span&gt;
&lt;a id="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-9" name="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-9" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_b5ecdf979fac451bb2d5d62f3fff1056-9"&gt;&lt;/a&gt;&lt;span class="w"&gt;                      &lt;/span&gt;&lt;span class="s"&gt;"Invalid sizes for multiplication"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-10" name="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-10" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_b5ecdf979fac451bb2d5d62f3fff1056-10"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-11" name="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-11" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_b5ecdf979fac451bb2d5d62f3fff1056-11"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;cpp_assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="c1"&gt;//interior dimensions&lt;/span&gt;
&lt;a id="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-12" name="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-12" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_b5ecdf979fac451bb2d5d62f3fff1056-12"&gt;&lt;/a&gt;&lt;span class="w"&gt;                       &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;//exterior dimension 1&lt;/span&gt;
&lt;a id="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-13" name="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-13" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_b5ecdf979fac451bb2d5d62f3fff1056-13"&gt;&lt;/a&gt;&lt;span class="w"&gt;                       &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;//exterior dimension 2&lt;/span&gt;
&lt;a id="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-14" name="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-14" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_b5ecdf979fac451bb2d5d62f3fff1056-14"&gt;&lt;/a&gt;&lt;span class="w"&gt;                   &lt;/span&gt;&lt;span class="s"&gt;"Invalid sizes for multiplication"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-15" name="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-15" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_b5ecdf979fac451bb2d5d62f3fff1056-15"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;a id="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-16" name="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-16" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_b5ecdf979fac451bb2d5d62f3fff1056-16"&gt;&lt;/a&gt;
&lt;a id="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-17" name="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-17" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_b5ecdf979fac451bb2d5d62f3fff1056-17"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;cpp_unused&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-18" name="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-18" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_b5ecdf979fac451bb2d5d62f3fff1056-18"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;cpp_unused&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-19" name="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-19" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_b5ecdf979fac451bb2d5d62f3fff1056-19"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;cpp_unused&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-20" name="rest_code_b5ecdf979fac451bb2d5d62f3fff1056-20" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_b5ecdf979fac451bb2d5d62f3fff1056-20"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Since the &lt;em&gt;discarded&lt;/em&gt; won't be instantiated, we can now use a single function!
We also avoid some duplications of the first static assertion of the unused
statements. Pretty great, right ? But we can do better with C++17. Indeed, it
added a nice new attribute &lt;code&gt;[[maybe_unused]]&lt;/code&gt;. Let's see what this gives
us:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code cpp"&gt;&lt;a id="rest_code_f5b73d78c7974a7c8449df8820c31c91-1" name="rest_code_f5b73d78c7974a7c8449df8820c31c91-1" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_f5b73d78c7974a7c8449df8820c31c91-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;C&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;a id="rest_code_f5b73d78c7974a7c8449df8820c31c91-2" name="rest_code_f5b73d78c7974a7c8449df8820c31c91-2" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_f5b73d78c7974a7c8449df8820c31c91-2"&gt;&lt;/a&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;&lt;span class="n"&gt;maybe_unused&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;maybe_unused&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;maybe_unused&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_f5b73d78c7974a7c8449df8820c31c91-3" name="rest_code_f5b73d78c7974a7c8449df8820c31c91-3" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_f5b73d78c7974a7c8449df8820c31c91-3"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;static_assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;all_2d&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Matrix multiplication needs matrices"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_f5b73d78c7974a7c8449df8820c31c91-4" name="rest_code_f5b73d78c7974a7c8449df8820c31c91-4" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_f5b73d78c7974a7c8449df8820c31c91-4"&gt;&lt;/a&gt;
&lt;a id="rest_code_f5b73d78c7974a7c8449df8820c31c91-5" name="rest_code_f5b73d78c7974a7c8449df8820c31c91-5" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_f5b73d78c7974a7c8449df8820c31c91-5"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;constexpr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;all_fast&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_f5b73d78c7974a7c8449df8820c31c91-6" name="rest_code_f5b73d78c7974a7c8449df8820c31c91-6" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_f5b73d78c7974a7c8449df8820c31c91-6"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;static_assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="c1"&gt;//interior dimensions&lt;/span&gt;
&lt;a id="rest_code_f5b73d78c7974a7c8449df8820c31c91-7" name="rest_code_f5b73d78c7974a7c8449df8820c31c91-7" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_f5b73d78c7974a7c8449df8820c31c91-7"&gt;&lt;/a&gt;&lt;span class="w"&gt;                          &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;//exterior dimension 1&lt;/span&gt;
&lt;a id="rest_code_f5b73d78c7974a7c8449df8820c31c91-8" name="rest_code_f5b73d78c7974a7c8449df8820c31c91-8" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_f5b73d78c7974a7c8449df8820c31c91-8"&gt;&lt;/a&gt;&lt;span class="w"&gt;                          &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;//exterior dimension 2&lt;/span&gt;
&lt;a id="rest_code_f5b73d78c7974a7c8449df8820c31c91-9" name="rest_code_f5b73d78c7974a7c8449df8820c31c91-9" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_f5b73d78c7974a7c8449df8820c31c91-9"&gt;&lt;/a&gt;&lt;span class="w"&gt;                      &lt;/span&gt;&lt;span class="s"&gt;"Invalid sizes for multiplication"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_f5b73d78c7974a7c8449df8820c31c91-10" name="rest_code_f5b73d78c7974a7c8449df8820c31c91-10" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_f5b73d78c7974a7c8449df8820c31c91-10"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_f5b73d78c7974a7c8449df8820c31c91-11" name="rest_code_f5b73d78c7974a7c8449df8820c31c91-11" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_f5b73d78c7974a7c8449df8820c31c91-11"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;cpp_assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="c1"&gt;//interior dimensions&lt;/span&gt;
&lt;a id="rest_code_f5b73d78c7974a7c8449df8820c31c91-12" name="rest_code_f5b73d78c7974a7c8449df8820c31c91-12" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_f5b73d78c7974a7c8449df8820c31c91-12"&gt;&lt;/a&gt;&lt;span class="w"&gt;                       &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;//exterior dimension 1&lt;/span&gt;
&lt;a id="rest_code_f5b73d78c7974a7c8449df8820c31c91-13" name="rest_code_f5b73d78c7974a7c8449df8820c31c91-13" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_f5b73d78c7974a7c8449df8820c31c91-13"&gt;&lt;/a&gt;&lt;span class="w"&gt;                       &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;//exterior dimension 2&lt;/span&gt;
&lt;a id="rest_code_f5b73d78c7974a7c8449df8820c31c91-14" name="rest_code_f5b73d78c7974a7c8449df8820c31c91-14" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_f5b73d78c7974a7c8449df8820c31c91-14"&gt;&lt;/a&gt;&lt;span class="w"&gt;                   &lt;/span&gt;&lt;span class="s"&gt;"Invalid sizes for multiplication"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_f5b73d78c7974a7c8449df8820c31c91-15" name="rest_code_f5b73d78c7974a7c8449df8820c31c91-15" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_f5b73d78c7974a7c8449df8820c31c91-15"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;a id="rest_code_f5b73d78c7974a7c8449df8820c31c91-16" name="rest_code_f5b73d78c7974a7c8449df8820c31c91-16" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_f5b73d78c7974a7c8449df8820c31c91-16"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;No more need for &lt;code&gt;cpp_unused&lt;/code&gt; trick :) This attribute tells the compiler
that a variable or parameter can be sometimes unused and therefore does not lead
to a warning for it. Only one thing that is not great with this attribute is
that it's too long, 16 characters. It almost double the width of my check
function signature. Imagine if you have more parameters, you'll soon have to use
several lines. I wish there was a way to set an attribute for all parameters
together or a shortcut. I'm considering whether to use a short macro to use in
place of it, but haven't yet decided.&lt;/p&gt;
&lt;p&gt;Just a note, if you have &lt;code&gt;else if&lt;/code&gt; statements, you need to set them as
&lt;code&gt;constexpr&lt;/code&gt; as well! This was a bit weird for me, but you can figure it as
if the condition is &lt;code&gt;constexpr&lt;/code&gt;, then the &lt;code&gt;if&lt;/code&gt; (or &lt;code&gt;else if&lt;/code&gt;)
is &lt;code&gt;constexpr&lt;/code&gt; as well.&lt;/p&gt;
&lt;p&gt;Overall, I'm really satisfied with the new &lt;cite&gt;if constexpr&lt;/cite&gt;! This really makes the
code much nicer in many cases, especially if you abuse metaprogramming like
I do.&lt;/p&gt;
&lt;p&gt;You may remember that I've &lt;a class="reference external" href="https://baptiste-wicht.com/posts/2015/07/simulate-static_if-with-c11c14.html"&gt;coded a version of static if in the past with C++14&lt;/a&gt; in the past. This was able to solve point 2, but not point 1 and was much uglier. Now we have a good solution to it. I've replaced two of these in the current code with the new &lt;code&gt;if constexpr&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="fold-expressions"&gt;
&lt;h2&gt;Fold expressions&lt;/h2&gt;
&lt;p&gt;For me, fold expressions is the second major feature of C++17. I wont' go into
too much details here, since
&lt;a class="reference external" href="https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html"&gt;I've already talked about fold expression in the past&lt;/a&gt;
. But I'll show two examples of refactorings I've been able to do with this.&lt;/p&gt;
&lt;p&gt;Here was the size() function of a static matrix in ETL before:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code cpp"&gt;&lt;a id="rest_code_1633bf0d7c2943cfbafb5e13312fb649-1" name="rest_code_1633bf0d7c2943cfbafb5e13312fb649-1" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_1633bf0d7c2943cfbafb5e13312fb649-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;constexpr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_1633bf0d7c2943cfbafb5e13312fb649-2" name="rest_code_1633bf0d7c2943cfbafb5e13312fb649-2" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_1633bf0d7c2943cfbafb5e13312fb649-2"&gt;&lt;/a&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mul_all&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Dims&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_1633bf0d7c2943cfbafb5e13312fb649-3" name="rest_code_1633bf0d7c2943cfbafb5e13312fb649-3" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_1633bf0d7c2943cfbafb5e13312fb649-3"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The Dims parameter pack from the declaration of fast_matrix:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code cpp"&gt;&lt;a id="rest_code_74ab20596a3246a29dcf1674a4447f11-1" name="rest_code_74ab20596a3246a29dcf1674a4447f11-1" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_74ab20596a3246a29dcf1674a4447f11-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;ST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Dims&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;a id="rest_code_74ab20596a3246a29dcf1674a4447f11-2" name="rest_code_74ab20596a3246a29dcf1674a4447f11-2" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_74ab20596a3246a29dcf1674a4447f11-2"&gt;&lt;/a&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;fast_matrix_impl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And the mul_all is a simple helper that multiplies each value of the variadic
parameter pack:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code cpp"&gt;&lt;a id="rest_code_5bb7f4c4cac8480182fdcf2acc804619-1" name="rest_code_5bb7f4c4cac8480182fdcf2acc804619-1" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_5bb7f4c4cac8480182fdcf2acc804619-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Dims&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;a id="rest_code_5bb7f4c4cac8480182fdcf2acc804619-2" name="rest_code_5bb7f4c4cac8480182fdcf2acc804619-2" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_5bb7f4c4cac8480182fdcf2acc804619-2"&gt;&lt;/a&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;mul_all_impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;final&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;integral_constant&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mul_all_impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Dims&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;::&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{};&lt;/span&gt;
&lt;a id="rest_code_5bb7f4c4cac8480182fdcf2acc804619-3" name="rest_code_5bb7f4c4cac8480182fdcf2acc804619-3" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_5bb7f4c4cac8480182fdcf2acc804619-3"&gt;&lt;/a&gt;
&lt;a id="rest_code_5bb7f4c4cac8480182fdcf2acc804619-4" name="rest_code_5bb7f4c4cac8480182fdcf2acc804619-4" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_5bb7f4c4cac8480182fdcf2acc804619-4"&gt;&lt;/a&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;a id="rest_code_5bb7f4c4cac8480182fdcf2acc804619-5" name="rest_code_5bb7f4c4cac8480182fdcf2acc804619-5" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_5bb7f4c4cac8480182fdcf2acc804619-5"&gt;&lt;/a&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;mul_all_impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;final&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;integral_constant&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{};&lt;/span&gt;
&lt;a id="rest_code_5bb7f4c4cac8480182fdcf2acc804619-6" name="rest_code_5bb7f4c4cac8480182fdcf2acc804619-6" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_5bb7f4c4cac8480182fdcf2acc804619-6"&gt;&lt;/a&gt;
&lt;a id="rest_code_5bb7f4c4cac8480182fdcf2acc804619-7" name="rest_code_5bb7f4c4cac8480182fdcf2acc804619-7" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_5bb7f4c4cac8480182fdcf2acc804619-7"&gt;&lt;/a&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Dims&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;a id="rest_code_5bb7f4c4cac8480182fdcf2acc804619-8" name="rest_code_5bb7f4c4cac8480182fdcf2acc804619-8" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_5bb7f4c4cac8480182fdcf2acc804619-8"&gt;&lt;/a&gt;&lt;span class="k"&gt;constexpr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mul_all&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mul_all_impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Dims&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;::&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Before C++17, the only way to compute this result at compilation time was to use
template recursion, either with types or with constexpr functions. I think this
is pretty heavy only for doing a multiplication sum. Now, with fold expressions,
we can manipulate the parameter pack directly and rewrite our size function:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code cpp"&gt;&lt;a id="rest_code_f909226d2c774072b07c43027cee4afd-1" name="rest_code_f909226d2c774072b07c43027cee4afd-1" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_f909226d2c774072b07c43027cee4afd-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;constexpr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_f909226d2c774072b07c43027cee4afd-2" name="rest_code_f909226d2c774072b07c43027cee4afd-2" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_f909226d2c774072b07c43027cee4afd-2"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Dims&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...);&lt;/span&gt;
&lt;a id="rest_code_f909226d2c774072b07c43027cee4afd-3" name="rest_code_f909226d2c774072b07c43027cee4afd-3" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_f909226d2c774072b07c43027cee4afd-3"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is much better! This clearly states that each value of the parameter should
be multiplied together. For instance &lt;code&gt;1,2,3&lt;/code&gt; will become &lt;code&gt;(1*2)*3&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Another place where I was using this was to code a traits that tests if a set of
boolean are all true at compilation-time:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code cpp"&gt;&lt;a id="rest_code_1117a5fb48184e758caed786b50e9ef1-1" name="rest_code_1117a5fb48184e758caed786b50e9ef1-1" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_1117a5fb48184e758caed786b50e9ef1-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;a id="rest_code_1117a5fb48184e758caed786b50e9ef1-2" name="rest_code_1117a5fb48184e758caed786b50e9ef1-2" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_1117a5fb48184e758caed786b50e9ef1-2"&gt;&lt;/a&gt;&lt;span class="k"&gt;constexpr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;and_v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;is_same&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;
&lt;a id="rest_code_1117a5fb48184e758caed786b50e9ef1-3" name="rest_code_1117a5fb48184e758caed786b50e9ef1-3" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_1117a5fb48184e758caed786b50e9ef1-3"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;cpp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;tmp_detail&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;bool_list&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_1117a5fb48184e758caed786b50e9ef1-4" name="rest_code_1117a5fb48184e758caed786b50e9ef1-4" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_1117a5fb48184e758caed786b50e9ef1-4"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;cpp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;tmp_detail&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;bool_list&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;...,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;::&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I was using a nice trick here to test if all booleans are true. I don't remember
where I picked it up, but it's quite nice and very fast to compile.&lt;/p&gt;
&lt;p&gt;This was used for instance to test that a set of expressions are all
single-precision floating points:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code cpp"&gt;&lt;a id="rest_code_d7b89cc7418b4ec7967a3ce60f05afcd-1" name="rest_code_d7b89cc7418b4ec7967a3ce60f05afcd-1" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_d7b89cc7418b4ec7967a3ce60f05afcd-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;a id="rest_code_d7b89cc7418b4ec7967a3ce60f05afcd-2" name="rest_code_d7b89cc7418b4ec7967a3ce60f05afcd-2" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_d7b89cc7418b4ec7967a3ce60f05afcd-2"&gt;&lt;/a&gt;&lt;span class="k"&gt;constexpr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;all_single_precision&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;and_v&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_single_precision&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)...&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now, we can get rid of the and_v traits and use directly the parameter pack
directly:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code cpp"&gt;&lt;a id="rest_code_2e9c377eb341487b8d4dc0f1bc8596ff-1" name="rest_code_2e9c377eb341487b8d4dc0f1bc8596ff-1" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_2e9c377eb341487b8d4dc0f1bc8596ff-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;a id="rest_code_2e9c377eb341487b8d4dc0f1bc8596ff-2" name="rest_code_2e9c377eb341487b8d4dc0f1bc8596ff-2" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_2e9c377eb341487b8d4dc0f1bc8596ff-2"&gt;&lt;/a&gt;&lt;span class="k"&gt;constexpr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;all_single_precision&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_single_precision&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I think using fold expressions results in much clearer syntax and better code
and it's a pretty nice feature overall :)&lt;/p&gt;
&lt;p&gt;As a note here, I'd like to mention, that you can also use this syntax to call
a function on each argument that you have, which makes for much nicer syntax as
well and I'll be using that in DLL once I migrate it to C++17.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="miscellaneous"&gt;
&lt;h2&gt;Miscellaneous&lt;/h2&gt;
&lt;p&gt;There are also a few more C++17 features that I've used to improve ETL, but that
have a bit less impact.&lt;/p&gt;
&lt;p&gt;A very nice feature of C++17 is the support for structured bindings. Often you
end up with a function that returns several parts of information in the form of
a pair or a tuple or even a fixed-size array. You can use an object for this,
but if you don't, you end up with code that is not terribly nice:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code cpp"&gt;&lt;a id="rest_code_28b0de5a904a4b1095556ede1fff1ab8-1" name="rest_code_28b0de5a904a4b1095556ede1fff1ab8-1" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_28b0de5a904a4b1095556ede1fff1ab8-1"&gt;&lt;/a&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_28b0de5a904a4b1095556ede1fff1ab8-2" name="rest_code_28b0de5a904a4b1095556ede1fff1ab8-2" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_28b0de5a904a4b1095556ede1fff1ab8-2"&gt;&lt;/a&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_28b0de5a904a4b1095556ede1fff1ab8-3" name="rest_code_28b0de5a904a4b1095556ede1fff1ab8-3" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_28b0de5a904a4b1095556ede1fff1ab8-3"&gt;&lt;/a&gt;&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_28b0de5a904a4b1095556ede1fff1ab8-4" name="rest_code_28b0de5a904a4b1095556ede1fff1ab8-4" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_28b0de5a904a4b1095556ede1fff1ab8-4"&gt;&lt;/a&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;tie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;my_function&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It's not terribly bad, but in these cases, you should be be hoping for something
better. With c++17, you can do better:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code cpp"&gt;&lt;a id="rest_code_5b13d0c8b01c4a4eba0c76d32142dc14-1" name="rest_code_5b13d0c8b01c4a4eba0c76d32142dc14-1" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_5b13d0c8b01c4a4eba0c76d32142dc14-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;auto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;my_function&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now you can directly use auto to deduce the types of the three variables at once
and you can get all the results in the variables at once as well :) I think this
is really nice and can really profit some projects. In ETL, I've almost no use
for this, but I'm going to be using that a bit more in DLL.&lt;/p&gt;
&lt;p&gt;Something really nice to clean up the code in C++17 is the ability to declared
nested namespaces in one line. Before, you have a nested namespace
etl::impl::standard for instance, you would do:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code cpp"&gt;&lt;a id="rest_code_b389e811c69e4e6c9bd67f236efa03d4-1" name="rest_code_b389e811c69e4e6c9bd67f236efa03d4-1" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_b389e811c69e4e6c9bd67f236efa03d4-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;namespace&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;etl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_b389e811c69e4e6c9bd67f236efa03d4-2" name="rest_code_b389e811c69e4e6c9bd67f236efa03d4-2" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_b389e811c69e4e6c9bd67f236efa03d4-2"&gt;&lt;/a&gt;&lt;span class="k"&gt;namespace&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_b389e811c69e4e6c9bd67f236efa03d4-3" name="rest_code_b389e811c69e4e6c9bd67f236efa03d4-3" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_b389e811c69e4e6c9bd67f236efa03d4-3"&gt;&lt;/a&gt;&lt;span class="k"&gt;namespace&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;standard&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_b389e811c69e4e6c9bd67f236efa03d4-4" name="rest_code_b389e811c69e4e6c9bd67f236efa03d4-4" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_b389e811c69e4e6c9bd67f236efa03d4-4"&gt;&lt;/a&gt;
&lt;a id="rest_code_b389e811c69e4e6c9bd67f236efa03d4-5" name="rest_code_b389e811c69e4e6c9bd67f236efa03d4-5" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_b389e811c69e4e6c9bd67f236efa03d4-5"&gt;&lt;/a&gt;&lt;span class="c1"&gt;// Someting inside etl::impl::standard&lt;/span&gt;
&lt;a id="rest_code_b389e811c69e4e6c9bd67f236efa03d4-6" name="rest_code_b389e811c69e4e6c9bd67f236efa03d4-6" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_b389e811c69e4e6c9bd67f236efa03d4-6"&gt;&lt;/a&gt;
&lt;a id="rest_code_b389e811c69e4e6c9bd67f236efa03d4-7" name="rest_code_b389e811c69e4e6c9bd67f236efa03d4-7" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_b389e811c69e4e6c9bd67f236efa03d4-7"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// end of namespace standard&lt;/span&gt;
&lt;a id="rest_code_b389e811c69e4e6c9bd67f236efa03d4-8" name="rest_code_b389e811c69e4e6c9bd67f236efa03d4-8" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_b389e811c69e4e6c9bd67f236efa03d4-8"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// end of namespace impl&lt;/span&gt;
&lt;a id="rest_code_b389e811c69e4e6c9bd67f236efa03d4-9" name="rest_code_b389e811c69e4e6c9bd67f236efa03d4-9" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_b389e811c69e4e6c9bd67f236efa03d4-9"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// end of namespace etl&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In C++17, you can do:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code cpp"&gt;&lt;a id="rest_code_9232bb817cb44fc188a23b5aaf3ec60f-1" name="rest_code_9232bb817cb44fc188a23b5aaf3ec60f-1" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_9232bb817cb44fc188a23b5aaf3ec60f-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;namespace&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;etl&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;standard&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_9232bb817cb44fc188a23b5aaf3ec60f-2" name="rest_code_9232bb817cb44fc188a23b5aaf3ec60f-2" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_9232bb817cb44fc188a23b5aaf3ec60f-2"&gt;&lt;/a&gt;
&lt;a id="rest_code_9232bb817cb44fc188a23b5aaf3ec60f-3" name="rest_code_9232bb817cb44fc188a23b5aaf3ec60f-3" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_9232bb817cb44fc188a23b5aaf3ec60f-3"&gt;&lt;/a&gt;&lt;span class="c1"&gt;// Someting inside etl::impl::standard&lt;/span&gt;
&lt;a id="rest_code_9232bb817cb44fc188a23b5aaf3ec60f-4" name="rest_code_9232bb817cb44fc188a23b5aaf3ec60f-4" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_9232bb817cb44fc188a23b5aaf3ec60f-4"&gt;&lt;/a&gt;
&lt;a id="rest_code_9232bb817cb44fc188a23b5aaf3ec60f-5" name="rest_code_9232bb817cb44fc188a23b5aaf3ec60f-5" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_9232bb817cb44fc188a23b5aaf3ec60f-5"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// end of namespace etl::impl::standard&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I think it's pretty neat :)&lt;/p&gt;
&lt;p&gt;Another very small change is the ability to use the typename keyword in place of
the class keyword when declaring template template parameters. Before, you had
to declare:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code cpp"&gt;&lt;a id="rest_code_7d0684b51552428f9869d2b46ce751f9-1" name="rest_code_7d0684b51552428f9869d2b46ce751f9-1" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_7d0684b51552428f9869d2b46ce751f9-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;X&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;now you can also use:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code cpp"&gt;&lt;a id="rest_code_af681ae932074853894c896784c04c4e-1" name="rest_code_af681ae932074853894c896784c04c4e-1" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_af681ae932074853894c896784c04c4e-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;X&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It's just some syntactic sugar, but I think it's quite nice.&lt;/p&gt;
&lt;p&gt;The last improvement that I want to talk about is one that probably very few
know about but it's pretty neat. Since C++11, you can use the &lt;code&gt;alignas(X)&lt;/code&gt;
specifier for types and objects to specify on how many bytes you want to align
these. This is pretty nice if you want to align on the stack. However, this
won't always work for dynamic memory allocation. Imagine this struct:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code cpp"&gt;&lt;a id="rest_code_c233a40a3c524a1093fadd235148b401-1" name="rest_code_c233a40a3c524a1093fadd235148b401-1" href="https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html#rest_code_c233a40a3c524a1093fadd235148b401-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;alignas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;test_struct&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you declare an object of this type on the stack, you have the guarantee that
it will be aligned on 128 bytes. However, if you use &lt;code&gt;new&lt;/code&gt; to allocate it
on the heap, you don't have such guarantee. Indeed, the problem is that 128 is
greater than the maximum default alignment. This is called an over-aligned type.
In such cases, the result will be aligned on the max alignment of your system.
Since C++17, &lt;code&gt;new&lt;/code&gt; supports aligned dynamic memory allocation of
over-aligned types. Therefore, you can use a simple &lt;code&gt;alignas&lt;/code&gt; to allocate
dynamic over-aligned types :) I need this in ETL for matrices that need to be
aligned for vectorized code. Before, I was using a larger array with some
padding in order to find an aligned element inside, but that is not very nice,
now the code is much better.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="compilation-time"&gt;
&lt;h2&gt;Compilation Time&lt;/h2&gt;
&lt;p&gt;I've done a few tests to see how much impact these news features have on
compilation time. Here, I'm doing benchmark on compiling the entire test suite
in different compilation mode, I enabled most compilation options (all GPU and
BLAS options in order to make sure almost all of the library is compiled).&lt;/p&gt;
&lt;p&gt;Since I'm a bit short on time before going to vacation, I've only gathered the
results with g++. Here are the results with G++ 7.2.0&lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;debug&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;release&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;release_debug&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;C++14&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;862s&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;1961s&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;1718s&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;C++17&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;892s&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;2018s&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;1745s&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;Difference&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;+3.4%&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;+2.9%&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;+1.5%&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Overall, I'm a bit disappointed by these results, it's around 3% slower to
compile the C++17 version than the C++14 version. I was thinking that this would
a least be as fast to compile as before. It seems that currently with G++ 7.2,
&lt;code&gt;if constexpr&lt;/code&gt; are slower to compile than the equivalent SFINAE functions.
I didn't do individual benchmarks of all the features I've migrated, therefore,
it may not be coming from &lt;code&gt;if constexpr&lt;/code&gt;, but since it's the greatest
change by far, it's the more likely candidate. Once I'll have a little more
time, after my vacations, I'll try to see if that is also the case with clang.&lt;/p&gt;
&lt;p&gt;Keep in mind that we are compiling the test suite here. The ETL test suite is
using the manual selection mode of the library in order to be able to test all
the possible implementations of each operation. This makes a considerable
difference in performance. I expect better compilation time when this is used in
automatic selection mode (the default mode). In the default mode, a lot more
code can be disabled with &lt;code&gt;if constexpr&lt;/code&gt;. I will test this next with the
DLL library which I will also migrate to C++17.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This concludes this report on the migration of my ETL library from C++14 to
C++17. Overall, I'm really satisfied with the improvement of the code, it's much
better. I'm a bit disappointed by the slight increase  (around 3%) in
compilation time, but it's not dramatic either. I'm still hoping that once it's
used in DLL, I will see a decrease in compilation, but we'll see that when I'll
be done with the migration of DLL to C++17 which may take some time since I'll
have two weeks vacation in China starting Friday.&lt;/p&gt;
&lt;p&gt;The new version is available only through the &lt;em&gt;master&lt;/em&gt; branch. It will be
released as the 1.3 version probably when I integrate some new features, but in
itself will not be released as new version. You can take a look in the
&lt;a class="reference external" href="https://github.com/wichtounet/etl"&gt;Github etl repository&lt;/a&gt; if you are interested.&lt;/p&gt;
&lt;/section&gt;</description><category>C++</category><category>C++14</category><category>C++17</category><category>etl</category><category>projects</category><guid>https://baptiste-wicht.com/posts/2018/02/c%2B%2B17-migration-of-expression-templates-library-etl.html</guid><pubDate>Fri, 02 Feb 2018 13:03:26 GMT</pubDate></item><item><title>Expression Templates Library 1.2.1: Faster GPU and new features</title><link>https://baptiste-wicht.com/posts/2018/01/expression-templates-library-121-faster-gpu-and-new-features.html</link><dc:creator>Baptiste Wicht</dc:creator><description>&lt;p&gt;Happy new year to all my dear readers!&lt;/p&gt;
&lt;p&gt;It has been a while since I've posted on this blog. I've had to serve three
weeks in the army and then I had two weeks vacation. I've been actively working
on budgetwarrior with a brand new web interface! More on that later ;)&lt;/p&gt;
&lt;p&gt;Today, I'm happy to release the version 1.2.1 of my Expression Templates Library
(ETL) project. This is a minor version but with significantly better GPU support
and a few new features and bug fixes so I decided to release it now.&lt;/p&gt;
&lt;section id="faster-gpu-support"&gt;
&lt;h2&gt;Faster GPU support&lt;/h2&gt;
&lt;p&gt;Last year, I &lt;a class="reference external" href="https://baptiste-wicht.com/posts/2017/11/advanced-gpu-patterns-optimization-in-etl.html"&gt;implemented the support for the detection of advanced GPU patterns in ETL&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This will significantly reduce the number of CUDA kernel calls that are being
launched. For instance, each of the following expressions will be evaluated
using a single GPU kernel:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code C++"&gt;&lt;a id="rest_code_e7535cefc1294756a6899aac35ad17bd-1" name="rest_code_e7535cefc1294756a6899aac35ad17bd-1" href="https://baptiste-wicht.com/posts/2018/01/expression-templates-library-121-faster-gpu-and-new-features.html#rest_code_e7535cefc1294756a6899aac35ad17bd-1"&gt;&lt;/a&gt;&lt;span class="n"&gt;yy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;
&lt;a id="rest_code_e7535cefc1294756a6899aac35ad17bd-2" name="rest_code_e7535cefc1294756a6899aac35ad17bd-2" href="https://baptiste-wicht.com/posts/2018/01/expression-templates-library-121-faster-gpu-and-new-features.html#rest_code_e7535cefc1294756a6899aac35ad17bd-2"&gt;&lt;/a&gt;&lt;span class="n"&gt;yy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;
&lt;a id="rest_code_e7535cefc1294756a6899aac35ad17bd-3" name="rest_code_e7535cefc1294756a6899aac35ad17bd-3" href="https://baptiste-wicht.com/posts/2018/01/expression-templates-library-121-faster-gpu-and-new-features.html#rest_code_e7535cefc1294756a6899aac35ad17bd-3"&gt;&lt;/a&gt;&lt;span class="n"&gt;yy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;
&lt;a id="rest_code_e7535cefc1294756a6899aac35ad17bd-4" name="rest_code_e7535cefc1294756a6899aac35ad17bd-4" href="https://baptiste-wicht.com/posts/2018/01/expression-templates-library-121-faster-gpu-and-new-features.html#rest_code_e7535cefc1294756a6899aac35ad17bd-4"&gt;&lt;/a&gt;&lt;span class="n"&gt;yy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;
&lt;a id="rest_code_e7535cefc1294756a6899aac35ad17bd-5" name="rest_code_e7535cefc1294756a6899aac35ad17bd-5" href="https://baptiste-wicht.com/posts/2018/01/expression-templates-library-121-faster-gpu-and-new-features.html#rest_code_e7535cefc1294756a6899aac35ad17bd-5"&gt;&lt;/a&gt;&lt;span class="n"&gt;yy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This makes some operation significantly faster.&lt;/p&gt;
&lt;p&gt;Moreover, I've reduced a lot the numbers of device synchronization in the
library. Especially, I've removed almost all synchronization from the
etl-gpu-blas sub library. This means that synchronization is mostly only done
when data needs to go back to the CPU. For machine learning, this means at the
end of the epoch to compute the final error. This makes a HUGE difference in
time, I didn't realize before that I was doing way too much synchronization.&lt;/p&gt;
&lt;p&gt;With these two changes, I've been able to attain &lt;em&gt;state of the art training performance on GPU&lt;/em&gt; with my Deep Learning Library (DLL) project!&lt;/p&gt;
&lt;p&gt;Moreover, I've now added for random number generations on the GPU and for
shuffle operations as well.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="new-features"&gt;
&lt;h2&gt;New Features&lt;/h2&gt;
&lt;p&gt;I've also added a few new features recently. They were especially added to
support new features in DLL.&lt;/p&gt;
&lt;p&gt;Matrices and vectors can now be normalized in order to have zero-mean and
unit-variance distribution. You can also merge matrices together. For now, there
is no GPU support, so this will use CPU anyway. I plan to fix that later.&lt;/p&gt;
&lt;p&gt;In addition to bias_batch_mean that I added before, I also added bias_batch_var
now with the variance in place of the mean. This is mainly used for Batch
Normalization in machine learning, but it may have some other usages. The GPU
support has been added as well directly.&lt;/p&gt;
&lt;p&gt;And the last feature is the support for embedding and the gradients of
embedding. Again this is totally related to machine learning, but can be very
useful as well. I haven't add the time to develop the GPU version so far, but
this will come as well.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance"&gt;
&lt;h2&gt;Performance&lt;/h2&gt;
&lt;p&gt;Nothing fancy on the CPU performance side, I only added vectorization for
hyperbolic versions. This makes &lt;em&gt;tanh much faster on CPU&lt;/em&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="bug-fixes"&gt;
&lt;h2&gt;Bug Fixes&lt;/h2&gt;
&lt;p&gt;I fixed quite a few bugs in this version, which is one of the main reason
I released it:&lt;/p&gt;
&lt;p&gt;1. When using large fast_matrix and aliasing was detected, there was a big chance of stack overflow occurring. This is now fixed by using a dynamic temporary.
1. Some assignables such sub_view did not perform any detection for aliasing. This is now fixed and aliasing is detected everywhere.
1. fast_dyn_matrix can now be correctly used with &lt;em&gt;bool&lt;/em&gt;
1. The use of iterators was not always ensuring correct CPU/GPU consistency. This is now correctly handled.
1. The 4D convolution in GPU were not using the correct flipping
1. Fix small compilation bug with sub_matrix and GPU&lt;/p&gt;
&lt;/section&gt;
&lt;section id="what-s-next"&gt;
&lt;h2&gt;What's next ?&lt;/h2&gt;
&lt;p&gt;I don't really know what will be in the next release. This should be the release
1.3. One possible idea would be to improve and review the support for sparse
matrix which is more than  poor as of now. But I'm not really motivated to
work on that :P Moreover, I'm now &lt;em&gt;actively&lt;/em&gt; working on the next release of
budgetwarrior which will probably still come this month.&lt;/p&gt;
&lt;p&gt;I'm also still hesitating in switching to C++17 for the library to make it
faster to compile. And also to clean some parts of the code. I would be able to
remove quite some SFINAE with the new &lt;em&gt;if constexpr&lt;/em&gt;, but I'm afraid this will
make the library to difficult to use since it would need at least GCC 7 or clang
3.9.&lt;/p&gt;
&lt;section id="download-etl"&gt;
&lt;h3&gt;Download ETL&lt;/h3&gt;
&lt;p&gt;You can download ETL &lt;a class="reference external" href="https://github.com/wichtounet/etl"&gt;on Github&lt;/a&gt;. If you
only interested in the 1.2.1 version, you can look at the
&lt;a class="reference external" href="https://github.com/wichtounet/etl/releases"&gt;Releases pages&lt;/a&gt; or clone the tag
1.2.1. There are several branches:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;master&lt;/em&gt; Is the eternal development branch, may not always be stable&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;stable&lt;/em&gt; Is a branch always pointing to the last tag, no development here&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For the future release, there always will tags pointing to the corresponding
commits. You can also have access to previous releases on Github or via the
release tags.&lt;/p&gt;
&lt;p&gt;The documentation is still a bit sparse. There are a few examples and the Wiki,
but there still is work to be done. If you have questions on how to use or
configure the library, please don't hesitate.&lt;/p&gt;
&lt;p&gt;Don't hesitate to comment this post if you have any comment on this library or
any question. You can also open an Issue on Github if you have a problem using
this library or propose a Pull Request if you have any contribution you'd like
to make to the library.&lt;/p&gt;
&lt;p&gt;Hope this may be useful to some of you :)&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;</description><category>C++</category><category>C++14</category><category>C++17</category><category>etl</category><category>GPU</category><category>Performance</category><category>projects</category><category>Releases</category><guid>https://baptiste-wicht.com/posts/2018/01/expression-templates-library-121-faster-gpu-and-new-features.html</guid><pubDate>Tue, 09 Jan 2018 10:06:15 GMT</pubDate></item><item><title>Expression Templates Library (ETL) 1.2 - Complete GPU support</title><link>https://baptiste-wicht.com/posts/2017/10/expression-templates-library-etl-1-2-complete-gpu-support.html</link><dc:creator>Baptiste Wicht</dc:creator><description>&lt;img alt="ETL Logo" class="align-center" src="https://baptiste-wicht.com/images/logo.png"&gt;
&lt;p&gt;I'm happy to announce the version 1.2 of my Expression Templates Library (ETL):
ETL 1.2, two months after &lt;a class="reference external" href="https://baptiste-wicht.com/posts/2017/08/expression-templates-library-etl-11.html"&gt;I released the version 1.1&lt;/a&gt;.
This version features much better GPU Support, a few new features and a lot of
changes in the internal code.&lt;/p&gt;
&lt;section id="gpu-support"&gt;
&lt;h2&gt;GPU Support&lt;/h2&gt;
&lt;p&gt;Before, only algorithms such as 4D convolution or matrix-matrix multiplication
were computed in the GPU and lots of operations were causing copies between CPU
and GPU version. Now, the support for basic operations has also been completed
and therefore, expressions like this:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code cpp"&gt;&lt;a id="rest_code_4880248f581649aeb00f8e807dac13ba-1" name="rest_code_4880248f581649aeb00f8e807dac13ba-1" href="https://baptiste-wicht.com/posts/2017/10/expression-templates-library-etl-1-2-complete-gpu-support.html#rest_code_4880248f581649aeb00f8e807dac13ba-1"&gt;&lt;/a&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sigmoid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Can be computed entirely on GPU.&lt;/p&gt;
&lt;p&gt;Each matrix and vector containers have a secondary GPU memory space.  During the
execution, the status of both memory spaces is being managed and when necessary,
copies are made between two spaces. In the best case, there should only be
initial copies to the GPU and then everything should be done on the GPU. I've
also considered using Unified Memory in place of this system, but this is
a problem for fast matrix and I'd rather not have two different systems.&lt;/p&gt;
&lt;p&gt;If you have an expression such as &lt;code&gt;c = a + b * 2&lt;/code&gt;, it can be entirely computed
on GPU, however, it will be computed in two GPU operations such as:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code cpp"&gt;&lt;a id="rest_code_f699b25ff2a042f3887ee554c01bd8f9-1" name="rest_code_f699b25ff2a042f3887ee554c01bd8f9-1" href="https://baptiste-wicht.com/posts/2017/10/expression-templates-library-etl-1-2-complete-gpu-support.html#rest_code_f699b25ff2a042f3887ee554c01bd8f9-1"&gt;&lt;/a&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;a id="rest_code_f699b25ff2a042f3887ee554c01bd8f9-2" name="rest_code_f699b25ff2a042f3887ee554c01bd8f9-2" href="https://baptiste-wicht.com/posts/2017/10/expression-templates-library-etl-1-2-complete-gpu-support.html#rest_code_f699b25ff2a042f3887ee554c01bd8f9-2"&gt;&lt;/a&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is not perfect in terms of performance but this will be done without any
copies between CPU and GPU memory. I plan to improve this system with a bit more
complex operations to avoid too many GPU operations, but there will always be
more operations than in CPU where this can easily be done in one go.&lt;/p&gt;
&lt;p&gt;There are a few expressions that are not computable on the GPU, such as random
generations. A few transformations are also not fully compatible with GPU.
Moreover, if you access an element with operators &lt;code&gt;[]&lt;/code&gt; or &lt;code&gt;()&lt;/code&gt;, this
will invalidate the GPU memory and force an update to the CPU memory.&lt;/p&gt;
&lt;p&gt;GPU operations are not implemented directly in ETL, there are coming from
various libraries. ETL is using NVIDIA CUDNN, CUFFT and CUDNN for most
algorithms. Moreover, for other operations, I've implemented a libraries with
simple GPU operations: ETL-GPU-BLAS (EGBLAS). You can have a look at
&lt;a class="reference external" href="https://github.com/wichtounet/etl-gpu-blas"&gt;egblas&lt;/a&gt; if you are interested.&lt;/p&gt;
&lt;p&gt;My Deep Learning Library (DLL) project is based on ETL and its performances are
mostly dependent on ETL's performances. Now that ETL fully supports GPU, the
GPU performance of DLL is much improved. You may remember a few weeks ago
I posted &lt;a class="reference external" href="https://baptiste-wicht.com/posts/2017/08/dll-blazing-fast-neural-network-library.html"&gt;very high CPU performance of DLL&lt;/a&gt;.
Now, I've run again the tests to see the GPU performance with DLL. Here is the
performance for training a small CNN on the MNIST data set:&lt;/p&gt;
&lt;img alt="Performances for training a Convolutional Neural Network on MNIST" class="align-center" src="https://baptiste-wicht.com/images/etl_12_dll_gpu_mnist.png"&gt;
&lt;p&gt;As you can see, the performances on GPU are now excellent. DLL's performances
are on par with Tensorflow and Keras!&lt;/p&gt;
&lt;p&gt;The next results are for training a much larger CNN on ImageNet, with the time
necessary to train a single batch:&lt;/p&gt;
&lt;img alt="Performances for training a Convolutional Neural Network on Imagenet" class="align-center" src="https://baptiste-wicht.com/images/etl_12_dll_gpu_imagenet.png"&gt;
&lt;p&gt;Again, using the new version of ETL inside DLL has led to excellent performance.
The framework is again on par with TensorFlow and Keras and faster than all the
other frameworks. The large difference between DLL and Tensorflow and Keras is
due to the inefficiency of reading the dataset in the two frameworks, so the
performance of the three framework themselves are about the same.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-changes"&gt;
&lt;h2&gt;Other Changes&lt;/h2&gt;
&lt;p&gt;The library also has a few other new features. Logarithms of base 2 and base 10
are now supported in complement to the base e that was already available before.
Categorical Cross Entropy (CCE) computation is also available now, the CCE loss
and error can be computed for one or many samples. Convolutions have also been
improved in that you can use mixed types in both the image and the kernel and
different storage order as well. Nevertheless, the most optimized version
remains the version with the same storage order and the same data type.&lt;/p&gt;
&lt;p&gt;I've also made a major change in the way implementations are selected for each
operation. The tests and the benchmark are using a system to force the selection
of an algorithm. This system is now disabled by default. This makes the
compilation much faster by default. Since it's not necessary in most cases, this
will help regular use cases of the library by compiling much faster.&lt;/p&gt;
&lt;p&gt;Overall, the support for complex numbers has been improved in ETL. There are
more routines that are supported and &lt;code&gt;etl::complex&lt;/code&gt; is better supported
throughout the code. I'll still work on this in the future to make it totally
complete.&lt;/p&gt;
&lt;p&gt;The internal code also has a few new changes. First, all traits have been
rewritten to use variable templates instead of struct traits. This makes the
code much nicer in my opinion. Moreover, I've started experimenting with C++17
&lt;code&gt;if constexpr&lt;/code&gt;. Most of the if conditions that can be transformed to if
constexpr have been annotated with comments that I can quickly enable or disable
so that I can test the impact of C++17, especially on compilation time.&lt;/p&gt;
&lt;p&gt;Finally, a few bugs have been fixed. ETL is now working better with parallel
BLAS library. There should not be issues with double parallelization in ETL and
BLAS. There was a slight bug in the Column-Major matrix-matrix multiplication
kernel. Binary operations with different types in the left and right hand sides
was also problematic with vectorization. The last bug was about GPU status in
case ETL containers were moved.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="what-s-next"&gt;
&lt;h2&gt;What's next ?&lt;/h2&gt;
&lt;p&gt;I don't yet know exactly on which features I'm going to focus for the next
version of ETL. I plan to focus a bit more in the near future on Deep Learning
Library (DLL) for which I should release the version 1.0 soon. I also plan to
start support for Recurrent Neural Networks on it, so that will take me quite
some time.&lt;/p&gt;
&lt;p&gt;Nevertheless, I'm still planning to consider the switch to C++17, since it is
&lt;a class="reference external" href="https://baptiste-wicht.com/posts/2017/09/how-i-made-deep-learning-library-38-faster-to-compile-optimization-and-cpp17-if-constexpr.html"&gt;a bit faster to compile ETL with if constexpr&lt;/a&gt;. The next version of ETL will also probably have GPU-support for
integers, at least in the cases that depend on the etl-gpu-blas library, which
is the standard operators. I also plan to improve the support for complex
numbers, especially in terms of performance and tests. Hopefully, I will have also time (and motivation)
to start working on  the sparse capabilities of ETL. It really needs much more
unit tests and the performance should be improved as well.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="download-etl"&gt;
&lt;h2&gt;Download ETL&lt;/h2&gt;
&lt;p&gt;You can download ETL &lt;a class="reference external" href="https://github.com/wichtounet/etl"&gt;on Github&lt;/a&gt;. If you
only interested in the 1.2 version, you can look at the
&lt;a class="reference external" href="https://github.com/wichtounet/etl/releases"&gt;Releases pages&lt;/a&gt; or clone the tag
1.2. There are several branches:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;master&lt;/em&gt; Is the eternal development branch, may not always be stable&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;stable&lt;/em&gt; Is a branch always pointing to the last tag, no development here&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For the future release, there always will tags pointing to the corresponding
commits. You can also have access to previous releases on Github or via the
release tags.&lt;/p&gt;
&lt;p&gt;The documentation is still a bit sparse. There are a few examples and the Wiki,
but there still is work to be done. If you have questions on how to use or
configure the library, please don't hesitate.&lt;/p&gt;
&lt;p&gt;Don't hesitate to comment this post if you have any comment on this library or
any question. You can also open an Issue on Github if you have a problem using
this library or propose a Pull Request if you have any contribution you'd like
to make to the library.&lt;/p&gt;
&lt;p&gt;Hope this may be useful to some of you :)&lt;/p&gt;
&lt;/section&gt;</description><category>C++</category><category>C++14</category><category>C++17</category><category>Compilers</category><category>dll</category><category>etl</category><category>GPU</category><category>Performance</category><category>projects</category><category>Release</category><guid>https://baptiste-wicht.com/posts/2017/10/expression-templates-library-etl-1-2-complete-gpu-support.html</guid><pubDate>Mon, 02 Oct 2017 08:49:02 GMT</pubDate></item><item><title>How I made my Deep Learning Library 38% faster to compile (Optimization and C++17 if constexpr)</title><link>https://baptiste-wicht.com/posts/2017/09/how-i-made-deep-learning-library-38-faster-to-compile-optimization-and-cpp17-if-constexpr.html</link><dc:creator>Baptiste Wicht</dc:creator><description>&lt;div&gt;&lt;p&gt;My Deep Learning Library (DLL) project is a C++ library for training and using
artificial neural networks (you can take a look at
&lt;a class="reference external" href="https://baptiste-wicht.com/posts/2017/07/update-on-deep-learning-library-dll-dropout-batch-normalization-adaptive-learning-rates.html"&gt;this post about DLL&lt;/a&gt;
if you want more information).&lt;/p&gt;
&lt;p&gt;While I made a lot of effort to make it as fast as possible to train and run
neural networks, the compilation time has been steadily going up and is becoming
quite annoying. This library is heavily templated and all the matrix operations
are done using my Expression Templates Library (ETL) which is more than
template-heavy itself.&lt;/p&gt;
&lt;p&gt;In this post, I'll present two techniques with which I've been able to reduce
the total compilation of the DLL unit tests by up to 38%.&lt;/p&gt;
&lt;p class="more"&gt;&lt;a href="https://baptiste-wicht.com/posts/2017/09/how-i-made-deep-learning-library-38-faster-to-compile-optimization-and-cpp17-if-constexpr.html"&gt;Read more…&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;</description><category>C++</category><category>C++17</category><category>clang</category><category>Compilers</category><category>dll</category><category>etl</category><category>gcc</category><category>Performance</category><category>projects</category><guid>https://baptiste-wicht.com/posts/2017/09/how-i-made-deep-learning-library-38-faster-to-compile-optimization-and-cpp17-if-constexpr.html</guid><pubDate>Thu, 21 Sep 2017 17:44:34 GMT</pubDate></item><item><title>Expression Templates Library (ETL) 1.1</title><link>https://baptiste-wicht.com/posts/2017/08/expression-templates-library-etl-11.html</link><dc:creator>Baptiste Wicht</dc:creator><description>&lt;img alt="ETL Logo" class="align-center" src="https://baptiste-wicht.com/images/logo.png"&gt;
&lt;p&gt;It took me longer than I thought, but I'm glad to announce the release of the
version 1.1 of my Expression Templates Library (ETL) project. This is a major
new release with many improvements and new features. It's been almost one month
since the last, and first, release (1.0) was released. I should have done some
minor releases in the mean time, but at least now the library is in a good shape
for major version.&lt;/p&gt;
&lt;p&gt;It may be interesting to note that my machine learning framework (DLL), based on
the ETL library, has shown to be faster than all the tested popular frameworks
(Tensorflow, Keras, Caffee, Torch, DeepLearning4J) for training various neural
networks on CPU. I'll post more details on another post on the coming weeks, but
that shows that special attention to performance has been done in this library
and that it is well adapted to machine learning.&lt;/p&gt;
&lt;p&gt;For those of you that don't follow my blog, ETL is a library providing
Expression Templates for computations on matrix and vector. For instance, if you
have three matrices A, B and C you could write C++ code like this:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code cpp"&gt;&lt;a id="rest_code_375555fb3e104251b2bc5f674dd5bf01-1" name="rest_code_375555fb3e104251b2bc5f674dd5bf01-1" href="https://baptiste-wicht.com/posts/2017/08/expression-templates-library-etl-11.html#rest_code_375555fb3e104251b2bc5f674dd5bf01-1"&gt;&lt;/a&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Or given vectors b, v, h and a matrix W, you could write code like this:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code cpp"&gt;&lt;a id="rest_code_715ea2aaf9e44c58aa38ad89da62b31b-1" name="rest_code_715ea2aaf9e44c58aa38ad89da62b31b-1" href="https://baptiste-wicht.com/posts/2017/08/expression-templates-library-etl-11.html#rest_code_715ea2aaf9e44c58aa38ad89da62b31b-1"&gt;&lt;/a&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sigmoid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;W&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The goal of such library is two-fold. First, this makes the expression more
readable and as close to math as possible. And then, it allows the library to
compute the expressions as fast as possible.  In the first case, the framework
will compute the sum using a vectorized algorithm and then compute the overall
expression using yet again vectorized code. The expression can also be computed
in parallel if the matrices are big enough. In the second case, the
vector-matrix multiplication will be computed first using either hand-code
optimized vectorized or a BLAS routine (depending on configuration options).
Then, all the expression will be executed using vectorized code.&lt;/p&gt;
&lt;section id="features"&gt;
&lt;h2&gt;Features&lt;/h2&gt;
&lt;p&gt;Many new features have been integrated into the library.&lt;/p&gt;
&lt;p&gt;The support for machine learning operations has been improved. There are now
specific helpers for machine learning in the etl::ml namespace which have names
that are standard to machine learning. A real transposed convolution has been
implemented with support for padding and stride. Batched outer product and
batched bias averaging are also now supported. The activation function support
has also been improved and the derivatives have been reviewed. The pooling
operators have also been improved with stride and padding support. Unrelated to
machine learning, 2D and 3D pooling can also be done in higher dimensional
matrix now.&lt;/p&gt;
&lt;p&gt;New functions are also available for matrices and vectors. The support for
square root has been improved with cubic root and inverse root. Support has also
been added for floor and ceil. Moreover, comparison operators are now available
as well as global functions such as approx_equals.&lt;/p&gt;
&lt;p&gt;New reductions have also been added with support for absolute sum and mean
(asum/asum) and for min_index and max_index, which returns the index of the
minimum element, respectively the maximum. Finally, argmax can now be used to
get the max index in each sub dimensions of a matrix. argmax on a vector is
equivalent to max_index.&lt;/p&gt;
&lt;p&gt;Support for shuffling has also been added. By default, shuffling a vector means
shuffling all elements and shuffling a matrix means shuffling by shuffling the
sub matrices (only the first dimension is shuffled), but shuffling a matrix as
a vector is also possible. Shuffle of two vectors or two matrices in parallel,
is also possible. In that case, the same permutation is applied to both
containers. As a side note, all operations using random generation are also
available with an addition parameter for the random generator, which can help to
improve reproducibility or simply tune the random generator.&lt;/p&gt;
&lt;p&gt;I've also included support for adapters matrices. There are adapters for
hermitian matrices, symmetric matrices and lower and upper triangular matrices.
For now, the framework does not take advantage of this information, this will be
done later, but the framework guarantee the different constrain on the content.&lt;/p&gt;
&lt;p&gt;There are also a few new more minor features. Maybe not so minor, matrices can
now be sliced into sub matrices. With that a matrix can be divided into several
sub matrices and modifying the sub matrices will modify the source matrix. The
sub matrices are available in 2D, 3D and 4D for now. There are also some other
ways of slicing matrix and vectors. It is possible to obtain a slice of its
memory or obtain a slice of its first dimension. Another new feature is that it
is now possible compute the cross product of vectors now. Matrices can be
decomposed into their Q/R decomposition rather than only their PALU
decomposition. Special support has been integrated for matrix and vectors of
booleans. In that case, they support logical operators such as and, not and or.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance"&gt;
&lt;h2&gt;Performance&lt;/h2&gt;
&lt;p&gt;I've always considered the performance of this library to be a feature itself.
I consider the library to be quite fast, especially its convolution support,
even though there is still room for improvement. Therefore, many improvements
have been made to the performance of the library since the last release. As said
before, this library was used in a machine learning framework which then proved
faster than most popular neural network frameworks on CPU. I'll present here
the most important new improvements to performance, in no real particular order,
every bit being important in my opinion.&lt;/p&gt;
&lt;p&gt;First, several operations have been optimized to be faster.&lt;/p&gt;
&lt;p&gt;Multiplication of matrices or matrices and vectors are now much faster if one of
the matrix is transposed. Instead of performing the slow transposition,
different kernels are used in order to maximize performance without doing any
transposition, although sometimes transposition is performed when it is faster.
This leads to very significant improvements, up to 10 times faster in the best
case. This is performed for vectorized kernels and also for BLAS and CUBLAS
calls. These new kernels are also directly used when matrices of different
storage order are used. For instance, multiplying a column major matrix with
a row major matrix and storing the result in a column major matrix is now much
more efficient than before. Moreover, the performance of the transpose operation
itself is also much faster than before.&lt;/p&gt;
&lt;p&gt;A lot of machine learning operations have also been highly optimized. All the
pooling and upsample operators are now parallelized and the most used kernel
(2x2 pooling) is now more optimized. 4D convolution kernels (for machine
learning) have been greatly improved. There are now very specialized vectorized
kernels for classic kernel configurations (for instance 3x3 or 5x5) and the
selection of implementations is now smarter than before. The support of padding
is now much better than before for small amount of padding. Moreover, for small
kernels the full convolution can now be evaluated using the valid convolution
kernels directly with some padding, for much faster overall performance. The
exponential operation is now vectorized which allows operations such as sigmoid
or softmax to be much faster.&lt;/p&gt;
&lt;p&gt;Matrices and vector are automatically using aligned memory. This means that
vectorized code can use aligned operations, which may be slightly faster.
Moreover, matrices and vectors are now padded to a multiple of the vector size.
This allows to remove the final non-vectorized remainder loop from the
vectorized code. This is only done for the end of matrices, when they are
accessed in flat way. Contrary to some frameworks, inner dimensions of the
matrix are not padded.  Finally, accesses to 3D and 4D matrices is now much
faster than before.&lt;/p&gt;
&lt;p&gt;Then, the parallelization feature of ETL has been completely reworked. Before,
there was a thread pool for each algorithm that was parallelized. Now, there is
a global thread engine with one thread pool. Since parallelization is not nested
in ETL, this improves performance slightly by greatly diminishing the number of
threads that are created throughout an application. Another big difference in
parallel dispatching is that now it can detect good split based on alignment so
that each split are aligned. This then allows the vectorization process to use
aligned stores and loads instead of unaligned ones which may be faster on some
processors.&lt;/p&gt;
&lt;p&gt;Vectorization has also been greatly improved in ETL. Integer operations are now
automatically vectorized on processors that support this. Before, only floating
points operations were vectorized. The automatic vectorizer now is able to use
non-temporal stores for very large operations. A non-temporal store bypasses the
cache, thus gaining some time. Since very large matrices do not fit in cache
anyway and the cache would end up being overwritten anyway, this is a net gain.
Moreover, the alignment detection in the automatic vectorizer has also been
improved. Support for Fused-Multiply-Add (FMA) operations has also been
integrated in the algorithms that can make use of it (multiplications and
convolutions). The matrix-matrix multiplications and vector-matrix
multiplications now have highly optimized vectorized kernels. They also have
versions for column-major matrices now.  I plan to reintegrate a version of the
GEMM based on BLIS in the future but with more optimizations and support for all
precisions and integers, For my version is still slower than the simple
vectorized version. The sum and the dot product operations now also have
specialized vectorized implementations. The min and max operations are now
automatically-vectorized. Several others algorithms have also their own
vectorized implementations.&lt;/p&gt;
&lt;p&gt;Last, but not least, the GPU support has also been almost completely reworked.
Now, several operations can be chained without any copies between GPU and CPU.
Several new operations have also been added with support to GPU (convolutions,
pooling, sigmoid, ReLU, ...). Moreover, to complement operations that are not
available in any of the supported NVIDIA libraries, I've created a simple
library that can be used to add a few more GPU operations.  Nevertheless a lot
of operations are still missing and only algorithms are available not
expressions (such as c = a + b * 1.0) that are entirely computed on CPU. I have
plans to improve that further, probably for version 1.2. The different contexts
necessary for NVIDIA library can now be cached (using an option from ETL),
leading to much faster code. Only the main handle can be cached so far, I plan
to try to cache all the descriptors, but I don't know yet when that will be
ready. Finally, an option is also available to reuse GPU memory instead of
directly releasing it to CUDA. This is using a custom memory pool and can save
some time. Since this needs to be cleaned (by a call to etl::exit() or using
ETL_PROLOGUE), this is only activated on demand.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-changes"&gt;
&lt;h2&gt;Other changes&lt;/h2&gt;
&lt;p&gt;There also have been a lot of refactorings in the code of the library. A lot of
expressions now have less overhead and are specialized for performance.
Moreover, temporary expressions have been totally reworked to be more simple and
maintainable and easier to optimize in the future. It's also probably easier to
add new expressions to the framework now, although that could be even more
simple. There are also less duplicated code now in the different expressions.
Especially, now there are now more SSE and AVX variants in the code. All the
optimized algorithms are now using the vectorization system of the library.&lt;/p&gt;
&lt;p&gt;I also tried my best to reduce the compilation time, based on the unit tests.
This is still not great but better than before. For user code, the next version
should be much faster to compile since I plan to disable forced selection of
implementations by default and only enable it on demand.&lt;/p&gt;
&lt;p&gt;Finally, there also was quite a few bug fixes. Most of them have been found by
the use of the library in the Deep Learning Library (DLL) project. Some were
very small edge cases. For instance, the transposition algorithm was not working
on GPU on rectangular column major matrices. There also was a slight bug in the
Q/R decomposition and in the pooling of 4D matrices.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="what-s-next"&gt;
&lt;h2&gt;What's next ?&lt;/h2&gt;
&lt;p&gt;Next time, I may do some minor release, but I don't yet have a complete plan.
For the next major release (1.2 probably), here is what is planned:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Review the system for selection of algorithms to reduce compilation time&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Review the GPU system to allow more complete support for standard operators&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Switch to C++17: there are many improvements that could be done to the code with C++17 features&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add support for convolution on mixed types (float/double)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;More tests for sparse matrix&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;More algorithms support for sparse matrix&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reduce the compilation time of the library in general&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reduce the compilation and execution time of the unit tests&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are pretty big changes, especially the first two, so maybe it'll be split
into several releases. It will really depend on the time I have. As for C++17,
I really want to try it and I have a lot of points that could profit from the
switch, but that will means setting GCC 7.1 and Clang 3.9 as minimum
requirement, which may not be reasonable for every user.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="download-etl"&gt;
&lt;h2&gt;Download ETL&lt;/h2&gt;
&lt;p&gt;You can download ETL &lt;a class="reference external" href="https://github.com/wichtounet/etl"&gt;on Github&lt;/a&gt;. If you
only interested in the 1.1 version, you can look at the
&lt;a class="reference external" href="https://github.com/wichtounet/etl/releases"&gt;Releases pages&lt;/a&gt; or clone the tag
1.1. There are several branches:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;master&lt;/em&gt; Is the eternal development branch, may not always be stable&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;stable&lt;/em&gt; Is a branch always pointing to the last tag, no development here&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For the future release, there always will tags pointing to the corresponding
commits. I'm not following the git flow way, I'd rather try to have a more
linear history with one eternal development branch, rather than an useless
develop branch or a load of other branches for releases.&lt;/p&gt;
&lt;p&gt;The documentation is a bit sparse. There are a few examples and the Wiki, but
there still is work to be done. If you have questions on how to use or configure
the library, please don't hesitate.&lt;/p&gt;
&lt;p&gt;Don't hesitate to comment this post if you have any comment on this library or
any question. You can also open an Issue on Github if you have a problem using
this library or propose a Pull Request if you have any contribution you'd like
to make to the library.&lt;/p&gt;
&lt;p&gt;Hope this may be useful to some of you :)&lt;/p&gt;
&lt;/section&gt;</description><category>C++</category><category>C++14</category><category>C++17</category><category>Compilers</category><category>dll</category><category>etl</category><category>GPU</category><category>Performance</category><category>projects</category><guid>https://baptiste-wicht.com/posts/2017/08/expression-templates-library-etl-11.html</guid><pubDate>Fri, 04 Aug 2017 13:13:03 GMT</pubDate></item><item><title>C++17 Fold Expressions</title><link>https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html</link><dc:creator>Baptiste Wicht</dc:creator><description>&lt;section id="variadic-templates"&gt;
&lt;h2&gt;Variadic Templates&lt;/h2&gt;
&lt;p&gt;C++11 introduced variadic template to the languages. This new feature allows to write template functions and classes taking an arbitrary number of template parameters. This a feature I really like and I already used it quite a lot in my different libraries. Here is a very simple example computing the sum of the parameters:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code c++"&gt;&lt;a id="rest_code_f7e39c87474a43d685b6de55c797f1d4-1" name="rest_code_f7e39c87474a43d685b6de55c797f1d4-1" href="https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html#rest_code_f7e39c87474a43d685b6de55c797f1d4-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;auto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;old_sum&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
&lt;a id="rest_code_f7e39c87474a43d685b6de55c797f1d4-2" name="rest_code_f7e39c87474a43d685b6de55c797f1d4-2" href="https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html#rest_code_f7e39c87474a43d685b6de55c797f1d4-2"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_f7e39c87474a43d685b6de55c797f1d4-3" name="rest_code_f7e39c87474a43d685b6de55c797f1d4-3" href="https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html#rest_code_f7e39c87474a43d685b6de55c797f1d4-3"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;a id="rest_code_f7e39c87474a43d685b6de55c797f1d4-4" name="rest_code_f7e39c87474a43d685b6de55c797f1d4-4" href="https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html#rest_code_f7e39c87474a43d685b6de55c797f1d4-4"&gt;&lt;/a&gt;
&lt;a id="rest_code_f7e39c87474a43d685b6de55c797f1d4-5" name="rest_code_f7e39c87474a43d685b6de55c797f1d4-5" href="https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html#rest_code_f7e39c87474a43d685b6de55c797f1d4-5"&gt;&lt;/a&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;T1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;a id="rest_code_f7e39c87474a43d685b6de55c797f1d4-6" name="rest_code_f7e39c87474a43d685b6de55c797f1d4-6" href="https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html#rest_code_f7e39c87474a43d685b6de55c797f1d4-6"&gt;&lt;/a&gt;&lt;span class="k"&gt;auto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;old_sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;a id="rest_code_f7e39c87474a43d685b6de55c797f1d4-7" name="rest_code_f7e39c87474a43d685b6de55c797f1d4-7" href="https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html#rest_code_f7e39c87474a43d685b6de55c797f1d4-7"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;old_sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;...);&lt;/span&gt;
&lt;a id="rest_code_f7e39c87474a43d685b6de55c797f1d4-8" name="rest_code_f7e39c87474a43d685b6de55c797f1d4-8" href="https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html#rest_code_f7e39c87474a43d685b6de55c797f1d4-8"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What can be seen here is a typical use of variadic templates. Almost all the time, is is necessary to use recursion and several functions to unpack the parameters and process them. There is only one way to unpack the arguments, by using the ... operator that simply put comma between arguments. Even if it works well, it is a bit heavy on the code. This will likely be completely optimized to a series of addition by the compiler, but it may still happen in more complicated functions that this is not done. Moreover, the intent is not always clear with that.&lt;/p&gt;
&lt;p&gt;That is why C++17 introduced an extension for the variadic template, fold expressions.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="fold-expressions"&gt;
&lt;h2&gt;Fold expressions&lt;/h2&gt;
&lt;p&gt;Fold expressions are a new way to unpack variadic parameters with operators. For now, only Clang 3.6 supports C++17 fold expression, with the -std=c++1z flag. That is the compiler I used to validate the examples of this post.&lt;/p&gt;
&lt;p&gt;The syntax is bit disturbing at first but quite logical once you get used to it:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code c++"&gt;&lt;a id="rest_code_29026fd3038742839bcd0aa99865ecee-1" name="rest_code_29026fd3038742839bcd0aa99865ecee-1" href="https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html#rest_code_29026fd3038742839bcd0aa99865ecee-1"&gt;&lt;/a&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pack&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="c1"&gt;//(1)&lt;/span&gt;
&lt;a id="rest_code_29026fd3038742839bcd0aa99865ecee-2" name="rest_code_29026fd3038742839bcd0aa99865ecee-2" href="https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html#rest_code_29026fd3038742839bcd0aa99865ecee-2"&gt;&lt;/a&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pack&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="c1"&gt;//(2)&lt;/span&gt;
&lt;a id="rest_code_29026fd3038742839bcd0aa99865ecee-3" name="rest_code_29026fd3038742839bcd0aa99865ecee-3" href="https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html#rest_code_29026fd3038742839bcd0aa99865ecee-3"&gt;&lt;/a&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pack&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;//(3)&lt;/span&gt;
&lt;a id="rest_code_29026fd3038742839bcd0aa99865ecee-4" name="rest_code_29026fd3038742839bcd0aa99865ecee-4" href="https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html#rest_code_29026fd3038742839bcd0aa99865ecee-4"&gt;&lt;/a&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pack&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;//(4)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Where &lt;em&gt;pack&lt;/em&gt; is an unexpanded parameter pack, &lt;em&gt;op&lt;/em&gt; an operator and &lt;em&gt;init&lt;/em&gt; a value. The version (1) is a right fold that is expanded like (P1 op (P2 op (P3 ... (PN-1 op PN)))). The version (2) is a left fold where the expansion is taken from the left. The (3) and (4) versions are almost the same except for an init value. Only some operators (+,*,&amp;amp;,|,&amp;amp;&amp;amp;,||, ,) have defined init values and can be used with the versions (1) and (2). The other operators can only be used with an init value.&lt;/p&gt;
&lt;p&gt;For instance, here is how we could write the sum functions with fold expressions:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code c++"&gt;&lt;a id="rest_code_e5b6eba7b7854c09b212466f690d7dc0-1" name="rest_code_e5b6eba7b7854c09b212466f690d7dc0-1" href="https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html#rest_code_e5b6eba7b7854c09b212466f690d7dc0-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;a id="rest_code_e5b6eba7b7854c09b212466f690d7dc0-2" name="rest_code_e5b6eba7b7854c09b212466f690d7dc0-2" href="https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html#rest_code_e5b6eba7b7854c09b212466f690d7dc0-2"&gt;&lt;/a&gt;&lt;span class="k"&gt;auto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fold_sum_1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;a id="rest_code_e5b6eba7b7854c09b212466f690d7dc0-3" name="rest_code_e5b6eba7b7854c09b212466f690d7dc0-3" href="https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html#rest_code_e5b6eba7b7854c09b212466f690d7dc0-3"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_e5b6eba7b7854c09b212466f690d7dc0-4" name="rest_code_e5b6eba7b7854c09b212466f690d7dc0-4" href="https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html#rest_code_e5b6eba7b7854c09b212466f690d7dc0-4"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I personally think it is much better, it clearly states our intent and does not need recursion. By default, the init value used for addition is 0, but you can change it:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code c++"&gt;&lt;a id="rest_code_a0b97b6b769a4f13ab7a6e22e37f8840-1" name="rest_code_a0b97b6b769a4f13ab7a6e22e37f8840-1" href="https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html#rest_code_a0b97b6b769a4f13ab7a6e22e37f8840-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;a id="rest_code_a0b97b6b769a4f13ab7a6e22e37f8840-2" name="rest_code_a0b97b6b769a4f13ab7a6e22e37f8840-2" href="https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html#rest_code_a0b97b6b769a4f13ab7a6e22e37f8840-2"&gt;&lt;/a&gt;&lt;span class="k"&gt;auto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fold_sum_2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;a id="rest_code_a0b97b6b769a4f13ab7a6e22e37f8840-3" name="rest_code_a0b97b6b769a4f13ab7a6e22e37f8840-3" href="https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html#rest_code_a0b97b6b769a4f13ab7a6e22e37f8840-3"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_a0b97b6b769a4f13ab7a6e22e37f8840-4" name="rest_code_a0b97b6b769a4f13ab7a6e22e37f8840-4" href="https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html#rest_code_a0b97b6b769a4f13ab7a6e22e37f8840-4"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This will yield the sum of the elements plus one.&lt;/p&gt;
&lt;p&gt;This can be also very practical to print some elements for instance:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code c++"&gt;&lt;a id="rest_code_156d187bb0944bb2bf55d6d4e555d97e-1" name="rest_code_156d187bb0944bb2bf55d6d4e555d97e-1" href="https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html#rest_code_156d187bb0944bb2bf55d6d4e555d97e-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="n"&gt;Args&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;a id="rest_code_156d187bb0944bb2bf55d6d4e555d97e-2" name="rest_code_156d187bb0944bb2bf55d6d4e555d97e-2" href="https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html#rest_code_156d187bb0944bb2bf55d6d4e555d97e-2"&gt;&lt;/a&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;print_1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Args&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_156d187bb0944bb2bf55d6d4e555d97e-3" name="rest_code_156d187bb0944bb2bf55d6d4e555d97e-3" href="https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html#rest_code_156d187bb0944bb2bf55d6d4e555d97e-3"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sc"&gt;'\n'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_156d187bb0944bb2bf55d6d4e555d97e-4" name="rest_code_156d187bb0944bb2bf55d6d4e555d97e-4" href="https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html#rest_code_156d187bb0944bb2bf55d6d4e555d97e-4"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And this can even be used when doing Template Metaprogramming, for instance here is a TMP version of the and operator:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code c++"&gt;&lt;a id="rest_code_4818d980a1bd491daa1b2c7451e64d31-1" name="rest_code_4818d980a1bd491daa1b2c7451e64d31-1" href="https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html#rest_code_4818d980a1bd491daa1b2c7451e64d31-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;a id="rest_code_4818d980a1bd491daa1b2c7451e64d31-2" name="rest_code_4818d980a1bd491daa1b2c7451e64d31-2" href="https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html#rest_code_4818d980a1bd491daa1b2c7451e64d31-2"&gt;&lt;/a&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;fold_and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;integral_constant&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{};&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/section&gt;
&lt;section id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;C++17 fold expressions are a really nice additions to the language that makes working with variadic templates much easier. This already makes me wish for C++17 release :)&lt;/p&gt;
&lt;p&gt;The source code for the examples are available on Github: &lt;a class="reference external" href="https://github.com/wichtounet/articles/blob/master/src/fold_expressions.cpp"&gt;https://github.com/wichtounet/articles/blob/master/src/fold_expressions.cpp&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;</description><category>C++</category><category>C++17</category><guid>https://baptiste-wicht.com/posts/2015/05/cpp17-fold-expressions.html</guid><pubDate>Sat, 23 May 2015 17:08:20 GMT</pubDate></item></channel></rss>