gpt4 book ai didi

c++ - 接受仿函数/可调用对象的可变参数函数

转载 作者:IT老高 更新时间:2023-10-28 21:42:11 26 4
gpt4 key购买 nike

问题

我希望创建一个函数,它接受任意数量的仿函数对象或更一般地只是可调用对象(不同类型)并将它们应用于内部数据结构。该函数将在我的代码中的不同点与不同数量的仿函数一起使用。

我考虑过使用可变参数模板,而不是制作不同的版本来接受 1、2、3... 等和重复代码。

我找到了一个解决方案,我将在下面发布作为答案,因为我在 Google 上找不到任何关于此的具体内容,其他人可能会觉得它很有用。但是,如果有人有更好的想法,请发布它们。我觉得应该有一个标准的方法来做到这一点?

天真的尝试

我知道这行不通,但我的第一次尝试是

#include <iostream>
using namespace std;

struct FunctorA {
void operator() () {
cout << "FunctorA" << endl;
}
};

struct FunctorB {
void operator() () {
cout << "FunctorB" << endl;
}
};

template<typename... Fs>
void apply_functors(Fs... fs) {
fs()...; // will not work - can only expand packs in certain situations (e.g. as funciton
}

int main(void) {
apply_functors(FunctorA(),FunctorB());
apply_functors(FunctorA());
apply_functors([]()->void{ cout << "Lambda" << endl; });
return 0;
}

但是这不起作用,因为我们只允许在 certain situations 中扩展参数包像这样的免费不是一个。

尝试 2

我的下一个想法是创建一个虚拟函数,它什么都不做,但我可以将仿函数作为参数传递给它,然后让它们展开。这背后的原因是函数参数是我们可以扩展参数包的情况之一。

template<typename... Fs>
void _dummyF_impl(Fs... fs){}

template<typename... Fs>
void apply_functors(Fs... fs) {
_dummyF_impl( fs()... ); // only works if all functors return a value (else we get "invalid use of 'void'")
}

但是,这不起作用,因为仿函数从它们的 operator() 中返回 void,我们不能将 void 作为参数传递给函数。

最佳答案

在花括号初始化器内扩展参数包具有保证从左到右评估的额外好处(函数参数列表不是这种情况)。您还应该考虑使用完美转发,here's why .

#include <initializer_list>  //
#include <utility> // std::forward

template<typename... Fs>
void apply_functors(Fs&&... fs)
{
auto list = { (std::forward<Fs>(fs)(), 0)... };
// ^^^^ deduced as std::initializer_list
}

原则上相同,但这次没有必要包含 <initializer_list>是一个可变参数模板构造函数,您也可以使用大括号初始化器调用它:

struct dummy {
template<typename... Fs>
dummy(Fs&&... fs) { }
};

template<typename... Fs>
void apply_functors(Fs&&... fs)
{
dummy { (std::forward<Fs>(fs)(), 0)... }; // evaluated left-to-right, too
}

关于c++ - 接受仿函数/可调用对象的可变参数函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18077259/

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