When is a lambda a guaranteed to be trivial, if ever?
I assumed that if it captures only trivial types or nothing, it would be trivial. I don't have any standard-ese to back that up though.
My motivation was in moving some code from Visual C++ 12 to 14 and discovered some static asserts failed when dealing with lambdas I assumed to be trivial.
Example:
#include <type_traits>
#include <iostream>
using namespace std;
int main()
{
auto lambda = [](){};
cout << boolalpha << is_trivially_copyable<decltype(lambda)>{} << endl;
}
This produces false
on vs140 but true
in vs120 and clang. I could not test gcc due to not having gcc >= 5 around. I expect this is a regression in vs140, but I'm not certain of the correct behavior here.
The standard does not specify whether a closure type (the type of a lambda expression) is trivial or not. It explicitly leaves this up to implementation, which makes it non-portable. I am afraid you cannot rely on your static_assert
producing anything consistent.
Quoting C++14 (N4140) 5.1.2/3:
... 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:
- the size and/or alignment of the closure type,
- whether the closure type is trivially copyable (Clause 9),
- whether the closure type is a standard-layout class (Clause 9), or
- whether the closure type is a POD class (Clause 9).
...
(Emphasis mine)
After parsing the double negation in that sentence, we can see that the implementation is allowed to decide whether the closure type is trivially copyable, standard layout, or POD.
Note that the same wording is also present in C++17 (N4659), [expr.prim.lambda.closure] 8.1.5.1/2.
According to the draft standard N4527 5.1.2/3 Lambda expressions [expr.prim.lambda] (emphasis mine):
The type of the lambda-expression (which is also the type of the closure object) is a unique, unnamed nonunion class type — called the closure type — whose properties are described below. This class type is neither an aggregate (8.5.1) nor a literal type (3.9). The closure type is declared in the smallest block scope, class scope, or namespace scope that contains the corresponding lambda-expression. [ Note: This determines the set of namespaces and classes associated with the closure type (3.4.2). The parameter types of a lambdadeclarator do not affect these associated namespaces and classes. — end note ] 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:
(3.1) — the size and/or alignment of the closure type,
(3.2) — whether the closure type is trivially copyable (Clause 9),
(3.3) — whether the closure type is a standard-layout class (Clause 9), or
(3.4) — whether the closure type is a POD class (Clause 9).
An implementation shall not add members of rvalue reference type to the closure type
Thus, it's implementation dependent.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With