为"make_function"推断lambda或任意callable的调用签名

eca*_*mur 26 c++ lambda type-inference function c++11

在某些情况下,希望能够键入 - 擦除可调用的(例如函数,函数指针,带有operator()lambda的对象实例mem_fn),例如在使用带有C++ 11 lambdas的Boost适配器中,其中可复制的和可默认构造的类型是必需的.

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) { ... }
Run Code Online (Sandbox Code Playgroud)

这样make_function([](int i) { return 0; })返回std::function<int(int)>.显然,如果一个实例可以使用多个签名(例如,具有多个,模板或默认参数operator()的对象)进行调用,那么预计这不会起作用.

尽管非过度复杂的非Boost解决方案是优选的,但Boost很好.


编辑:回答我自己的问题.

eca*_*mur 29

我提出了一个相当讨厌的非库解决方案,使用lambdas具有的事实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)); }
Run Code Online (Sandbox Code Playgroud)

有什么想法可以简化或改进吗?任何明显的错误?