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

0mkxixxg  于 8个月前  发布在  其他
关注(0)|答案(3)|浏览(99)

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

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


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

klh5stk1

klh5stk11#

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

template <typename... T> 
void execute (T&&... t)
{
    (t(),...);
}

int main()
{
    int a = 42, b = 0;
    // this
    execute([&](){f0();}, [&](){f1(a);}, [&](){f2(a,b);});
    // or this
    execute(std::bind(f0), std::bind(f1, a), std::bind(f2, a, b));
}

字符串

a0x5cqrl

a0x5cqrl2#

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

#include <tuple>
#include <iostream>

void f0() {
  std::cout << "f0:" << std::endl;
}

void f1(int a) {
  std::cout << "f1: " << a << std::endl;
}

void f2(int a, int b) {
  std::cout << "f2: " << a << "," << b << std::endl;
}

template <typename... Tuples>
void execute(Tuples &&... tuples) {
  (std::apply(std::get<0>(tuples), std::get<1>(tuples)), ...);
}

int main() {
  execute(std::forward_as_tuple(f0, std::forward_as_tuple()),
          std::forward_as_tuple(f1, std::forward_as_tuple(1)),
          std::forward_as_tuple(f2, std::forward_as_tuple(3, 4)));
}

字符串

ars1skjm

ars1skjm3#

这里有一个工作解决方案,它使用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)
noexcept
{
    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) noexcept {
    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 <std::size_t I, typename... Ts>
    void iterate_over_functions(const std::tuple<Ts...>& t) noexcept {
        if constexpr (I < sizeof...(Ts)) {
            call(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();
}

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

相关问题