【问题标题】:How to combine multiple variadic templated tuple classes into one class?如何将多个可变参数模板元组类组合成一个类?
【发布时间】:2019-04-30 17:09:35
【问题描述】:

我已将我的方法从 my original question 更改为模板化整个类并将其放置在可变参数元组中。我现在可以按照我希望创建的方式使用 getter 和 setter。但是,现在我正试图向前迈出一步,将各个控制器组合成一个控制器。

#ifndef CONTROLLER_HPP
#define CONTROLLER_HPP

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

template<typename...Classes>
class Controller
{
  public:
    Controller(Classes&...objects) : objects(objects...){}

    void setValues(int value)
    {
      std::apply([&](auto&...x) { (x.updateValue(value),...);}, objects);
    }

    void getValues(std::vector<int> &values)
    {
      std::apply([&](auto&...x) { (values.push_back(x.get()),...);}, objects);
    }
  private:
    std::tuple<Classes&...> objects;
};

#endif

有了这个,我可以做到以下几点:

classA A;
classB B;
classC C;
classD D;
classE E;
classF F;
classG G;

Controller controller1(A,B,C);
Controller controller2(D,E);
Controller controller3(F,G);

controller1.setValues(20);
controller2.setValues(13);
controlelr3.setValues(32);

但是,我想更进一步,像这样将两者结合起来:

Controller master(controller1,controller2,controller3);
master.setValues(40);

我看过at this post talking about joining variadic templates,但是我认为这会返回一个类型(?)而不是一个类。我还尝试创建两个重载类,但我认为我没有正确创建重载:

template<typename...Classes>
class Controller
{
  public:
    Controller(Classes&...objects) : objects(objects...){}

    void setValues(int value)
    {
      std::apply([&](auto&...x) { (x.updateValue(value),...);}, objects);
    }

    void getValues(std::vector<int> &values)
    {
      std::apply([&](auto&...x) { (values.push_back(x.get()),...);}, objects);
    }
  private:
    std::tuple<Classes&...> objects;
};

template<Controller<typename ... > class Controllers, typename ...Classes>
class Controller<Controllers<Classes&...classes>...>
{
  // create a new controller that takes all the combined classes
};

如何将任意数量的模板化可变参数模板类组合成一个类?我确实有能力使用 C++17。

【问题讨论】:

  • 用重载的operator() 创建一个函子,一个负责处理或Controller&lt;...&gt;s,一个负责处理其他任何事情。然后你可以将它传递给 std::apply 而不是你当前的 lambda。
  • @super 你想举个例子吗?
  • @super 这将要求子控制器的生命周期无实际原因超过主控制器。

标签: c++ templates c++17 variadic-templates


【解决方案1】:
template<typename...Classes>
class Controller
{
  Controller( std::tuple<Classes&...> tup ):objects(tup) {}
public:
  template<class...Rhs>
  Controller<Classes..., Rhs...> operator+( Controller<Rhs...> rhs ) const {
    return std::tuple_cat( objects, rhs.objects );
  }

...

给我们:

Controller master = controller1+controller2+controller3;
master.setValues(40);

【讨论】:

  • 我想这是一种方法,但是它需要用户使用+,而不是在类内部构造它。
  • @Sailanarmo 是的,如果您觉得将操作的代数性质暴露给消费者是一件坏事。
  • 不错的方法,几乎​​没有额外的样板。
  • @Sailanarmo 否:super 的实现(我可以从他的简短评论中理解)有问题。我可以列出您通过建筑传递它们的计划的错误;它不反映操作的代数性质(例如,操作分布),它需要一大堆额外的样板,并且它将“控制这些实例”与“控制这些控制器控制的实例”(即super的解决方案有我指出的错误的原因)。这就是图灵焦油坑,一切都是等价的,但有些东西形状更好。
  • @Sailanarmo 您的运算是连接的事实使它具有代数性,并且用代数表达代数运算会导致简单、清晰、优雅的代码。而且由于您的状态是引用元组,因此编译器的结果也非常有效且容易忽略中间结果。具有您要求的语法的解决方案将需要更多丑陋的样板。
猜你喜欢
  • 1970-01-01
  • 2021-12-14
  • 2015-03-12
  • 1970-01-01
  • 2022-01-05
  • 1970-01-01
  • 1970-01-01
  • 2013-03-03
  • 2022-08-13
相关资源
最近更新 更多