如何检查函数的参数类型? [英] How to inspect the types of a function's parameters?
问题描述
我有一个应用程序,其中我正在建立一个函数 marshal_and_apply
,它调用一些其他函数(或函子), f
有一些参数。 marshal_and_apply
的作业是根据 f
的参数类型对参数应用一些特殊的封送处理。 / p>
如果 f
的某个参数是特殊类型, marshal_me& ,然后
marshal_and_apply
将通过一些特殊分配的存储编组参数,然后将其传递给 f
。为了执行分配,在任何可以编组之前,所有参数的存储需求必须已知为 marshal_and_apply
。
一些示例:
模板< typename函数,typename ... Args>
void marshal_and_apply(Function f,Args ... args);
void func1(int x,int y);
void func2(marshal_me< int> x,int y);
void func3(marshal_me< int> x,marshal_me< int> y,marshal_me< int> z)
//这个调用相当于:
// func1(7,13)
marshal_and_apply(func1,7,13);
//这个调用相当于:
// auto storage = my_allocator(sizeof(int));
// auto x = marshal_me< int>(7,storage);
// func2(x,13);
marshal_and_apply(func2,7,13);
//这个调用相当于:
// auto storage = my_allocator(sizeof(int)+ sizeof(int)+ sizeof(int));
// auto x = marshal_me< int>(7,storage);
// auto y = marshal_me< int>(13,storage + sizeof(int));
// auto z = marshal_me< int>(42,storage + sizeof(int)+ sizeof(int));
// func3(x,y,z);
marshal_and_apply(func3,7,13,42);
为了解决这个问题, c $ c> marshal_and_apply 需要一种机制来检查 f
的参数类型。我怀疑这通常是不可能的,但是可以识别特殊的一组类型(在这种情况下, marshal_me
)中的一个是可转换的到特定参数的类型。
如何构建 marshal_and_apply
?
可能类似这样:
template< ,typename ... Args>
void marshal_and_apply(function f,Args& ... args)
{
f(InspectAndModify< Args> :: process(sizeof ...(Args),std :: forward& ; Args(args))...);
}
现在定义:
template< typename T> struct InspectAndModify
{
static T&&过程(unsigned int N,T& t)
{
return std :: forward< T&
}
};
template< typename T> struct InspectAndModify< marshal_me< T>>
{
static T&& process(unsigned int N,marshal_me< T&& m)
{
/ * ... * /
}
}
完全不同的这种方法首先剖析函数签名,然后对每对类型执行静态变换,这是您可以插入 marshal_me
specialization:
模板< typename T> struct marshal_me {marshal_me(T){}};
template< typename To,typename From> struct static_transform;
template< typename T> struct static_transform< T,T>
{
static T go(T t){return t; }
};
template< typename T> struct static_transform< T,T&>
{
static T go(T& t){return t; }
};
template< typename T> struct static_transform< marshal_me< T>,T>
{
static marshal_me< T> go(T& t){return std :: forward T(t); }
};
template< typename T,typename ... Args>
struct marshal_impl
{
template< typename ... Urgs>
static T go(T(* f)(Urgs ...),Args& ... args)
{
return f(static_transform< Urgs,Args> :: go(std :: forward< Args>(args))...);
}
};
template< typename Function,typename ... Args>
void marshal_and_apply(function f,Args& ... args)
{
marshal_impl< void,Args ...> :: go(static_cast< typename std :: decay< ; function> :: type>(f),
std :: forward< Args>(args)...)
}
I have an application where I'm building a function, marshal_and_apply
, which calls some other function (or functor), f
with some arguments. marshal_and_apply
's job is to apply some special marshaling for the arguments depending on the type of f
's parameters.
If one of f
's parameters is of a special type, marshal_me<T>
, then marshal_and_apply
will marshal the parameter through some specially allocated storage before passing it to f
. In order to perform the allocation, the storage requirements of all the parameters must be known to marshal_and_apply
before any can be marshaled.
Some examples:
template<typename Function, typename... Args>
void marshal_and_apply(Function f, Args... args);
void func1(int x, int y);
void func2(marshal_me<int> x, int y);
void func3(marshal_me<int> x, marshal_me<int> y, marshal_me<int> z);
// this call would be equivalent to:
// func1(7,13)
marshal_and_apply(func1, 7, 13);
// this call would be equivalent to:
// auto storage = my_allocator(sizeof(int));
// auto x = marshal_me<int>(7, storage);
// func2(x, 13);
marshal_and_apply(func2, 7, 13);
// this call would be equivalent to:
// auto storage = my_allocator(sizeof(int) + sizeof(int) + sizeof(int));
// auto x = marshal_me<int>(7, storage);
// auto y = marshal_me<int>(13, storage + sizeof(int));
// auto z = marshal_me<int>(42, storage + sizeof(int) + sizeof(int));
// func3(x,y,z);
marshal_and_apply(func3, 7, 13, 42);
To solve this problem, it seems that marshal_and_apply
requires a mechanism to inspect the types of f
's parameters. I suspect this isn't possible in general, but it may be possible to recognize whether one of a special set of types (in this case, marshal_me<T>
) is convertible to the type of a particular parameter.
How should I build marshal_and_apply
?
Maybe something like this:
template<typename Function, typename... Args>
void marshal_and_apply(Function f, Args &&... args)
{
f(InspectAndModify<Args>::process(sizeof...(Args), std::forward<Args>(args))...);
}
Now define:
template <typename T> struct InspectAndModify
{
static T&& process(unsigned int N, T && t)
{
return std::forward<T>(t);
}
};
template <typename T> struct InspectAndModify<marshal_me<T>>
{
static T&& process(unsigned int N, marshal_me<T> && m)
{
/* ... */
}
};
Something completely different: This approach first dissects the function signature, and then performs a "static transform" on each pair of types, which is where you can insert the marshal_me
specialization:
template <typename T> struct marshal_me { marshal_me(T) { } };
template <typename To, typename From> struct static_transform;
template <typename T> struct static_transform<T, T>
{
static T go(T t) { return t; }
};
template <typename T> struct static_transform<T, T&>
{
static T go(T & t) { return t; }
};
template <typename T> struct static_transform<marshal_me<T>, T>
{
static marshal_me<T> go(T && t) { return std::forward<T>(t); }
};
template<typename T, typename... Args>
struct marshal_impl
{
template <typename ...Urgs>
static T go(T(*f)(Urgs...), Args &&... args)
{
return f(static_transform<Urgs, Args>::go(std::forward<Args>(args))...);
}
};
template<typename Function, typename... Args>
void marshal_and_apply(Function f, Args &&... args)
{
marshal_impl<void, Args...>::go(static_cast<typename std::decay<Function>::type>(f),
std::forward<Args>(args)...);
}
这篇关于如何检查函数的参数类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!