Reputation: 34175
In C++11, the two lines are equivalent. From what I see, the the advantage of the second syntax is that the return type is in class scope. Therefore, you can use both, nested types of the class directly and decltype
expressions of non static members. Moreover, the function names line up nicely.
int foo(int bar);
auto foo(int bar) -> int;
The auto
keyword is used here, which can also be used to automatically derive the type of local variables. However, I don't see the analogy here. In the function declaration syntax, nothing is derived. The return type is mentioned explicitly behind the arrow.
Personally, I would say that the syntax would be clearer without the auto
keyword. Is there any intention behind this? Which?
Upvotes: 5
Views: 445
Reputation: 69864
Adding this answer to complement @dyp's excellent answer.
Here's a real-world example from some code in my project that would be very difficult to write without the trailing return type:
template<class F, class... ArgTypes>
auto expected_from_code(F&& f, ArgTypes&& ...args)
-> expected_t<
typename std::enable_if<
!std::is_void<decltype(f(std::forward<ArgTypes>(args)...))>::value,
decltype(f(std::forward<ArgTypes>(args)...))>::type>
{
using expected = expected_t<decltype(f(std::forward<ArgTypes>(args)...))>;
try {
return expected { f(std::forward<ArgTypes>(args)...) };
}
catch(...) {
return expected { typename expected::exception_sentinel{} };
}
}
Upvotes: 0
Reputation: 39101
The paper "Decltype (revision 5)", N1978 proposed the syntax for trailing-return-type (as they're now known). This was done to simplify defining function templates whose return type depends on an expression involving its arguments in chapter 3:
template <class T, class U> decltype((*(T*)0)+(*(U*)0)) add(T t, U u);
The expression
(*(T*)0)
is a hackish way to write an expression that has the typeT
and does not requireT
to be default constructible. If the argument names were in scope, the above declaration could be written as:template <class T, class U> decltype(t+u) add(T t, U u);
Several syntaxes that move the return type expression after the argument list are discussed in [Str02]. If the return type expression comes before the argument list, parsing becomes difficult and name lookup may be less intuitive; the argument names may have other uses in an outer scope at the site of the function declaration.
We suggest reusing the
auto
keyword to express that the return type is to follow after the argument list. The return type expression is preceded by->
symbol, and comes after the argument list and potential cv-qualifiers in member functions and the exception specification:template <class T, class U> auto add(T t, U u) -> decltype(t + u);
The reference [Str02] is "Bjarne Stroustrup. Draft proposal for "typeof". C++ reflector message c++std-ext-5364, October 2002.", but I'm not sure if that's publicly available.
Upvotes: 4