6

The C++11 standard says (or at least, the version I have - not the final one) :

The closure type for a lambda-expression with no lambda-capture has a public non-virtual non-explicit const conversion function to pointer to function having the same parameter and return types as the closure type’s function call operator.

I understand why it is not possible to get a function pointer from a stateful lambda since a function pointer cannot hold any data by itself.

But when the captured objects are just a static members /static variable, there is no such limitation since the references to the captured objects can be hardwired in the function itself.

struct A {
    static int count = 0;
    void foo() {
         static int bar = 0;
         auto fun = [&]()->void {
             count++;
             bar++;
         };
         void(*ptrFun)();
         ptrFun = fun; // forbidden by the quoted wording
    }
};

Why isn't it always possible to convert a lambda to a function pointer as soon as the former is stateless ? Am I missing something or does the committee forgot this specific point ?

Frédéric Terrazzoni
  • 2,190
  • 19
  • 25
  • 1
    I'd take a guess that it's to avoid requiring compilers to be able to prove anything much about what's being captured. – Flexo Jul 17 '12 at 22:59
  • The compiler is already able to automatically capture variables as soon as they are used (using the automatic [&]), so it won't involve a lot more work to check if the they are static members or global since they've necessarily been declared before. – Frédéric Terrazzoni Jul 17 '12 at 23:05
  • Actually I've not tested it on any compiler (I only have MSVC10 which doesn't support function pointer conversion at all). I guess it is a GCC extension ? Anyway, my question is : it is allowed by the standard (maybe I missed something) ? If no, why is it forbidden (maybe there is a technical limitation I don't know about) ? – Frédéric Terrazzoni Jul 17 '12 at 23:11

1 Answers1

9

A::count does not need to be captured at all. Only this and local variables need to be captured. Variables with static storage duration (e.g., static data members, namespace-scope variables, or function-local static variables) do not need to be captured because they are "unique." There is exactly one instance of each such variable, so a reference to the object does not need to be captured.

If you remove the default capture from your lambda (i.e., change [&] to []) and define count, it should compile without error. (I've verified that both Visual C++ 2012 RC and g++ 4.5.1 accept the code; the only change I had to make was to move the inline initialization of count, since neither of those compilers supports that C++11 feature yet.)

James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • Yes of course... I'm feeling stupid now :) But, what if we want to capture a static local variable ? – Frédéric Terrazzoni Jul 17 '12 at 23:40
  • They also do not need to be captured, for the same reason: each static local variable is "unique" and has a known address. I've amended the answer to refer to "variables with static storage duration." There may still be some subtleties here, though none of which I am aware (and VC11 and g++4.5.1 both accept the program with `count` as a namespace-scope variable, a static data member, or as a function-local static). – James McNellis Jul 17 '12 at 23:47