在一些情况下,它是期望的是能够键入擦除一个可调用(例如功能,函数指针,与对象实例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)。
升压是好的,虽然非升压的解决方案,也不会过复杂的是优选的。
编辑:回答我的问题。
我想出了一个相当讨厌的非图书馆解决方案,使用的事实,有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)); }
任何想法在那里这可以简化或改进? 任何明显的错误?
不可能。 您可以采取的地址operator()
对于某些类型的,而不是任意调用,因为它很可能具有过载或模板参数。 它是否将工作拉姆达是最稳妥不明确,据我所知。
对于非可变参数非通用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”