简体   繁体   English

是否可以从(仿函数成员的)function 签名中检索参数类型以在模板中使用?

[英]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.关键是Arg0Arg1分别是longint*

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) :可以通过使用完美前进使doItfunctor(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.

相关问题 C ++ - 是否可以从模板中的成员函数类型中提取类和参数类型? - C++ - is it possible to extract class and argument types from a member function type in a template? 可以使用functor作为std :: function的模板参数吗? - Is possible to use functor as template parameter to std::function? 模板函数+函子参数,为什么函子没有内联? - Template function + functor argument, why the functor is not inlined? 模板函数作为模板函子的模板参数 - Template function as template argument for template functor 如何使用模板成员 function 作为另一个模板成员 function 的参数? - How to use a template member function as an argument to another template member function? 如何将functor用作类模板中的成员? - How to use functor as a member in class template? 如何使用模板特化来查找成员函数参数类型等? - How can I use template specialisation to find member function argument types etc? class 成员 function 参数列表是否可能依赖于模板参数? - Is it possible for a class member function argument list to be dependent on a template argument? 使模板 function 反映其模板参数的签名 - Making a template function mirror its template argument's signature 是否可以使用成员函数调用作为默认参数? - Is it possible to use member function call as default argument?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM