Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is inheritability of lambdas guaranteed by the standard?

In the C++ standard, closure types are defined as follows:

[expr.prim.lambda.closure] The type of a lambda-expression (which is also the type of the closure object) is a unique, unnamed non-union class type, called the closure type, whose properties are described below. [...]

The standard does not seem to define whether or not the unnamed non-union class type is final. Would a compiler implementing lambdas as final classes be standard compliant, or do we have the guarantee that one can inherit from lambdas?

The question is not whether it is useful or not to inherit from lambdas: it's a given that it is useful. The question is whether the standard provides this guarantee.

like image 956
Vincent Avatar asked Apr 07 '18 07:04

Vincent


People also ask

When should you use lambda c++?

50: Use a lambda when a function won't do (to capture local variables, or to write a local function) The difference in the usage of functions and lambda functions boils down to two points. You can not overload lambdas. A lambda function can capture local variables.

Why use c++ lambda expressions?

C++ Lambda expression allows us to define anonymous function objects (functors) which can either be used inline or passed as an argument. Lambda expression was introduced in C++11 for creating anonymous functors in a more convenient and concise way.

What is lambda function CPP?

In C++11 and later, a lambda expression—often called a lambda—is a convenient way of defining an anonymous function object (a closure) right at the location where it's invoked or passed as an argument to a function.


1 Answers

Yes, the closure type must not be final. At least that's my interpretation.

§8.1.5.1 Closure types [expr.prim.lambda.closure]

An implementation may define the closure type differently from what is described below provided this does not alter the observable behavior of the program other than by changing:

  • ... [does not apply]

The standard then doesn't describe the closure type as being final. Making it final would alter the observable behavior ergo the closure type must not be final.

Regarding the observable behavior. Consider this:

auto l = []{};
return std::is_final_v<decltype(l)>;

Making the closure type final would clearly modify the observable behavior of a valid program.


As to a use case, it can actually be a very useful feature:

template <class... Fs> struct Overload : Fs ...
{
    using Fs::operator()...;
};

template <class... Fs> Overload(Fs...) -> Overload<Fs...>;

auto test()
{
    Overload f = {[] (int a) { return a * 100; },
                  [] (int a, int b) { return a + b;}};

    return f(1) + f(2, 3); // 105
}

See it in action on godbolt


Thanks to hvd and rakete1111 for the discussions and feedback in the comments.

like image 91
bolov Avatar answered Sep 26 '22 08:09

bolov