34

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.

1
  • 4
    gcc 5.2 produces also true: Demo Commented Oct 7, 2015 at 7:29

2 Answers 2

33

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Well thats pretty sad for me :( I wasn't expecting that answer at all. I guess I learned a lesson about no making assumptions.
Does this change with c++17?
14

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.