Logo

Blog


Use of the comma operator

Last week, I read a blog article from Jonathan Boccara called "Getting Along With The Comma Operator in C++". At the end of the article I felt bad for the comma operator. Jonathan pointed out an example where the comma operator gets in our way. The article is great. However, to me it looks like the comma operator is not needed and can just be in our way. In this post I will point out two use-cases where the comma operator is in fact helpful.

Let's start with C++11. Do you remember how great it was to get that language update? Especially after all the years seeing other languages arise and or improve? There are many things which got introduced or improved with C++11, one I like is constexpr. I like to focus on constexpr-functions here. They got improved a lot with C++14 and again with C++17. Unfortunately, not all of us are lucky enough to get to use the latest standard.

Back in C++11 they are, let's say restricted. Such functions can more or less contain only a single return statement. This restriction makes it hard to write constexpr functions in C++11. One particular hard area is an assertion. Assume there is a constexpr function:

1
constexpr size_type CheckLength(size_type len)

The length parameter len must be in a certain range. Otherwise, we will get a buffer over- or underflow. How can this be achieved? The comma operator is our friend:

1
2
3
4
constexpr size_type CheckLength(size_type len)
{
    return ((len <= MAX_SIZE) ? (void)0 : assert(false); ), len;
}

Thanks to the comma operator we still have only a single return statement. The comma operator helps us, to separate the assert-expression from the actual return value: len. The idea is, that this function always returns len. Except if the assert condition is not met, then is fires the assert and the program terminates. Still len is the only return value. Here the same, but in a bit more readable and reusable fashion:

1
2
3
4
constexpr size_type CheckLength(size_type len)
{
    return ASSERT(len <= MAX_SIZE), len;
}

Either the ASSERT will kick in or this functions returns len. The ASSERT-macro itself is a bit more complicated. You can find a working version in abseil marco.h. Which is used, for example in string_view.h.

Another C++11 and later feature which can be used with the comma operator are variadic templates. To be more precise the pack expansion:

1
2
3
4
5
template<typename T, typename... Args>
void push_back_vec(std::vector<T>& v, Args&&... args)
{
    (v.push_back(args), ...);
}

This is part of an example from cppreference.com. Here the comma operator is used to expand the pack and execute an operation for each pack-member. In this case push_back. Jason Turner once wrote an article exploring even more (ab)uses of variadic templates and the comma operator: Folds (ish) In C++11.

As you can see, as much the comma operator can be annoying, but also helpful.



I hope you learned something with this article.

Andreas

Comments