Functions that do nothing

Is C++ a language difficult to learn? I cannot objectively answer this question because I have programmed in C++ for a couple of years now, and I got used to it and its idioms; and all the idioms and techniques appear natural to me. “Easy to learn” on the other hand means how fast the idioms become natural. Yet, I tend to think that C++ is difficult to learn, and I will try to show one argument for it. I am not going to talk about any “dark corners” of the standard, but about well established idioms. My goal is not to criticize C++, but to show you why other programmers may perceive it as difficult, and perhaps give some insight into new idioms in C++11, so that they become natural more quickly.

What is a function in the context of computer programming? It is a sub-program. It does some things, opens files, establishes a connection, adds numbers, and so on… In short, a function does something. Yet in C++ Standard Library, you can find a couple of functions that do nothing.


This function (template) takes a reference (either an lvalue or an rvalue reference) to an object, and returns an rvalue reference to that object. It is intended to be used in context where you want to trigger move semantics for expressions that are not rvalues.

Pair::Pair( Pair && rhs ) // move-constructor
: first{ std::move(rhs.first) }
, second{ std::move(rhs.second) }

In this example we need to use move in order to move-construct first and second. Although parameter rhs is bound to an rvalue, it is an lvalue itself (a name of a reference is an lvalue) and omitting move, would initialize first with an lvalue, which would trigger a (potentially expensive) copy construction. Function move changes lvalues into rvalues. We could have achieved the same effect by typing:

Pair::Pair( Pair && rhs ) // move-constructor
: first{ static_cast<first_t &&>(rhs.first) }
, second{ static_cast<second_t &&>(rhs.second) }

And this shows the nature of function move: it is a type (a reference, to be precise) cast. Yet, since it is going to be one of the most frequently used casts, and we do not want to repeat the type that is already obvious, the Standard Library offers this shorthand notation. Counter to what its name suggests, the function itself does not move anything. It simply casts one reference to another. This in turn may trigger a move constructor, but might as well trigger copy constructor in case our type does not provide a move constructor.


This one is similar to the previous one; it takes an lvalue and casts it to either rvalue reference or lvalue reference to const, based on the following conditions:

  • if our type offers a no-throw move — rvalue reference,
  • if our type is movable but not copyable — rvalue reference,
  • otherwise — lvalue reference to const.

This function is preferred in contexts where a non-destructive copy operation enables us to offers stronger exception safety guarantees than a potentially throwing move operation. For an example of such situation see this article.


This is an another ‘cast’ function, that enables the technique known as perfect forwarding. It has already been well explained by many authors: [1], [2], [3]. It is different than the previous moving functions in that it is only useful in function templates, for parameters with rvalue reference types, where special reference collapsing rules apply. The typical usage would be a factory function:

template< typename T, typename... Args >
std::unique_ptr<T> make( Args &&... args ) 
    return std::unique_ptr<T>{ new T{std::forward<Args>(args)...} };

The detailed meaning of this code is already described in the articles listed above. In short, the part T{forward<Args>(args)...} indicates that T will be initialized with the very same types of arguments as make was invoked with (same rvalue or lvalue).


This function (template) is even more strange. It is only declared but never defined. If you try to just call it in your program, the program will not even compile. It can only be used as an unevaluated operand of sizeof, decltype, noexcept. For instance:

template< typename T, typename U >
struct common_type<T, U>
    typedef decltype(true ? declval<T>() : declval<U>()) type;
    // typedef decltype(true ? T() : U()) type;

Its purpose is to mention a value of some type, without creating the value. Note that the line I have commented out would not work, because types T and U may not have a default constructor.

This entry was posted in programming and tagged . Bookmark the permalink.

One Response to Functions that do nothing

  1. Pingback: has_no_except_mem_fun type trait | Mens supra materia

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s