C++17
C++ language is constantly evolving, and for us, as for developers of a static analyzer, it is important to track all its changes, in order to support all new features of the language. In this review article, I would like to share with the reader the most interesting innovations introduced in C++17, and demonstrate them with examples.
Now, developers of compilers are actively adding support for the new standard. You can see what is supported at the moment via the following links:
GCC
Clang
Visual Studio
Fold expressions
I would like to start with a few words about what a fold is (also known as reduce or accumulate).
Fold is a function that applies the assigned combining function to sequential pairs of elements in a list, and returns a result. The simplest example is the summing up of elements in the list using a fold:
Example from C++:
std::vector<int> lst = { 1, 3, 5, 7 }; int res = std::accumulate(lst.begin(), lst.end(), 0, Â [](int a, int b) Â { return a + b; }); std::cout << res << '\n'; // 16
If the combining function is applied to the first item in a list and to the result of the recursive processing of the tail of a list, then the fold is called 'right'. In our example, we will get:
1 + (3 + (5 + (7 + 0)))
If the combining function is applied to the result of the recursive processing at the top of the list (the entire list without the last element) and to the last element, then a folding is called 'left'. In our example, we will get:
(((0 + 1) + 3) + 5) + 7
Thus, the fold type determines the order of evaluation.
In C++17 there is also folding support for a template parameters list. It has the following syntax:
op is one of the following binary operators:
+ - * / % ^ & | ~ = < > << >> += -= *= /= %= ^= &= |= <<= >>= == != <= >= && || , .* ->*
pack is an expression containing an undisclosed parameter pack
init - initial value
For example, here's a template function that takes a variable number of parameters and calculates their sum:
// C++17 #include <iostream> template<typename... Args> auto Sum(Args... args) { Â return (args + ...); } int main() { Â std::cout << Sum(1, 2, 3, 4, 5) << '\n'; // 15 Â return 0; }
Note: In this example, the Sum function could be also declared as constexpr.
If we want to specify an initial value, we can use binary fold:
// C++17 #include <iostream> template<typename... Args> auto Func(Args... args) { Â return (args + ... + 100); } int main() { Â std::cout << Func(1, 2, 3, 4, 5) << '\n'; //115 Â return 0; }
Before C++17, to implement a similar function, you would have to explicitly specify the rules for recursion:
// C++14 #include <iostream> auto Sum() { Â return 0; } template<typename Arg, typename... Args> auto Sum(Arg first, Args... rest) { Â return first + Sum(rest...); } int main() { Â std::cout << Sum(1, 2, 3, 4); // 10 Â return 0; }
It is worth highlighting the operator ',' (comma), which will expand the pack into a sequence of actions separated by commas. Example:
// C++17 #include <iostream> template<typename T, typename... Args> void PushToVector(std::vector<T>& v, Args&&... args) {  (v.push_back(std::forward<Args>(args)), ...); //This code is expanded into a sequence of expressions    //separated by commas as follows:  //v.push_back(std::forward<Args_1>(arg1)),  //v.push_back(std::forward<Args_2>(arg2)),  //.... } int main() {  std::vector<int> vct;  PushToVector(vct, 1, 4, 5, 8);  return 0; }
Thus, folding greatly simplifies work with variadic templates.
Read more -Â https://www.viva64.com/en/b/0533/














