std :: function类型的类成员内部的可变参数模板参数扩展

问题描述 投票:0回答:1

我有一个称为“菜单”的类,用于显示用户可以选择的选项。然后,用户选择一个选项,然后处理该值。但是,我有一个不显示任何内容的子类,而是仅接收带有可变数量参数的std :: function。

签名看起来像

template<class FuncRetTy, class... FuncArgs>
class FunctionMenu : public Menu;

理想情况下,我想保存一个具有以下形式的类成员:

std::function<FuncRetTy(FuncArgs...)> m_function;

我还想从构造函数中自动推断出所有类型并保存FuncArgs...的值,这样,每次调用重写的“ run()”方法时,这些值就可以通过此函数运行。在run()内部,将调用m_function(/* FuncArgs values */)

欢迎提出任何想法。我正在将Visual Studio 2019与C ++ 17一起使用。

c++ templates lambda function-pointers variadic-templates
1个回答
0
投票

这是您想要的吗?

#include <functional>
#include <iostream>

template<class Ret, class... Args>
class FunctionMenu {
    std::function<Ret(Args...)> m_function;

  public:
    FunctionMenu(std::function<Ret(Args...)> f) : m_function(f) {}

    Ret run(Args... args) {
        return f(args...);
    }
};

template<class Ret, class... Args>
FunctionMenu(std::function<Ret(Args...)>)->FunctionMenu<Ret, Args...>;

int test(int i, double d) {
    std::cout << i << ' ' << d << '\n';
    return 0;
}

int main() {
    std::function m = test;

    FunctionMenu fm{m};
}

((由于它似乎不相关,所以我没有添加Menu基类)


0
投票

最简单的方法是使用std::bind存储参数。

#include <functional>

template <typename Ret>
class FunctionMenu {
 public:
  template <typename Ret, typename... Args>
  explicit FunctionMenu(std::function<Ret(Args...)> func, Args... args)
      : m_function{std::bind(func, std::move(args)...)} {}

  auto run() { return m_function(); }

 private:
  std::function<Ret()> m_function;
};

template <typename Ret, typename... Args>
FunctionMenu(std::function<Ret(Args...)>, Args...)->FunctionMenu<Ret>;

这样,参数存储在std::function内部。也可以将参数手动存储在std::tuple中,并在调用run()时解压缩它们。

#include <tuple>

template <typename Ret, typename... Args>
class FunctionMenu2 {
 public:
  template <typename Ret, typename... Args>
  explicit FunctionMenu2(std::function<Ret(Args...)> func, Args... args)
      : m_function{func}, m_args{std::move(args)...} {}

  auto run() { return std::apply(m_function, m_args); }

 private:
  std::function<Ret(Args...)> m_function;
  std::tuple<Args...> m_args;
};

template <typename Ret, typename... Args>
FunctionMenu2(std::function<Ret(Args...)>, Args...)
    ->FunctionMenu2<Ret, Args...>;

第二种方法使您可以更轻松地访问参数(如果需要)。这是如何使用两个类的方法:

int main() {
  std::function<int(float, int)> f = [](auto a, auto b) {
    std::cout << a << std::endl;
    std::cout << b << std::endl;
    return 0;
  };

  FunctionMenu menu(f, 1.f, 200);
  FunctionMenu2 menu2(f, 1.f, 200);

  std::cout << menu.run() << std::endl;
  std::cout << menu2.run() << std::endl;

  return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.