Reputation: 2110
I have a library of C++11 code that I need to build on an older compiler that has no support for lambdas. It is not practical to manually change all the lambdas into hand-crafted function-objects.
Does anyone know of a tool that I can run as a precompilation step, that will automatically extract all the lambdas into their equivalent function-classes? I was wondering if I could use clang's front end perhaps.
Upvotes: 2
Views: 217
Reputation: 1847
Does anyone know of a tool that I can run as a precompilation step, that will automatically extract all the lambdas into their equivalent function-classes?
Well, such tool might theoretically exist, but even if it did it would be more practical to simply switch to newer compiler in the first place.
Let's consider following code:
template <class F>
auto apply_0(F f) -> decltype(f(0)) {
auto g = [f] (int x) { return f(x); };
return g(0);
}
In this case, our tool would need to either generate function object, that returns auto
type (which implies, that generated code would need to be compilable using C++14) or instantiate template to detect all possible return types, that appear in code (at this point it would be easier to switch to C++14).
But, let's consider even most optimistic situation: all lambda expressions throughout project define their return types using ->
and they don't appear in template functions - in this case theoretically you could convert lambda expression to equivalent struct with operator()
and constructor, that captures variables as struct members - would it give you code, that behaves the same way? Answer is: it's implementation-defined.
Consider even smallest possible lambda:
auto f = [] { return 0; };
cout << is_pod<decltype(f)>::value << endl;
When compiled with g++ - this code will write '0', with clang++ - it will write '1'. If we converted this lambda to function object - resulting struct would be POD type in both gcc and clang. Another example:
int x = 42;
auto f = [x] { return x; };
cout << is_pod<decltype(f)>::value << endl;
g++ will still give '0', clang++ will still give '1'. During conversion to struct we would need to write some initializer (constructor or other) for binded member x
of our function object - depending on implementation it could be POD or non-POD, either way - it may be different than what compiler does when creating anonymous closure object for lambda.
Other things, that may change are listed by C++11 standard, § 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).
As always, your code shouldn't depend on implementation-defined parts of language - so this is not such a big deal, but it may lead to unexpected consequences nonetheless.
Upvotes: 2
Reputation: 38118
There isn't such a tool already built as far as I know, but if you were to try to implement one, your best choices of infrastructure would be Clang and ROSE.
Upvotes: -1