You can make it work, in clang 3.4, as long as the lambda doesn't capture anything. The idea is directly from Pythy .
#include <type_traits>
#include <iostream>
template<typename T>
auto address(T&& t) -> typename std:: remove_reference<T> :: type *
{
return &t;
}
struct A
{
static constexpr auto * F = false ? address(
[](int x){ std:: cout << "It worked. x = " << x << std:: endl;
}
) : nullptr; // a nullptr, but at least its *type* is useful
};
int main()
{
(*A::F)(1337); // dereferencing a null. Doesn't look good
return 0;
}
There are two potentially controversial bits here. First, there's the fact that A::F is constexpr, but it has a lambda in its definition.
That should be impossible right? No. A ternary expression b ? v1 : v2 can be a constexpr without requiring all three of b, v1, v2 to be constexpr. It is sufficient merely that b is constexpr along with one of the remaining two (depending on whether b is true or false. Here b is false, and this selects the final part of the ?:, i.e. nullptr.
In other words false ? a_non_constexpr_func() : a_constexpr_func() is a constexpr. 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 it constexpr-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:
It appears that we are derefencing a null pointer. Remember in C++ when dereferencing a null pointer, undefined behavior occurs when there is an lvalue-to-rvalue conversion. However, since a non-capturing lambda closure is almost always implemented as an object with no members, undefined behavior never occurs, since it won't access any of its members. Its highly unlikely that a non-capturing lambda closure could be implemented another way since it must be convertible to a function pointer. But the library does statically assert that the closure object is empty to avoid any possible undefined behavior.