Search code examples
c++c++11autodecltype

Arrow operator (->) in function heading


I came across the following code:

template <typename T, typename T1> auto compose(T a, T1 b) -> decltype(a + b) {
   return a+b;
}

There is one thing I cannot understand:

Where could I find out what the arrow operator (->) means in the function heading?

I guess purely logically, that the -> operator determines a type, that auto will be deduced to, but I want to get this straight. I can't find any information.


Solution

  • In C++11, there are two syntaxes for function declaration:

        return-type identifier ( argument-declarations... )

    and

        auto identifier ( argument-declarations... ) -> return_type

    They are equivalent. Now when they are equivalent, why do you ever want to use the latter? Well, C++11 introduced this cool decltype thing that lets you describe type of an expression. So you might want to derive the return type from the argument types. So you try:

    template <typename T1, typename T2>
    decltype(a + b) compose(T1 a, T2 b);
    

    and the compiler will tell you that it does not know what a and b are in the decltype argument. That is because they are only declared by the argument list.

    You could easily work around the problem by using declval and the template parameters that are already declared. Like:

    template <typename T1, typename T2>
    decltype(std::declval<T1>() + std::declval<T2>())
    compose(T1 a, T2 b);
    

    except it's getting really verbose now. So the alternate declaration syntax was proposed and implemented and now you can write

    template <typename T1, typename T2>
    auto compose(T1 a, T2 b) -> decltype(a + b);
    

    and it's less verbose and the scoping rules didn't need to change.


    C++14 update: C++14 also permits just

        auto identifier ( argument-declarations... )

    as long as the function is fully defined before use and all return statements deduce to the same type. The -> syntax remains useful for public functions (declared in the header) if you want to hide the body in the source file. Somewhat obviously that can't be done with templates, but there are some concrete types (usually derived via template metaprogramming) that are hard to write otherwise.