推断拉姆达或任意调用的调用签名为“make_function”(Inferring the call

2019-06-17 16:14发布

在一些情况下,它是期望的是能够键入擦除一个可调用(例如功能,函数指针,与对象实例operator() ,λ, mem_fn中),例如使用升压适配器与C ++ 11 lambda表达式 ,其中一个副本可分配和默认constructible类型是必需的。

std::function将是理想的,但似乎没有办法自动确定哪些签名实例化类模板std::function用。 有一种简单的方法来获得一个任意调用和/或在适当的包装它的函数签名std::function实例化实例(即make_function函数模板)?

具体来说,我正在寻找一个或另一个

template<typename F> using get_signature = ...;
template<typename F> std::function<get_signature<F>> make_function(F &&f) { ... }

使得make_function([](int i) { return 0; })返回std::function<int(int)> 。 显然,这预计不会工作,如果一个实例是可调用一个以上的签名(例如,使用一个以上的,模板或默认参数对象operator() S)。

升压是好的,虽然非升压的解决方案,也不会过复杂的是优选的。


编辑:回答我的问题。

Answer 1:

我想出了一个相当讨厌的非图书馆解决方案,使用的事实,有lambda表达式operator()

template<typename T> struct remove_class { };
template<typename C, typename R, typename... A>
struct remove_class<R(C::*)(A...)> { using type = R(A...); };
template<typename C, typename R, typename... A>
struct remove_class<R(C::*)(A...) const> { using type = R(A...); };
template<typename C, typename R, typename... A>
struct remove_class<R(C::*)(A...) volatile> { using type = R(A...); };
template<typename C, typename R, typename... A>
struct remove_class<R(C::*)(A...) const volatile> { using type = R(A...); };

template<typename T>
struct get_signature_impl { using type = typename remove_class<
    decltype(&std::remove_reference<T>::type::operator())>::type; };
template<typename R, typename... A>
struct get_signature_impl<R(A...)> { using type = R(A...); };
template<typename R, typename... A>
struct get_signature_impl<R(&)(A...)> { using type = R(A...); };
template<typename R, typename... A>
struct get_signature_impl<R(*)(A...)> { using type = R(A...); };
template<typename T> using get_signature = typename get_signature_impl<T>::type;

template<typename F> using make_function_type = std::function<get_signature<F>>;
template<typename F> make_function_type<F> make_function(F &&f) {
    return make_function_type<F>(std::forward<F>(f)); }

任何想法在那里这可以简化或改进? 任何明显的错误?



Answer 2:

不可能。 您可以采取的地址operator()对于某些类型的,而不是任意调用,因为它很可能具有过载或模板参数。 它是否将工作拉姆达是最稳妥不明确,据我所知。



Answer 3:

对于非可变参数非通用captureless拉姆达功能以及简单的免费功能,可以使用以下方法:

#include <iostream>

#include <cstdlib>

template< typename L, typename R, typename ...A >
constexpr
auto // std::function< R (A...) >
to_function_pointer(L l, R (L::*)(A...) const)
{
    return static_cast< R (*)(A...) >(l);
}

template< typename L, typename R, typename ...A >
constexpr
auto // std::function< R (A...) >
to_function_pointer(L l, R (L::*)(A...)) // for mutable lambda
{
    return static_cast< R (*)(A...) >(l);
}

template< typename L >
constexpr
auto
to_function_pointer(L l)
{
    return to_function_pointer(l, &L::operator ());
}

template< typename R, typename ...A >
constexpr
auto // std::function< R (A...) >
to_function_pointer(R (* fp)(A...))
{
    return fp;
}

namespace
{

void f() { std::cout << __PRETTY_FUNCTION__ << std::endl; }

}

int
main()
{
    to_function_pointer([] () { std::cout << __PRETTY_FUNCTION__ << std::endl; })();
    //to_function_pointer([&] () { std::cout << __PRETTY_FUNCTION__ << std::endl; })(); // can't cast from non-captureless lambda to function pointer
    to_function_pointer([] () mutable { std::cout << __PRETTY_FUNCTION__ << std::endl; })();
    to_function_pointer(f)();
    to_function_pointer(&f)();
    return EXIT_SUCCESS;
}


文章来源: Inferring the call signature of a lambda or arbitrary callable for “make_function”