1

Say I have three classes, ClassA, ClassB, and ClassC. And all three of these classes have a function called updateValue(int). And then I have controller class called, Controller. Who's constructor is templated like the following:

class Controller
{
  public:
    template <class...Classes>
    Controller(Classes & ...classes); // maybe initialize a tuple?

    void setValues(int val)
    {
      // unpack whatever data structure and call each classes updateValue(int)
    }
  private:
    std::tuple<Classes...classes> packedClasses; // Not sure if this is good idea? This will not compile
};

As you can see, I want to be able to take the classes from some data structure, and call their functions. For example, in main I would have:

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

  Controller controller1(A,B);
  Controller controller2(A,C);
  Controller controller3(B,C);
  Controller controller4(A,B,C);

  controller4.setValues(20);

}

Each class has their own way of updating a value, for example ClassA has setValue(int), ClassB has setInt(int), and ClassC has updateNumber(int). My plan is to write the function updateValue into each of these classes that will call their setter functions. However, I am not sure how to achieve what it is I am trying to do. How can I unpack all of the classes and call their function updateValue(int)?

Sailanarmo
  • 1,139
  • 15
  • 41
  • Can you have template class (`template class Controller;`)? – Jarod42 Apr 25 '19 at 16:43
  • Else you need erasure type... (`std::function` does the job for your example). – Jarod42 Apr 25 '19 at 16:45
  • `std::tuple packedClasses;` should be `std::tuple packedClasses;`. Using that you can use the dupe target to call a function on each member of the tuple. – NathanOliver Apr 25 '19 at 16:46
  • Is the idea that controller class manages the lifetime of the classes passed in, or do they live elsewhere and the controller just reference them? – super Apr 25 '19 at 16:49
  • I reopened as I didn't see the class wasn't a template. If you can make it one then you can use this: https://stackoverflow.com/questions/16387354/template-tuple-calling-a-function-on-each-element – NathanOliver Apr 25 '19 at 16:49
  • @Jarod42 yes I can do that. That will be fine. – Sailanarmo Apr 25 '19 at 16:49
  • @super just a reference to them. They will not manage the lifetime. – Sailanarmo Apr 25 '19 at 16:50
  • @NathanOliver, how would that apply with calling the classes functions though? Generally, when you call a function belonging to another class, you have to do something like `&A::func()` don't you? – Sailanarmo Apr 25 '19 at 16:59
  • You use a lambda that takes the object and calls the class member function on it. – NathanOliver Apr 25 '19 at 17:00

1 Answers1

2

From your current interface, you might do something like:

class Controller
{
 public:
    template <class...Classes>
    Controller(Classes&... classes)
    {
        mF = [&](int val) { (classes.updateValue(val), ...); }; // Fold expression from C++17
    }

    void setValues(int val)
    {
        mF(val);
    }
    private:
        std::function<void(int)> mF;
    };
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • That is awesome. How would this work if you were trying to get their values and push them back into a vector? – Sailanarmo Apr 25 '19 at 17:19