gimmeamilk
gimmeamilk

Reputation: 2110

C++11: convert lambdas to function-objects in source

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

Answers (2)

Patryk Obara
Patryk Obara

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

Phil Miller
Phil Miller

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

Related Questions