Explicit Return Type of Lambda

Explicit Return Type of Lambda

You can explicitly specify the return type of a lambda by using -> Type after the arguments list:

[]() -> Type { }

However, if a lambda has one statement and that statement is a return statement (and it returns an expression), the compiler can deduce the return type from the type of that one returned expression. You have multiple statements in your lambda, so it doesn't deduce the type.

Kotlin lambda with explicit return type

You actually cannot explicitly declare the return type in a Kotlin lambda:

One thing missing from the lambda expression syntax presented above is the ability to specify the return type of the function.

https://kotlinlang.org/docs/reference/lambdas.html#anonymous-functions

Returning a generic lambda expression from a function causes compiler warnings if an explicit return type is given

The point is that decltype(dst) is auto const & (where you can see auto as a template type`, so the lambda return a reference (I repeat: a reference) to a constant object.

The problem is that is a reference to

dst + src

that is: a reference to a temporary value, the temporary object created from the operation dst + src, that doesn't exist anymore when the lambda conclude the execution.

A possible solution: remove -> decltype(dst) or change it to -> decltype(dst+src), so you return a value, not a reference.

Another way (require more typewriting in this case but can be prefereble in more complex cases) could be remove the reference part from the type returned from decltype().

So

-> std::remove_reference_t<decltype(dst)>

or, as suggested by Jarod42, also

-> std::decay_t<decltype(dst)>

If the type of dst support the unary operator + (returning the same type of dst), another simple solution can be

-> decltype(+dst)

This way, +dst is an expression, not a variable, so decltype(+dst) isn't a reference anymore.

C++11 restrictions on lambda return type

That is slightly imprecise. [expr.prim.lambda]/4:

If a lambda-expression does not include a lambda-declarator, it is
as if the lambda-declarator were (). If a lambda-expression does
not include a trailing-return-type, it is as if the
trailing-return-type denotes the following type:

  • if the compound-statement is of the form

    { attribute-specifier-seqoptreturn expression ; }

    the type of the returned expression after lvalue-to-rvalue
    conversion (4.1), array-to-pointer conversion (4.2), and
    function-to-pointer conversion (4.3);

  • otherwise, void.

So the return type is only deduced if the whole body of the lambda expression only consists of one sole return statement.

Both GCC and Clang are not standard conforming in this case as they issue an error message if and only if two return statements lead to inconsistent deductions. This is because they already implemented the C++14 standard which deducts the return type even with multiple return statements and/or multiple other statements present. [expr.prim.lambda]/4 specifies that

The lambda return type is auto, which is replaced by the
trailing-return-type if provided and/or deduced from return statements as described in 7.1.6.4.

§7.1.6.4/9

If a function with a declared return type that contains a placeholder
type has multiple return statements, the return type is deduced for
each return statement. If the type deduced is not the same in each
deduction, the program is ill-formed.

It is possible to define the return type of a lambda expression?

This has nothing to do with "declaring the return type of your lambda." You're just specifying an invalid argument to map(), and the compiler is telling you so.

The map method in IntStream takes an IntUnaryOperator (a function from int to int). There is no method Math.sqrt that can be converted to this signature.

When can we omit the return type in a C++11 lambda?

Your code is being accepted without any warnings because the original C++11 restriction is considered a defect in the standard, which allows implementations to fix the behavior. See CWG DR975, DR1048 and N3638.

975. Restrictions on return type deduction for lambdas

[Moved to DR status at the April, 2013 meeting as part of paper N3638.]

There does not appear to be any technical difficulty that would require the current restriction that the return type of a lambda can be deduced only if the body of the lambda consists of a single return statement. In particular, multiple return statements could be permitted if they all return the same type.

1048. auto deduction and lambda return type deduction.

...

Notes from the November, 2014 meeting:

CWG agreed that the change embodied in paper N3638 should be considered to have been a DR against C++11.

In summary, DR975 proposed modifying the rules for return type deduction for lambda expressions to allow multiple return statements.

DR1048 identifies a discrepancy where the rules for deducing the return type for normal functions using the placeholder type auto differs slightly from the rules proposed in DR975. Specifically, return type deduction for normal functions would discard top-level cv-qualifiers in all cases, where as those for lambda expressions would preserve cv-qualifiers for class types.

N3638 resolves this issue, amongst others.


I doubt there's any way to revert to the original behavior short of finding a compiler version that shipped with C++11 lambda support prior to the implementation of the DR above.

Function Attribute on Lambda with Explicit Return Type fails to Compile

This is GCC bug Bug 90333 - [9 Regression] Can't apply attributes to lambdas with trailing returns . It was introduced with R265787 and is slated as fixed in 9.3.

Return type of a C++ lambda

Since the return type can depend on the arguments given to the functor, you need to specify them somewhere in order to query the return type. Therefore, when speaking of generic functors (not restricting them to (non-generic) lambdas), it's not possible to determine the return type when not knowing the types of the arguments.

C++11 has the keyword decltype which can be used in conjunction with a trailing return type in order to specify the return type of your function by naming an expression which can depend on the function arguments (here, it depends on what Func is):

template<typename TFunctor>
auto MyFunc(TFunctor &Func) -> decltype(Func(/* some arguments */))
{ ... }

So if you were to call it for example with no argument (I assume this when looking at your lambda example), simply write:

template<typename TFunctor>
auto MyFunc(TFunctor &Func) -> decltype(Func())
{
return Func();
}

In C++14, you can even completely omit the return type and simply write

template<typename TFunctor>
auto MyFunc(TFunctor &Func)
{
return Func();
}

Note that even in C++03, you don't have to provide another function argument; another template argument is enough:

template<typename TReturn, typename TFunctor>
TReturn MyFunc(TFunctor &Func)
{
return Func();
}

int n = MyFunc<int>(someFunctorReturningAnInt);


Related Topics



Leave a reply



Submit