且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

检测是否可以将C ++ lambda转换为函数指针

更新时间:2021-11-10 05:58:25

您希望将lambda转换为的函数,您可以利用 std :: is_assignable trait:

If you know the signature of a function you want your lambda to be converted to, you can leverage the std::is_assignable trait:

auto lambda = [] (char, double) -> int { return 0; };
using signature = int(char, double);
static_assert(std::is_assignable<signature*&, decltype(lambda)>::value, "!");

DEMO

这种方法也可以与通用lambdas一起使用。

This way it can work also with generic lambdas.


我想要一个解决方案,适用于vs 2013/2015,gcc和clang

I'd like to have a solution that works for vs 2013/2015, gcc and clang

如果你不知道签名,这里是一个替代方法来检查 + 触发隐式转换。这一个利用 std :: is_assignable 测试,并验证lambda是否可分配给与lambda的函数调用操作符具有相同签名的函数指针。 (就像使用一元运算符plus的测试,这不适用于通用lambdas。但是在C ++ 11中没有通用的lambdas)。

If you don't know the signature, here's an approach that is an alternative to checking whether + triggers an implicit conversion. This one exploits the std::is_assignable test and verifies whether a lambda is assignable to a function pointer with the same signature as the lambda's function call operator. (Just like a test with unary operator plus, this doesn't work with generic lambdas. But in C++11 there are no generic lambdas).

#include <type_traits>

template <typename T>
struct identity { using type = T; };

template <typename...>
using void_t = void;

template <typename F>
struct call_operator;

template <typename C, typename R, typename... A>
struct call_operator<R(C::*)(A...)> : identity<R(A...)> {};

template <typename C, typename R, typename... A>
struct call_operator<R(C::*)(A...) const> : identity<R(A...)> {};

template <typename F>
using call_operator_t = typename call_operator<F>::type;

template <typename, typename = void_t<>>
struct is_convertible_to_function
    : std::false_type {};

template <typename L>
struct is_convertible_to_function<L, void_t<decltype(&L::operator())>>
    : std::is_assignable<call_operator_t<decltype(&L::operator())>*&, L> {};

测试:

int main()
{
    auto x = [] { return 5; };
    auto y = [x] { return x(); };

    static_assert(is_convertible_to_function<decltype(x)>::value, "!");
    static_assert(!is_convertible_to_function<decltype(y)>::value, "!");
}

GCC VC ++ Clang ++