遍历可变参数模板

时间:2018-04-09 05:31:51

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

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

./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方法创建一个布局结构,该方法将输出第一个模板参数stride。然后我创建了一个名为view的第二个结构,它带有一个indexcalc方法,它可以生成一个布局,打印stride,并通过调用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;
}

1 个答案:

答案 0 :(得分:0)

这里有多个问题:

void overloaded_function(const std::string& param) {
  uniqueCall(std::forward<std::string&>(param));
}
void overloaded_function(std::string&& param) {
  uniqueCall(std::forward<std::string&&>(param));
}
void uniqueCall(T&& param) {
    someStuffHere
}
如果 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; 也是一个模板,如果没有完全专门化类参数,就不允许专门化你的方法!

如果你使用c ++ 17,你只需使用myView来解决所有问题,但在c ++ 11中你必须专注于封装类。

使用模板化方法的模板化课程很复杂,只需在此为您写下完整的解决方案。