I'm trying to use a lambda as a static member, like this:
struct A
{
static constexpr auto F = [](){};
};
int main()
{
A::F();
return 0;
}
Is this even correct C++11 code? On clang, I get this error:
error: constexpr variable 'F' must be initialized by a constant
expression
static constexpr auto F = [](){};
^~~~~~
It seems in clang, lambdas aren't considered a constant expression. Is this correct? Perhaps they haven't fully implemented lambdas yet in clang because gcc 4.7 seems to allow it as a constexpr
, but it give another error:
error: ‘constexpr const<lambda()> A::F’, declared using local type ‘const<lambda()>’, is used but never defined
I'm not sure, I understand what that means. It seems to correctly deduce the type of the lambda, but it only declares it and not define it. How would I go about defining it?
This code is ill-formed. A
constexpr
variable is required to be initialized by a constant expression, and[expr.const]p2
says:GCC is therefore incorrect to accept this code.
Here's one way to give a class a static data member of lambda type:
You can make it work, in clang 3.4, as long as the lambda doesn't capture anything. The idea is directly from Pythy .
There are two potentially controversial bits here. First, there's the fact that
A::F
isconstexpr
, but it has a lambda in its definition.That should be impossible right? No. A ternary expression
b ? v1 : v2
can be aconstexpr
without requiring all three ofb
,v1
,v2
to beconstexpr
. It is sufficient merely thatb
isconstexpr
along with one of the remaining two (depending on whetherb
istrue
orfalse
. Hereb
isfalse
, and this selects the final part of the?:
, i.e.nullptr
.In other words
false ? a_non_constexpr_func() : a_constexpr_func()
is aconstexpr
. This appears to be the interpretation in clang anyway. I hope this is what's in the standard. If not, I wouldn't say that clang "should not accept this". It appears to be a valid relaxation of the rule. The unevaluated part of a?:
is unevaluated and therefore itconstexpr
-ness shouldn't matter.Anyway, assuming this is OK, that gives us a
nullptr
of the correct type, i.e. the type of a pointer to the lambda. The second controversial bit is(*A::F)(1337);
where we are dereferencing the null pointer. But it is argued by the page linked above that that is not a problem: