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.

image

Now, developers of compilers are actively adding support for the new standard.

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:
(pack op ...) A unary right associative fold
(... op pack) A unary left associative fold
(pack op ... op init) A binary right associative fold
(init op ... op pack) A binary left associative fold

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.
Kate Milovidova 13 october 2017, 14:23

image

One of the main problems with C++ is having a huge number of constructions whose behavior is undefined, or is just unexpected for a programmer. We often come across them when using our static analyzer on various projects. But, as we all know, the best thing is to detect errors at the compilation stage. Let's see which techniques in modern C++ help writing not only simple and clear code, but make it safer and more reliable.
What is Modern C++?

The term Modern C++ became very popular after the release of C++11. What does it mean? First of all, Modern C++ is a set of patterns and idioms that are designed to eliminate the downsides of good old "C with classes", that so many C++ programmers are used to, especially if they started programming in C. C++11 looks way more concise and understandable, which is very important.
Kate Milovidova 15 september 2016, 11:44

Here is a small e-Book for your attention: The Ultimate Question of Programming, Refactoring, and Everything. This book is intended for C/C++ programmers, but it could be of interest for developers using other languages as well.

What makes the book peculiar is the descriptions of real, not theoretical cases at the base of it. Each chapter starts with a code fragment taken from a real application, and then the author gives various tips of how this bug could be avoided. The questions touched upon in this book can help the readers improve the personal coding style and the coding standards used in the team.
Kate Milovidova 11 may 2016, 6:52