Open Possseidon opened 2 years ago
If I'm not mistaken, C++20 allows passing lambdas as template parameters, which could not only fix this issue, but also allows me to get rid of the +
before each lambda. The big question is, if GCC allows this or if this is still not possible because of the same reasons as previously (no linkage, which GCC might technically be correct about, but not sure).
Of course, the lambdas still won't be allowed to capture anything, but the conversion to a function pointer can happen inside the wrap
style functions.
Pattern
The following pattern is heavily used in the current Lua bindings:
This is very convenient, as the full context of the class (for e.g. type aliases) is available inside the lambda.
Issue
This works fine on msvc and clang, but gcc gives an error, stating that the lambda cannot be used as it has no linkage - except it doesn't actually give this error at the moment. Everything compiles just fine with gcc... or does it?
Why it works (even though it shouldn't)
The reason it compiles is the (un)lucky coincidence of:
Basically, upgrading gcc or moving the lambdas somewhere that isn't templated will (likely) cause the error.
Workarounds
There are several ways on how one can work around this issue.
1. Wrapping it in
std::function
The probably easiest fix would be to simply type-erase the lambda with a
std::function
. This even has the benefit of having a nice signature when printing in Lua. However it comes with a decent performance hit.2. Use free-standing functions
Simply replacing the lambdas with free-standing functions e.g. right in front of the function in which they are used is generally a good alternative. Context from the class is lost however.
3. Use static constexpr lambdas inside the class
This way, context of the class can be retained. Implementations have to be put in the header however, although that is hopefully not a big deal.
This also has the added benefit of allowing for re-use of wrappers between e.g.
methods()
andproperties()
.4. Proper static functions inside the class
Another option would be to use proper static functions, but implementing them is very verbose, as the entire template header has to be repeated for each and every function.
Conclusion
Use static constexpr lambdas (approach 3) like so:
Header
Source