[英]Is it possible to retrieve the argument types from a (Functor member's) function signature for use in a template?
Assume you have a functor:假设你有一个函子:
struct MyFunctor
{
bool operator ()( int value )
{
return true;
}
};
Is it possible to retrieve a functor's member's argument type for use within your template?是否可以检索仿函数成员的参数类型以在模板中使用? The following is a use of this mythical functionality:
以下是这个神秘功能的使用:
template < typename FunctorType >
bool doIt( FunctorType functor, typename FunctorType::operator()::arg1 arg )
{
return functor( arg );
}
Is there a valid syntax that would substitute for my mythical FunctorType::operator()::arg1
?是否有有效的语法可以替代我神话中的
FunctorType::operator()::arg1
?
If you know the item is a functor, then you can just grab its operator()
, like so:如果您知道该项目是一个仿函数,那么您可以抓住它的
operator()
,如下所示:
#include <iostream>
template <unsigned Idx, typename... T>
struct pick
{
static_assert(Idx < sizeof...(T), "cannot index past end of list");
};
template <typename T, typename... TRest>
struct pick<0U, T, TRest...>
{
typedef T result;
};
template <unsigned Idx, typename T, typename... TRest>
struct pick<Idx, T, TRest...>
{
typedef typename pick<Idx-1, TRest...>::result result;
};
template <typename Func>
struct func_traits;
template <typename TObj, typename R, typename... TArgs>
struct func_traits<R (TObj::*)(TArgs...)>
{
typedef R result_type;
template <unsigned Idx>
struct argument
{
typedef typename pick<Idx, TArgs...>::result type;
};
};
template <typename Func,
typename Traits = func_traits<Func>,
typename R = typename Traits::result_type,
typename Arg0 = typename Traits::template argument<0>::type,
typename Arg1 = typename Traits::template argument<1>::type
>
void foo(Func f)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
};
struct thing
{
void operator()(long, int*) { }
};
int main()
{
foo(&thing::operator());
}
For me, that program prints out:对我来说,该程序打印出来:
void foo(Func) [with Func = void (thing::*)(long int, int*), Traits = func_traits<void (thing::*)(long int, int*)>, R = void, Arg0 = long int, Arg1 = int*]
The key point being that Arg0
and Arg1
are long
and int*
, respectively.关键是
Arg0
和Arg1
分别是long
和int*
。
No there is not.不,那里没有。 The most elegant way to do this would be to either require your functors to provide a
typedef
for the argument-type, or to introduce a traits-class.最优雅的方法是要求仿函数为参数类型提供
typedef
,或者引入特征类。 The latter is useful if you want your template to work with functors and functions.如果您希望模板与仿函数和函数一起使用,后者很有用。
Alternatively, you can just make the argument type a second template parameter:或者,您可以将参数类型设置为第二个模板参数:
template < typename FunctorType, class ArgumentType >
bool doIt( FunctorType functor, ArgumentType arg )
{
return functor( arg );
}
The compiler will still complain if ArgumentType
does not match the type required by the functor.如果
ArgumentType
与仿函数所需的类型不匹配,编译器仍然会报错。
You can sort of do it in C++0x你可以用 C++0x 来做
template <typename... Args>
struct Function {
typedef std :: tuple <Args...> args;
void call () (Args... args);
}
template <typename... Args>
void do_it (Function<Args...>::args:: SOMETHING :: type t, Args... args) {
something (t)
Function <Args...> :: call (args...);
}
Here I give a C++11 update to @BjörnPollex (correct) answer.在这里,我将 C++11 更新为@BjörnPollex(正确)答案。
Going back the question, you want to specify the second argument of doIt
explicitly mainly to restrict what can be passed.回到问题,您想明确指定
doIt
的第二个参数,主要是为了限制可以传递的内容。 In C++11 you can imply this restriction without knowing explicitly the argument type of the functor (which is not well defined if the functor overloaded anyway).在 C++11 中,您可以在不明确知道函子的参数类型的情况下暗示此限制(如果函子重载,则定义不明确)。
template < typename FunctorType, class ArgumentType >
auto doIt( FunctorType functor, ArgumentType arg ) -> decltype(bool(functor(arg)))
{
return functor( arg );
}
(the conversion to bool
may not be even necessary, I put it here because it seem that you really want the return type to be bool
). (甚至可能不需要转换为
bool
,我把它放在这里是因为您似乎真的希望返回类型为bool
)。
This doIt
(template) function will take any argument that is possibly compatible with a functor
argument (and also convertible to bool
).这个
doIt
(模板) function 将采用任何可能与仿functor
参数兼容的参数(也可以转换为bool
)。 If the argument passed is not compatible the function will not even exist at all, and will produce an elegant "doIt function not found" compiler error.如果传递的参数不兼容,则 function 将根本不存在,并且会产生优雅的“doIt function not found”编译器错误。
One can go one step more by using perfect forward to make doIt
exactly equivalent to functor(arg)
:可以通过使用完美前进使
doIt
与functor(arg)
完全等价,再进一步 go :
template < typename F, class A >
auto doIt( F&& f, A&& a ) -> decltype(bool(std::forward<F>(f)(std::forward<A>(a))))
{
return std::forward<F>(f)( std::forward<A>(a) );
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.