Search code examples
c++c++11autotrailing-return-type

Should the trailing return type syntax style become the default for new C++11 programs?


C++11 supports a new function syntax:

auto func_name(int x, int y) -> int;

Currently this function would be declared as:

int func_name(int x, int y);

The new style does not seem to be widely adopted yet (say in the gcc stl)

However, should this new style be preferred everywhere in new C++11-programs, or will it only be used when needed?

Personally, I prefer the old style when possible, but a code-base with mixed styles looks pretty ugly.


Solution

  • There are certain cases where you must use a trailing return type. Most notably, a lambda return type, if specified, must be specified via a trailing return type. Also, if your return type utilizes a decltype that requires that the argument names are in scope, a trailing return type must be used (however, one can usually use declval<T> to work around this latter issue).

    The trailing return type does have some other minor advantages. For example, consider a non-inline member function definition using the traditional function syntax:

    struct my_awesome_type
    {
        typedef std::vector<int> integer_sequence;
    
        integer_sequence get_integers() const;
    }; 
    
    my_awesome_type::integer_sequence my_awesome_type::get_integers() const
    {
        // ...
    }
    

    Member typedefs are not in scope until after the name of the class appears before ::get_integers, so we have to repeat the class qualification twice. If we use a trailing return type, we don't need to repeat the name of the type:

    auto my_awesome_type::get_integers() const -> integer_sequence
    {
        // ...
    }
    

    In this example, it's not such a big deal, but if you have long class names or member functions of class templates that are not defined inline, then it can make a big difference in readability.

    In his "Fresh Paint" session at C++Now 2012, Alisdair Meredith pointed out that if you use trailing return types consistently, the names of all of your functions line up neatly:

    auto foo() -> int;
    auto bar() -> really_long_typedef_name;
    

    I've used trailing return types everywhere in CxxReflect, so if you're looking for an example of how code looks using them consistently, you can take a look there (e.g, the type class).