推断lambda或任意可调用的“make_function”的调用签名。 [英] Inferring the call signature of a lambda or arbitrary callable for "make_function"
问题描述
在某些情况下,需要能够使用 operator()
,lambda,<$ c $来类型擦除可调用(例如函数,函数指针, c> mem_fn ),例如在使用Boost适配器与C ++ 11 lambdas 其中需要一个可复制赋值和默认构造类型。
In some situations it's desirable to be able to type-erase a callable (e.g. function, function pointer, object instance with operator()
, lambda, mem_fn
), for instance in Using Boost adaptors with C++11 lambdas where a copy-assignable and default-constructible type is required.
std :: function
将是理想的,但似乎没有办法自动确定什么签名实例化类模板 std :: function
与。有一个简单的方法来获取任意可调用的函数签名和/或将它包装在适当的 std :: function
实例化实例中(即 make_function
函数模板)?
std::function
would be ideal, but there seems to be no way to automatically determine what signature to instantiate the class template std::function
with. Is there an easy way to get the function signature of an arbitrary callable and/or wrap it in an appropriate std::function
instantiation instance (i.e. a make_function
function template)?
具体来说,我正在寻找
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()的对象) 。
such that make_function([](int i) { return 0; })
returns a std::function<int(int)>
. Obviously this wouldn't be expected to work if an instance is callable with more than one signature (e.g. objects with more than one, template or default-parameter operator()
s).
Boost是好的,虽然不是非过于复杂的非Boost解决方案是首选。
Boost is fine, although non-Boost solutions that aren't excessively complex are preferred.
编辑:回答我自己的问题。
answering my own question.
推荐答案
讨厌的非库解决方案,使用lambdas有 operator()
的事实:
I've come up with a fairly nasty non-library solution, using the fact that lambdas have 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)); }
任何可以简化或改进的想法?任何明显的错误?
Any ideas where this can be simplified or improved? Any obvious bugs?
这篇关于推断lambda或任意可调用的“make_function”的调用签名。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!