Распаковать Variadic Templated Class, когда конструктор берет себя? - PullRequest
0 голосов
/ 29 апреля 2019

Это продолжение моего последнего поста . Я успешно смог установить и получить значения классов. Тем не менее, сейчас я пытаюсь сделать этот шаг дальше и сделать так, чтобы конструктор взял себя в качестве параметра. Однако я не уверен, как правильно распаковать его.

Я пробовал:

#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 << " ";
}

Затем будут установлены все значения всех классов и получены значения всех классов в контроллерах.

1 Ответ

0 голосов
/ 12 мая 2019

А как насчет преобразования 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;
 }
...