C++17:传递多个可调用对象及其参数

0mkxixxg  于 2024-01-09  发布在  其他
关注(0)|答案(3)|浏览(134)

我想写一个函数(C++17,如果这很重要的话),它接受多个可调用对象及其参数,并在循环中执行它们。我还想避免任何中间数据复制。
范例:
假设我们有三个函数f0f1f2,它们需要不同数量的输入参数

  1. void f0() {
  2. // Implementation of f0
  3. }
  4. void f1(int a) {
  5. // Implementation of f1
  6. }
  7. void f2(int a, int b) {
  8. // Implementation of f2
  9. }

字符串
我正在寻找一种方法,将上述所有函数与示例输入参数一起传递到类或另一个函数(比如Execute)。示例接口如下所示:

  1. int main() {
  2. // If Execute is a class
  3. Execute exec({f0}, {f1, 4}, {f2, 1, 2});
  4. // The result of the command above is a sequence of calls
  5. // 1. f0()
  6. // 2. f1(4)
  7. // 3. f2(1, 2)
  8. }


我希望避免任何中间数据复制。
那么我的问题是,如何才能做到这一点呢?

klh5stk1

klh5stk11#

为了完整起见,这里有一个零努力的解决方案。

  1. template <typename... T>
  2. void execute (T&&... t)
  3. {
  4. (t(),...);
  5. }
  6. int main()
  7. {
  8. int a = 42, b = 0;
  9. // this
  10. execute([&](){f0();}, [&](){f1(a);}, [&](){f2(a,b);});
  11. // or this
  12. execute(std::bind(f0), std::bind(f1, a), std::bind(f2, a, b));
  13. }

字符串

展开查看全部
a0x5cqrl

a0x5cqrl2#

我提出了以下解决方案。谁能告诉我这是否有效?

  1. #include <tuple>
  2. #include <iostream>
  3. void f0() {
  4. std::cout << "f0:" << std::endl;
  5. }
  6. void f1(int a) {
  7. std::cout << "f1: " << a << std::endl;
  8. }
  9. void f2(int a, int b) {
  10. std::cout << "f2: " << a << "," << b << std::endl;
  11. }
  12. template <typename... Tuples>
  13. void execute(Tuples &&... tuples) {
  14. (std::apply(std::get<0>(tuples), std::get<1>(tuples)), ...);
  15. }
  16. int main() {
  17. execute(std::forward_as_tuple(f0, std::forward_as_tuple()),
  18. std::forward_as_tuple(f1, std::forward_as_tuple(1)),
  19. std::forward_as_tuple(f2, std::forward_as_tuple(3, 4)));
  20. }

字符串

展开查看全部
ars1skjm

ars1skjm3#

这里有一个工作解决方案,它使用std::tuple实现了一个模板化的类,它模仿了您的建议。

  1. #include <iostream>
  2. #include <utility>
  3. #include <vector>
  4. #include <tuple>
  5. void f0() {
  6. std::cout << "f0\n";
  7. }
  8. void f1(int a) {
  9. std::cout << "f1: " << a << '\n';
  10. }
  11. void f2(int a, int b) {
  12. std::cout << "f2: " << a + b << '\n';
  13. }
  14. void f3(const std::string a, int b) {
  15. std::cout << "f3: " << a << " ** " << b << '\n';
  16. }
  17. template <typename T1, typename... Ts>
  18. std::tuple<Ts...> unshift_tuple(const std::tuple<T1, Ts...>& tuple)
  19. noexcept
  20. {
  21. return std::apply(
  22. [](auto&&, const auto&... args) {
  23. return std::tie(args...);
  24. },
  25. tuple
  26. );
  27. }
  28. template <typename Callable, typename... Params>
  29. void call(const std::tuple<Callable, Params...>& t) noexcept {
  30. const auto f = std::get<0>(t);
  31. const auto args = unshift_tuple(t);
  32. std::apply(f, args);
  33. }
  34. template <typename... Params>
  35. class Execute {
  36. public:
  37. Execute(std::tuple<Params...>&& t) : m_fs(t) { }
  38. void execute() noexcept {
  39. iterate_over_functions<0>(m_fs);
  40. }
  41. private:
  42. template <std::size_t I, typename... Ts>
  43. void iterate_over_functions(const std::tuple<Ts...>& t) noexcept {
  44. if constexpr (I < sizeof...(Ts)) {
  45. call(std::get<I>(t));
  46. iterate_over_functions<I + 1>(t);
  47. }
  48. }
  49. private:
  50. std::tuple<Params...> m_fs;
  51. };
  52. int main() {
  53. Execute f(
  54. std::make_tuple(
  55. std::make_tuple(f0),
  56. std::make_tuple(f1, 1),
  57. std::make_tuple(f2, 1, 2),
  58. std::make_tuple(f3, "Stack Overflow!", 2)
  59. )
  60. );
  61. f.execute();
  62. }

字符串
注意:我需要remember如何取消元组的移位,并使用std::apply调用一个函数,该函数使用std::tuple中的值作为参数。

展开查看全部

相关问题