首页 > 解决方案 > 当构造函数自行解压可变参数模板类?

问题描述

这是我上一篇文章的后续。我已经成功地设置和获取类的值。但是,现在我试图更进一步,让构造函数将自己作为参数。但是,我不确定如何正确解压缩它。

我努力了:

#ifndef CONTROLLER_HPP
#define CONTROLLER_HPP

#include <functional>
#include <vector>
#include <iostream>

class Controller
{

  public:
    template <class...Classes>
    Controller(Classes & ...classes) 
    { 
      toSet = [&](int val){(classes.updateValue(val), ...); }; 
      toGet = [&](std::vector<int> &values)
      {
        int size[sizeof...(Classes)] = { (classes.get())...};
        for(const auto &e: size) values.push_back(e); 
      }; 
    }

    // TODO: Find out how to create one master group if more than one are created.
    //template <Controller&...Controllers, class...Classes>
    template <class...Classes>
    Controller(Controller& controllers(Classes&...classes)...) : Controller(classes&...c){};

    void setValues(int val)
    {
      toSet(val);
    }

    std::vector<int> getValues()
    {
      std::vector<int> values;
      toGet(values);
      return values;
    }

  private:
    std::function<void(int)> toSet;
    std::function<void(std::vector<int>&)> toGet;
};

#endif

但是,在这种情况下,classes was not declared in this scope当我尝试将其传递给初始控制器构造函数时会出错。我也尝试过注释掉的模板声明,但是我认为这也不正确。我也尝试过Controller&...controllers(Classes&...)...) : (Controller(Classes&...classes));,但这也不起作用。

我真的不知道接下来要尝试什么,或者我所要求的是否可以做。或者,如果我将整个班级模板化,这可能会更容易。我只是想避免Controller<A,B> controller(A,B);,而只是创建Controller controller(A,B). 但是,我理解是否必须以其他方式进行。

编辑:我应该澄清我正在尝试做的事情:

int main()
{
  ClassA A;
  ClassB B;
  ClassC C;
  ClassD D;

  Controller controller1(A,B);
  Controller controller2(C,D);

  Controller master(controller1,controller2);

  master.setValues(20);

  std::vector<int> getVals = master.getValues();

  for(const auto& e: getVales) std::cout << e << " ";
}

然后,这将设置所有类的所有值并获取控制器内所有类的值。

标签: c++templatesc++17variadic-templatesfold-expression

解决方案


Controller可以递归管理自身的类中的转换怎么样?

简化:在控制器中添加updateValue()和怎么样get()

void updateValue (int v0)
 { setValues(v0); }

auto get () const
 { return getValues(); } 

?

根据情况,仅保留修改toGet函数以附加单个值或值向量。

我的意思是......给定几个重载append()方法如下

  static auto append (std::vector<int> & v0, std::vector<int> const & v1)
   { v0.insert(v0.end(), v1.cbegin(), v1.cend()); }

  static auto append (std::vector<int> & v0, int i)
   { v0.emplace_back(i); }

你可以简单地写你的构造函数如下

template <typename ... Cs>
Controller (Cs & ... cs)
   : toSet{[&](int v){ (cs.updateValue(v), ...); }},
     toGet{[&](auto & vs){ (append(vs, cs.get()), ...); }}
 { }

下面是一个完整的编译示例

#include <vector>
#include <iostream>
#include <functional>

template <std::size_t>
class ClassTmpl
 {
   private:
      int val;

   public:
      void updateValue (int v0)
       { val = v0; }

      int get () const
       { return val; }
 };

using ClassA = ClassTmpl<0u>;
using ClassB = ClassTmpl<1u>;
using ClassC = ClassTmpl<2u>;
using ClassD = ClassTmpl<3u>;

class Controller
 {
   private:
      std::function<void(int)> toSet;
      std::function<void(std::vector<int>&)> toGet;

      static auto append (std::vector<int> & v0, std::vector<int> const & v1)
       { v0.insert(v0.end(), v1.cbegin(), v1.cend()); }

      static auto append (std::vector<int> & v0, int i)
       { v0.emplace_back(i); }

   public:

      template <typename ... Cs>
      Controller (Cs & ... cs)
         : toSet{[&](int v){ (cs.updateValue(v), ...); }},
           toGet{[&](auto & vs){ (append(vs, cs.get()), ...); }}
       { }

      void setValues (int val)
       { toSet(val); }

      void updateValue (int v0)
       { setValues(v0); }

      auto getValues () const
       {
         std::vector<int> values;
         toGet(values);
         return values;
       }

      auto get () const
       { return getValues(); }
 };

int main ()
 {
   ClassA A;
   ClassB B;
   ClassC C;
   ClassD D;

   Controller controller1(A, B);
   Controller controller2(C, D);

   Controller master(controller1, controller2);

   master.setValues(20);

   std::vector<int> getVals = master.getValues();

   for ( auto const & e : getVals )
      std::cout << e << ' ';

   std::cout << std::endl;
 }

推荐阅读