【问题标题】:Traversing variadic templates遍历可变参数模板
【发布时间】:2018-04-09 05:31:50
【问题描述】:

我有兴趣打印出可变数量的模板化参数。 到目前为止,我已经实现了下面的代码,但遇到了以下编译时错误

./include/AView.hpp:46:5: error: call to member function 'indexcalc2' is ambiguous
    indexcalc2<Strs...>();
    ^~~~~~~~~~~~~~~~~~~
./include/AView.hpp:46:5: note: in instantiation of function template specialization 'myView<double, 2, 1, 2, 3, 4,
      5>::indexcalc2<4, 5>' requested here
./include/AView.hpp:46:5: note: in instantiation of function template specialization 'myView<double, 2, 1, 2, 3, 4,
      5>::indexcalc2<3, 4, 5>' requested here
./include/AView.hpp:52:5: note: in instantiation of function template specialization 'myView<double, 2, 1, 2, 3, 4,
      5>::indexcalc2<2, 3, 4, 5>' requested here
    indexcalc2<Strides...>();
    ^
main.cpp:23:9: note: in instantiation of member function 'myView<double, 2, 1, 2, 3, 4, 5>::indexcalc' requested here
      A.indexcalc();
        ^
./include/AView.hpp:36:8: note: candidate function [with Str0 = 5]
  void indexcalc2() const
       ^
./include/AView.hpp:43:8: note: candidate function [with Str0 = 5, Strs = <>]
  void indexcalc2() const

这里的想法是创建一个带有 get 方法的布局结构,该方法将输出第一个模板参数跨度。然后,我使用 indexcalc 方法创建了第二个名为 view 的结构,该方法将生成布局,打印步幅,并通过调用 indexcalc2 递归地删除模板参数。

不幸的是,我没有完全正确的实现,想知道是否有建议。

template<size_t... Strides>
struct layout
{
  static size_t get(size_t idx0) {return idx0;};
};

template<size_t stride0, size_t... Strides>
struct layout<stride0, Strides...> : layout<Strides...>
{

  static size_t get()
  {
    std::cout<<"Stride is : "<<stride0<<std::endl;
    return stride0;
  }
};


template<typename T, size_t DIM,size_t Stride0,  size_t... Strides>
struct myView
{
  myView() {};

  template<size_t Str0>
  void indexcalc2() const
  {
    std::cout<<layout<Str0>::get()<<std::endl;
    std::cout<<"End"<<std::endl;
  }

  template<size_t Str0, size_t... Strs>
  void indexcalc2() const
  {
    std::cout<<layout<Str0,Strs...>::get()<<std::endl;
    indexcalc2<Strs...>();
  }

  void indexcalc() const
  {
    std::cout<<layout<Stride0, Strides...>::get()<<std::endl;
    indexcalc2<Strides...>();
  }

};


int main()
{
struct myView<double,2,1,2,3,4,5> A;
A.indexcalc();

return 0;
}

【问题讨论】:

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


    【解决方案1】:

    这里有多个问题:

      template<size_t Str0> void indexcalc2() const;
      template<size_t Str0, size_t... Strs> void indexcalc2() const;
    

    如果Strs 不包含任何元素,将产生相同的实例。所以你在这里有一个模棱两可的实例,编译器已经抱怨了:

    ./include/AView.hpp:46:5: error: call to member function 'indexcalc2' is ambiguous
    indexcalc2<Strs...>();
    

    因此,展开参数集的想法总是有一个空的特化,例如:

      template<> void indexcalc2() const;
    

    让来自

    的电话
     indexcalc2<Strs...>();
    

    如果Strs 为空,则转到该专业化。

    但是在这之后你会遇到下一个麻烦:

    模板的特殊化不能在类范围内完成。所以你必须在外面专攻:

    template<> void myView::indexcalc2<>() const;
    

    但是您的myView 也是一个模板,如果没有完全专门化类参数,则不允许专门化您的方法!

    如果你使用 c++17,你可以简单地使用 constexpr if 来解决所有这些问题,但是在 c++11 中你必须使用一个封装类。

    您的带有模板化方法的模板化类很复杂,无法在此处简单地为您编写一个完整的解决方案。

    【讨论】:

    • 谢谢,您对替代方法有什么建议吗?
    • @user2785954:如果您觉得答案有帮助,您应该点赞而不是评论。如果答案是正确的,你应该接受它,以便其他人看到答案也对他们有帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-06
    • 2019-06-06
    • 2017-04-02
    • 2016-12-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多