Re: C++11 lambdas and normal function pointers
Am 02.03.2012 22:00, schrieb Jimmy H.:
In my compiler (gcc 4.6), the following compiles:
#include<cstdio>
typedef int (*callback)();
int main() {
int foo = 0;
callback c = [] () { return 3; };
for (int i = 0; i< 10; i++) {
printf("%i\n", c());
}
return 0;
}
But the following does not compile:
#include<cstdio>
typedef int (*callback)();
int main() {
int foo = 0;
callback c = [&] () { return foo++; };
for (int i = 0; i< 10; i++) {
printf("%i\n", c());
}
return 0;
}
Three questions:
* Is this first program's successful compilation in line with the C+
+11 standard, or is it a GCC extension?
It is part of the standard. The standard requires that a lambda-closure
with *no* captured variables shall provide a non-explicit conversion
function to a function pointer that has the same signature as the
function call operator overload of the closure class.
* Is the rule then that lambdas without contexts are automatically
convertible to C-style function pointers, and that lambdas with
contexts are not?
Exactly.
And most interestingly:
* I know that GCC is capable of using trampolining (which works only
when writable pages can also be executable) to implement things
similar to the second, non-compiling program. Would gcc still be
standards-compliant if it allowed the second program, or does the
standard expressly forbid it? Or am I misunderstanding how standards
work?
I tend to argue that the compiler would still be conforming, at least if
we look at your example. The reason is that you could not create a
well-formed program without that conversion. The situation becomes a bit
more tricky when we involve this conversion with constrained templates.
Given C++11 capabilities, a conforming program could observe this
difference. Consider:
#include <type_traits>
#include <cassert>
template<class T, class P, class = typename std::enable_if<
std::is_convertible<T, P>::value
::type>
std::true_type f(int){ return std::true_type(); }
template<class, class>
std::false_type f(...){ return std::false_type(); }
typedef int (*callback)();
int main() {
int foo = 0;
auto c = [&] () { return foo++; };
assert((f<decltype(c), callback>(0) == 0));
}
This means that a compile would need to provide some extra "extension"
flag to allow it in non-strictly conforming mode.
HTH & Greetings from Bremen,
Daniel Kr?gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]