I have a question regarding C++0x lambdas. In my code, it would be beneficial to know whether or not a given type is the type of a C++0x lambda expression. To give an example:
struct foobar
{
void operator()()
{
}
};
auto lambda = []{};
typedef is_lambda < decltype(lambda) > ::type T; // T would be a true_type
typedef is_lambda < foobar > ::type T; // T would be a false_type
It is rather easy to distinguish lambda expressions from function and member function types. Functors are another matter.
The problem I see here is the definition of lambda expressions according to the upcoming C++0x standard; the only thing that must be defined is a public call operator. However, this is true for a functor as well; testing for the presence of the call operator is not enough for distinguishing lambda expressions from functors. Furthermore, if the operator of a functor is not present, a compiler error will occur, since SFINAE does not apply. When does this happen? The functor's call operator may be templated. So, such a code:
typedef decltype(&T::operator()) call_type;
will work for both lambda expressions and functors with non-templated call operator, and generate a compiler error for templated call operators.
I believe an is_lambda < >
trait can only be created using intrinsic compiler features. Do you see a way how to implement this trait?
I created a header-only compiler specific (msvc >= 19.20?, gcc >= 7.3, clang >= 6.0) is_lambda
type trait in c++17 if anyone interested in.
https://github.com/schaumb/is_lambda-cpp-type-trait
This can be used as in the question:
struct foobar
{
void operator()()
{
}
};
auto lambda = []{};
typedef bxlx::is_lambda < decltype(lambda) > T; // T is true_type
typedef bxlx::is_lambda < foobar > U; // U is false_type
There are more examples for the usage.
It's possible to define some macro code that determines if an expression is a lambda expression (but that's not very useful as it doesn't tell you if an expression is of a lambda type).
#include <type_traits>
template<typename T, typename U>
struct SameType {
static_assert(!std::is_same<T, U>::value, "Must use Lambda");
static T pass(T t) { return t; }
};
template <typename T, typename U>
T NotLambda(T t, U u) { return SameType<T, U>::pass(t); }
#define ASSERT_LAMBDA(x) NotLambda(x,x)
/////////////////////////////////////
int fn() { return 0; }
int main() {
auto l = []{ return 0; };
return ASSERT_LAMBDA(fn)() + // << fails
ASSERT_LAMBDA(l)() + // << fails
ASSERT_LAMBDA([]{ return 0; })(); // << passes
}
This depends on section 5.1.2.3 which specifies that each lambda expression has a distinct type (which I think is a property unique to lambdas).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With