As per [expr.const]/2, a lambda-expression is explicitly forbidden to be part of a core constant expression. It can appear in an unevaluated operand of a ternary operator, e.g. p ? 42 : [](){ return 255; }();
, if p
evaluates to true
.
That said, a lambda may also appear in a constexpr
function, however, that part may not be evaluated when the function is to be used in a constant expression. Example:
constexpr unsigned long long int operator "" _b(const char* s)
{
return *s == '0' || *s == 0 ? 0 : [=]() mutable
{
unsigned long long ret = 0;
for(; *s != 0; ++s)
{
ret <<= 1;
if(*s == '1') ret += 1;
}
return ret;
}();
}
#include <iostream>
int main()
{
constexpr int c = 0_b; // fine
//constexpr int c1 = 1_b; // error
std::cout << 1010_b << std::endl; // fine
}
Of course, this is not very useful; the operator is constexpr
to allow parsing strings as binary literals in constant expressions. Therefore, the parts of the operator that do this conversion must be valid (core) constant expressions.
As the signature of the operator is precisely specified, you cannot recur on the operator itself and pass the processed data as an additional argument. You may not use loops in C++11's constexpr
either.
Of course, you can use namespaces. This might even be better for the user:
namespace my_literals
{
constexpr unsigned long long ToBinary(unsigned long long x, const char* s)
{
return (!*s ? x : ToBinary(x + x + (*s =='1'? 1 : 0), s+1));
}
constexpr unsigned long long int operator "" _b(const char* s)
{ return ToBinary(0,s);}
}
// user writes:
using my_literals::operator ""_b;