如何确定std :: function的参数数量? [英] How do I determine the number of parameters of a std::function?

查看:131
本文介绍了如何确定std :: function的参数数量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下问题。假设您要编写一个通用函数,该函数可以使用lambda表达式。我知道,如果参数的类型为std :: function,则不仅可以使用lambda,还可以使用函数,甚至指向函数的指针。因此,第一步,我做了以下操作:

I have the following problem. Say you want to write a generic function that can take a lambda expression. I understand that if the parameter is of type std::function, then I could not only use lambdas, but also functions and even pointers to functions. So at a first step, I did the following:

void print(std::function<void(int, int)> fn) {
  fn(1,2);
}

int main() {

  print([](int i, int j) { std::cout << j <<','<<i<<'\n'; });
  return 0;
}

现在的问题是我想使此函数通用,这意味着不想让lambda表达式只有两个参数。
因此,我尝试将打印功能的签名更改为更通用的名称,例如:

Now the problem is that I want to make this function generic, meaning that I don't want the lambda expression to have only two parameters. So I tried changing the signature of the print function to something more generic like:

template <class function_type>
void print(function_type fn);

但是现在的问题是该函数接受任何对象,我对此不太满意。
但是主要的问题是,我不知道对象fn可以接受多少个参数。

But now the problem is that the function takes ANY object and I'm not ok with that. But the main problem is that, I have no idea how many parameters the object fn can accept.

因此,我正在寻找一种编译方式确定fn有多少个参数以及将fn的类型更改为std :: function的时间方法。然后,鉴于我知道fn接受的参数数量,是否存在一种通用方法来打包要传递给fn的任意数量的参数?我什至不知道这在C ++ 11中是否可行。我的意思是给定参数数量,是否有办法打包参数传递给fn?这样,如果有两个参数,那么我将调用

So in a way I'm looking for a compile time way to determine how many arguments fn has, and if possible to change the type of fn to std::function. And then, given that I know the number of parameters that fn accepts, is there a generic way to pack an arbitrary number of parameters to be passed to fn? I don't even know if this is possible within C++11. What I mean is that given the number of arguments, is there a way to pack parameters to pass to fn? So that if there are two arguments, then I would call

fn(arg1, arg2);

如果有三个:

fn(arg1, arg2, arg3);

等。

谢谢

aa

推荐答案

以下代码段可能

这给出了 std :: function 接受的参数数量

This gives the number of arguments that a std::function takes

template <typename Signature>
struct count_args;

template <typename Ret, typename... Args>
struct count_args<std::function<Ret(Args...)>> {
    static constexpr size_t value = sizeof...(Args);
};

例如以下代码编译(clang 3.2,gcc 4.7.2和icc 13.1.0)

For example the following code compiles (clang 3.2, gcc 4.7.2 and icc 13.1.0)

static_assert(count_args<std::function<void()        >>::value == 0, "Ops!");
static_assert(count_args<std::function<void(int)     >>::value == 1, "Ops!");
static_assert(count_args<std::function<void(int, int)>>::value == 2, "Ops!");

据我了解,您想调用传递正确数量参数的函数对象,对?然后,对于每个参数,我们需要提供一个可转换为其类型的值。具有这种普遍性的解决方案非常困难(甚至不可能)。因此,我将提出两种选择。

As far as I understand, you want to call the function object passing the correct number of arguments, right? Then for each argument we need to provide a value which is convertible to its type. A solution with this generality is very hard (or even impossible). Hence, I'll present two alternatives.

1 每个参数都是其类型的值初始化对象。 (这是 ecatmur 建议的内容。)

1 Each argument is a value initialized object of its type. (This is what ecatmur suggested.)

template <typename Ret, typename... Args>
Ret call(const std::function<Ret(Args...)>& f) {
    return f(Args{}...); // for the intel compiler replace {} with ()
}

2 给出了一个固定值,并且所有参数都从该值隐式初始化:

2 A fixed value is given and all the arguments are implicitly initialized from this value:

template <typename Ret, typename... Args, typename Val, typename... Vals>
typename std::enable_if<sizeof...(Args) == sizeof...(Vals), Ret>::type
call(const std::function<Ret(Args...)>& f, const Val&, const Vals&... vals) {
    return f(vals...);
}

template <typename Ret, typename... Args, typename Val, typename... Vals>
typename std::enable_if<(sizeof...(Args) > sizeof...(Vals)), Ret>::type
call(const std::function<Ret(Args...)>& f, const Val& val, const Vals&... vals) {
    return call(f, val, val, vals...);
}

这三个重载是明确的,可以用作以下示例所示: / p>

The three overloads are unambiguous and can be used as the following examples show:

{
    std::function<char()> f = []() -> char {
        std::cout << "f() ";
        return 'A';
    };
    std::cout << call(f)    << std::endl; // calls f()
    std::cout << call(f, 0) << std::endl; // calls f()
}
{
    std::function<char(int)> f = [](int i) -> char {
        std::cout << "f(" << i << ") ";
        return 'B';
    };
    std::cout << call(f)    << std::endl; // calls f(0)
    std::cout << call(f, 1) << std::endl; // calls f(1)
}
{
    std::function<char(int, int)> f = [](int i, int j) -> char {
        std::cout << "f(" << i << "," << j << ") ";
        return 'C';
    };
    std::cout << call(f)    << std::endl; // calls f(0, 0)
    std::cout << call(f, 2) << std::endl; // calls f(2, 2)
}

这篇关于如何确定std :: function的参数数量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆