【问题标题】:Create a Recursive Function for a Tuple in a Template为模板中的元组创建递归函数
【发布时间】:2018-05-06 23:20:12
【问题描述】:

我正在尝试在工厂模式中创建一个递归函数,该函数通过可变数量的元素迭代 std::tuple。我已经像这样创建了我的 ConsoleShapeFactory:

template<size_t N, typename...Shapes>
class ConsoleShapeFactory : public ShapeFactory {
private:
  //Functions for shape creation
  void MakePoint(std::shared_ptr<CAD::Point>);

  //Recursive Router for shapes
  void MakeShapeRouter(std::tuple<Shapes...>&);

public:

  //Create Object Function
  std::tuple<Shapes...> CreateShapeTuple();


};

CreateShapeTuple 方法定义如下:

template<size_t N, typename...Shapes>
std::tuple<Shapes...> ConsoleShapeFactory<N, Shapes...>::CreateShapeTuple() {

  //Define return tuple and get size
  std::tuple<Shapes...> returnTuple;

  MakeShapeRouter(returnTuple);

  return returnTuple;

}

而递归的 MakeShapeRouter 函数看起来像这样(这不起作用):

template<size_t N, typename...Shapes>
void ConsoleShapeFactory<N, Shapes...>::MakeShapeRouter(std::tuple<Shapes...>& tupShapes) {
  MakePoint(std::tuple::get<N-1>(tupShapes));

  ConsoleShapeFactory<N-1, Shapes...>::MakeShapeRouter(tupShapes); //This doesn't work
} 

我在基本情况下的尝试如下所示:

template<size_t N, typename...Shapes>
void ConsoleShapeFactory<1, Shapes...>::MakeShapeRouter(std::tuple<Shapes...>& tupShapes) {

  MakePoint(std::tuple::get<0>(tupShapes));
}

我不确定如何设置我的 MakeShapeRouter 函数,以便可以递归调用它并以基本情况退出。我正在尝试做的事情是否可能?

*编辑

如果有帮助,我想在我的 main 方法中调用该函数:

int main()
{
  auto factory = ConsoleShapeFactory<2, std::shared_ptr<CAD::Point>, std::shared_ptr<CAD::Point>>();

  std::tuple<std::shared_ptr<CAD::Point>, std::shared_ptr<CAD::Point>> shapeTuple = factory.CreateShapeTuple();

  return 0;
}

*编辑 2

MakePoint 实现:

template<typename...Shapes>
void ConsoleShapeFactory<Shapes...>::MakePoint(std::shared_ptr<CAD::Point>& sp_point) {

  double x, y;

  x = 3;
  y = 4;

  sp_point = std::make_shared<CAD::Point>(x,y);
};

【问题讨论】:

    标签: c++ recursion variadic-templates


    【解决方案1】:

    你的方法不是static,所以你需要一个实例来调用它们。

    ConsoleShapeFactory<N-1, Shapes...>::MakeShapeRouter(tupShapes); //This doesn't work
    

    应该是

    ConsoleShapeFactory<N-1, Shapes...>{}.MakeShapeRouter(tupShapes);
    

    但是由于std::index_sequence,事情可以在没有递归的情况下完成,例如:

    template<typename... Shapes>
    class ConsoleShapeFactory : public ShapeFactory {
    private:
      //Functions for shape creation
      void MakePoint(std::shared_ptr<CAD::Point>);
    
      template <std::size_t ... Is>
      std::tuple<Shapes...> CreateShapeTuple(std::index_sequence<Is...>)
      {
          std::tuple<Shapes...> res;
    
          (MakePoint(std::get<Is>(res)), ...); // C++17
    
          /* or C++11
          const int dummy[] = {0, (MakePoint(std::get<Is>(res)), 0)...};
          static_cast<void>(dummy); // Avoid warning for unused variable.
          */
    
          return res;
      }
    
    public:
      //Create Object Function
      std::tuple<Shapes...> CreateShapeTuple() {
           return CreateShapeTuple(std::index_sequence_for<Shapes...>());
      }
    };
    

    【讨论】:

    • 所以我为 C++11 实现了你的 std::index_sequence 解决方案,它几乎可以工作了。函数 CreateShapeTuple 现在迭代地调用 MakePoint 函数,但现在我在 CreateShapeTuple(std::index_sequence&lt;Is...&gt; 类末尾 static_cast&lt;void&gt;(dummy); 之后遇到运行时错误。退出函数似乎有问题(我尝试使用 void 返回类型并只是改变 res,但仍然有运行时异常)。关于如何诊断的任何想法?
    • 您的示例实现(我复制的)很奇怪,您的元组只有 nullptr shared_ptr.MakePoint 不会更改内容,因为它按值而不是按引用。提供MakePoint 实现可能会有所帮助。
    • 我已将我的 MakePoint 实现添加到我的问题中,并且我确实将其更改为引用 shared_ptr<:point>。该程序在 MakePoint() 中没有崩溃。事实上,即使我让 MakePoint() 什么都不做,程序仍然会出现运行时错误。由于某种原因,C++ 无法退出 CreateShapeTuple 函数。
    • @EliSquared:按预期工作Here
    • 好的,所以我能够从您的示例开始使其工作并慢慢将其转换为分离的类。事实上,我什至能够删除 #if 0 (MakePoint(std::get&lt;Is&gt;(res)), ...); // C++17 #else and #endif 语句,所以我只需要 const int dummy[] = { 0, (MakeShape(std::get&lt;Is&gt;(res)), 0)... };static_cast&lt;void&gt;(dummy); 行。我不确定是什么导致了崩溃,但它不再发生了。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-18
    • 1970-01-01
    • 2017-02-13
    • 1970-01-01
    • 1970-01-01
    • 2012-05-17
    • 1970-01-01
    相关资源
    最近更新 更多