0

This is a follow up of my last post. I have successfully been able to set and get values of the classes. However, now I am trying to take this a step further and have the constructor take itself as the parameter. However, I am not sure how to properly unpack it.

I have tried:

#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

However, in this case, I get classes was not declared in this scope error when I try to pass it to the intial controller constructor. I have also tried the commented out template declaration, however Id on't think that is correct either. I have also tried Controller&...controllers(Classes&...)...) : (Controller(Classes&...classes));, but that doesn't work either.

I don't really know what to try next or if what I am asking is possible to do. Or maybe this is easier if I templatize the entire class. I was simply trying to avoid Controller<A,B> controller(A,B); and instead just create Controller controller(A,B). However, I understand if I have to do it the other way.

EDIT: I should clarify what I am trying to do:

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

This would then set all the values of all the classes and get the values of all the classes within the controllers.

max66
  • 65,235
  • 10
  • 71
  • 111
Sailanarmo
  • 1,139
  • 15
  • 41

1 Answers1

0

What about transform Controller in a class that can manage itself recursively?

Simplifying: what about adding updateValue() and get() in controller

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

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

?

Remain only to modify the toGet function to append a single value or a vector of values, according to the cases.

I mean... given a couple of overloaded append() methods as follows

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

you can write your constructor simply as follows

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

The following is a full compiling example

#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;
 }
max66
  • 65,235
  • 10
  • 71
  • 111