【问题标题】:Encapsulating arguments of variadic function in a class instance在类实例中封装可变参数函数的参数
【发布时间】:2020-05-29 16:44:45
【问题描述】:

这里有一些有漏洞的代码:

template<typename... Args>
class A 
{

  typedef function_type = void(*)(Args...);

  public:
  void set_args(Args&& ... args)
  {
      // something magic manages to encapsulate
      // args in instance of A
  }
  void apply_args(function_type function)
  {
      // something magic manages to "retrieve"
      // the encapsulated args
      function(std::forward<Args>(args)...);
  }

};

这有可能吗?

【问题讨论】:

    标签: c++ parameter-passing function-pointers variadic-functions


    【解决方案1】:

    您可以使用std::tuplestd::apply

    #include <iostream>
    #include <tuple>
    #include <functional>
    #include <string>
    
    template <typename... Ts>
    class A
    {
        private:
            std::function<void (Ts...)> f;
            std::tuple<Ts...> args;    
        public:
            template <typename F>
            A(F&& func, Ts&&... args)
                : f(std::forward<F>(func)),
                  args(std::make_tuple(std::forward<Ts>(args)...))
            {}
    
            void Invoke()
            {
                std::apply(f, args);
            }
    };
    
    template <typename F, typename... Args>
    A<Args...> Create(F&& f, Args&&... args)
    {
        return A<Args...>(std::forward<F>(f), std::forward<Args>(args)...);
    }
    
    int main()
    {
        auto helloWorld = Create([] (std::string a, std::string b) { std::cout << a << ", " << b; }, std::string("Hello"), std::string("World!"));
    
        helloWorld.Invoke();
    }
    

    【讨论】:

      【解决方案2】:

      您可以将模板参数存储在 std::tuple 类型的类数据成员中,并使用 std::apply 以便将存储的参数应用于提供的函数。

      所以,假设你有一个像这样的Action 类:

      template <typename... Args>
      class Action {
          std::tuple<Args...> args_;
      
      public:
          Action() = default;
          Action(Args&&... args)
              : args_(std::forward<Args>(args)...)
          {}
      
          void args(Args&&... args) {
              args_ = std::make_tuple<Args...>(std::forward<Args>(args)...);
          }
      
          template <typename F>
          void apply(F&& fun) {
              std::apply(std::forward<F&&>(fun), args_);
          }
      };
      

      您通过构造函数Action action(1, 2, 3); 或通过单独的函数action.set(3, 2, 1); 设置参数。

      那么你的 main 函数可以如下所示:

      int main() {
          Action action(1, 2);
      
          action.apply([](int a, int b) {
              std::cout << "a + b = " << (a + b) << std::endl;
          });
      
          return 0;
      }
      

      查看live example

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-20
        • 1970-01-01
        相关资源
        最近更新 更多