我想编写一个函数(C++17,如果重要的话),它接受多个可调用对象及其参数并在循环中执行它们。我还想避免任何中间数据复制。
示例:
假设我们有三个函数
f0
、f1
和 f2
,它们需要不同数量的输入参数
void f0() {
// Implementation of f0
}
void f1(int a) {
// Implementation of f1
}
void f2(int a, int b) {
// Implementation of f2
}
我正在寻找一种方法将上述所有函数与示例输入参数一起传递到类或另一个函数中(例如
Execute
)。示例界面如下所示:
int main() {
// If Execute is a class
Execute exec({f0}, {f1, 4}, {f2, 1, 2});
// The result of the command above is a sequence of calls
// 1. f0()
// 2. f1(4)
// 3. f2(1, 2)
}
我想避免任何中间数据复制。
那么我的问题是如何实现这一目标?
这是一个可行的解决方案,它使用模仿您建议的
std::tuple
来实现模板化类。
#include <iostream>
#include <utility>
#include <vector>
#include <tuple>
void f0() {
std::cout << "f0\n";
}
void f1(int a) {
std::cout << "f1: " << a << '\n';
}
void f2(int a, int b) {
std::cout << "f2: " << a + b << '\n';
}
void f3(const std::string a, int b) {
std::cout << "f3: " << a << " ** " << b << '\n';
}
template <typename T1, typename... Ts>
std::tuple<Ts...> unshift_tuple(const std::tuple<T1, Ts...>& tuple)
{
return std::apply(
[](auto&&, const auto&... args) {
return std::tie(args...);
},
tuple
);
}
template <typename Callable, typename... Params>
void call(const std::tuple<Callable, Params...>& t) {
const auto f = std::get<0>(t);
const auto args = unshift_tuple(t);
std::apply(f, args);
}
template <typename... Params>
class Execute {
public:
Execute(std::tuple<Params...>&& t) : m_fs(t) { }
void execute() noexcept {
iterate_over_functions<0>(m_fs);
}
private:
template <typename... Ts>
void call_function(const std::tuple<Ts...>& t) {
std::cout << "Hey!\n";
call(t);
}
template <
std::size_t I = 0,
typename... Ts,
std::enable_if_t<I == sizeof...(Ts), bool> = true
>
void iterate_over_functions(const std::tuple<Ts...>& t) {
// do nothing
}
template <
std::size_t I = 0,
typename... Ts,
std::enable_if_t<I < sizeof...(Ts), bool> = true
>
void iterate_over_functions(const std::tuple<Ts...>& t) {
call_function(std::get<I>(t));
iterate_over_functions<I + 1>(t);
}
private:
std::tuple<Params...> m_fs;
};
int main() {
Execute f(
std::make_tuple(
std::make_tuple(f0),
std::make_tuple(f1, 1),
std::make_tuple(f2, 1, 2),
std::make_tuple(f3, "Stack Overflow!", 2)
)
);
f.execute();
}
注意:我需要记住如何取消移动元组并使用
std::tuple
中的值作为参数调用函数。