Open nandor opened 2 years ago
I wonder why you can give a lambda with non-empty catch clause to a std::function<void(void)>
.
https://en.cppreference.com/w/cpp/language/lambda#ClosureType::operator.28.29.28params.29
This user-defined conversion function is only defined if the capture list of the lambda-expression is empty.
I wonder why you can give a lambda with non-empty catch clause to a
std::function<void(void)>
.https://en.cppreference.com/w/cpp/language/lambda#ClosureType::operator.28.29.28params.29
This user-defined conversion function is only defined if the capture list of the lambda-expression is empty.
The user-defined conversion function to function pointer type shouldn't be used here, because std::function
can directly be constructed from a Callable
object, that's overload (5) here. The usual implementation is that it copies over the Callable
object into dynamically allocated storage. See the note below:
When the target is a function pointer or a std::reference_wrapper, small object optimization is guaranteed, that is, these targets are always directly stored inside the std::function object, no dynamic allocation takes place. Other large objects may be constructed in dynamic allocated storage and accessed by the std::function object through a pointer.
We've previously discussed this here. Our conclusion then appears to have been that we should force lambdas to have internal linkage. Clang seems to have never implemented that; in r151029, Doug Gregor gave lambdas external linkage in the situations where they have a stable mangling. It looks like GCC and ICC are doing the same. So effectively compilers are implementing option 1 from that mailing list post.
If compilers aren't going to give lambdas internal linkage in these situations, the ABI needs to define a layout for them. As far as I can tell, Clang, GCC, and ICC are all trying to use the same layout rule: explicit captures are added in declaration order, then implicit captures are added in the source order of their ODR use in the lambda body. The exception which causes this incompatibility is that GCC seems to order implicit this
arguments (and only implicit ones) after the formal call arguments. I would argue that that's just a GCC bug, and the this
argument should be ordered as if it were written in source. @jicama, do you agree?
Compiler inlining of methods which define lambdas leads to issues. If the creation site is inlined and compiled with a separate compiler, the linker can still decide to replace the function with an implementation from another compiler capturing items in a different order. Since the creation site and the lambda implementation do not match, incorrect parameters are passed to the function.
Is this undefined behaviour or an issue with the ABI?
A minimal example to reproduce the error can be found here: https://github.com/nandor/lambda-abi-error