gpt4 book ai didi

c++ - 如何确定 std::function 的参数数量?

转载 作者:塔克拉玛干 更新时间:2023-11-03 06:51:05 24 4
gpt4 key购买 nike

我有以下问题。假设您想编写一个可以采用 lambda 表达式的通用函数。我知道如果参数是 std::function 类型,那么我不仅可以使用 lambda,还可以使用函数甚至函数指针。因此,在第一步中,我执行了以下操作:

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 表达式只有两个参数。所以我尝试将打印函数的签名更改为更通用的签名,例如:

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

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

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

fn(arg1, arg2);

如果有三个:

fn(arg1, arg2, arg3);

等等。

感谢大家的见解。

啊啊

最佳答案

以下片段可能会有用。

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

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)

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!");

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

1 每个参数都是其类型的值初始化对象。 (这就是 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 给定一个固定值,所有参数都从该值隐式初始化:

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...);
}

这三个重载是明确的,可以像下面的例子一样使用:

{
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)
}

关于c++ - 如何确定 std::function 的参数数量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15806319/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com