Tag Archives: functions

Function return type deduction in C++14

C++11 introduced the auto keyword as a placeholder for types. It could be used for declaring variables but also for the return type of a function, given than you use a new syntax with a trailing type at the end of the function.

or

This is a bit cumbersome and too explicit so C++14 takes the next step and makes the trailing return type unnecessary. Under C++14 the above examples can be simply written as:

and

There are several things to keep in mind:

  • if a function has more than one return statement they all must deduce the same type
  • a recursive function can have an auto return type only if it has a non-recursive return statement before the recursive call.
  • a function with an auto return type can be forward declared, but cannot be used until it has been defined

In my personal opinion auto return type should be used with caution. It can make the code harder to read and maintain (you don’t know the type just by looking at the signature), harder to document (automatic documenting tools use the signature to produce documentation), and can lead to situations when the developer expects one return type but the compiler generates another.

Additional readings:

C++11: non-member begin() and end()

One of the addition to the C++ 2011 standard that is perhaps not so much popularized is the non-member begin() and end(). In STL all containers have a non-static member begin() and end() methods that return an iterator to the beginning and the end of the container. Therefor iterating over a container could look like this:

The problem here is that not all user-defined containers have begin() and end(), which makes them impossible to use with the STL algorithms or any other user-defined template function that requires iterators. That is even more problematic when using C arrays. For instance, using a C array with a standard algorithm is quite different than using a vector, for instance.

The non-member begin() and end() methods are extensible, in the sense they can be overloaded for any type (including C arrays). Herb Sutter argues in his Elements of Modern C++ Style article that you should always prefer the non-member version. They promote uniformity and consistency and allow for more generic programming.

Always use nonmember begin(x) and end(x) (not x.begin() and x.end()), because begin(x) and end(x) are extensible and can be adapted to work with all container types – even arrays – not just containers that follow the STL style of providing x.begin() and x.end() member functions.

The code above can now look like this:

As for the C array we can overload begin() and end() to look maybe like this:

With this available we can write:

If you’d argue that non-member begin() and end() break the encapsulation then I suggest you read Scott Meyers’ How Non-Member Functions Improve Encapsulation where he explains the opposite.

If you’re writing a function that can be implemented as either a member or as a non-friend non-member, you should prefer to implement it as a non-member function. That decision increases class encapsulation. When you think encapsulation, you should think non-member functions.

There is still one question left: what about the other container functions that return iterators, rbegin(), rend(), cbegin(), cend(), crbegin(), and crend()? Currently they are not implemented as non-member functions. According to Herb Sutter, the omission of cbegin() and cend() was an oversight and it will be fixed.

Additional readings: