Trailing Return Type

The trailing return type feature was added in C++11. This feature allows you to specify the return type after a function declaration instead of before. In order to see how this is can be useful, we shall look at a simple example.

Suppose we have an Employee class which records an employee’s salary and whether they are on a permanent or temporary contract.

The class declaration might look like this:

class Employee
{
public:
    enum class Type
    {
        Permanent,
        Temporary
    };

    Employee(Type type, int salary)
    {
        _type = type;
        _salary = salary;
    }

    Type type() const;
    int salary() const;

private:
    Type _type;
    int _salary;
};

Prior to C++11, the implementation of the type() accessor might be as follows:

Employee::Type Employee::type() const
{
    return _type;
}

Since the Type enumeration is declared inside the Employee type, we need to explicitly declare the return type as Employee::Type.

In C++11, we can use the alternative trailing return type syntax:

auto Employee::type() const -> Type
{
    return _type;
}

Note that because this is a member function of the Employee class, we can specify the return type as Type instead of Employee::Type.

Using decltype

Ok, now it’s time to talk about salaries! Let’s implement the salary() member function:

int Employee::salary() const
{
    return _salary;
}

For the time being, we are using an integer type to represent the salary.

When it’s time to do the monthly payroll, we might want a helper function to calculate each employee’s wages:

int monthlyPay(const Employee& employee)
{
    return employee.salary() / 12;
}

To keep things simple, we are returning the calculated value as an integer to be consistent throughout the code.

However, some of the employees might get a little disgruntled that their wages are getting rounded down each month! After all, those ‘half cents’ add up as Richard Pryor discovered in Superman III.

So at some point in the future, we might want to refactor the code to use double instead of int. If we could get the compiler to deduce the return type automatically, we could reduce the dreaded ‘ripple effect’.

In C++11, we can achieve this by combining the trailing return type with the declspec keyword:

auto monthlyPay(const Employee& employee) 
    -> decltype(employee.salary())
{
    return employee.salary() / 12;
}

Note that in C++14, we can take advantage of automatic return type deduction and simply write:

auto monthlyPay(const Employee& employee) 
{
    return employee.salary() / 12;
}

We can now change our salary type to int, double, or any other suitable numeric type and our monthlyPay() helper function will still compile without having to make any changes.