variadic templates与类中相同数量的函数参数

Dik*_*rAz 11 c++ templates variadic-templates c++11

如何定义方法签名,以便它接受与variadic模板类定义相同数量的参数?例如,如何定义Array类:

template<typename T, int... shape>
class Array
{
public:
    T& operator () (???);
};
Run Code Online (Sandbox Code Playgroud)

所以你可以像这样调用它:

Array<int, 3, 4, 5> a;
a(1, 2, 3) = 2;
Run Code Online (Sandbox Code Playgroud)

Yak*_*ont 14

template<class T, int...Shape>
class Array {
  template<int>using index_t=int; // can change this
public:
  T& operator()(index_t<Shape>... is);
};
Run Code Online (Sandbox Code Playgroud)

要么:

template<class T, int...Shape>
class Array {
public:
  T& operator()(decltype(Shape)... is);
};
Run Code Online (Sandbox Code Playgroud)

要么:

template<class T, int...Shape>
class Array {
public:
  T& operator()(decltype(Shape, int())... is);
};
Run Code Online (Sandbox Code Playgroud)

如果您希望能够将参数类型更改为不同Shape.

我发现decltype比触摸更难理解触摸using,特别是如果你想改变参数的类型而不是int.

另一种方法:

template<class T, int...Shape>
class Array {
public:
  template<class...Args,class=typename std::enable_if<sizeof...(Args)==sizeof...(Shape)>::type>
  T& operator()(Args&&... is);
};
Run Code Online (Sandbox Code Playgroud)

它使用SFINAE.但是,它并不强制使用Args整数类型.如果我们想要的话,我们可以添加另一个子句(比如说所有的Args都可以转换int).

另一种方法是让你operator()采取一系列价值观,比如std::array<sizeof...(Shape), int>.来电者必须:

Array<double, 3,2,1> arr;
arr({0,0,0});
Run Code Online (Sandbox Code Playgroud)

使用一组{}s.

最后的方法是:

template<class T, int...Shape>
class Array {
public:
  template<class...Args>
  auto operator()(Args&&... is) {
    static_assert( sizeof...(Args)==sizeof...(Shapes), "wrong number of array indexes" );
  }
};
Run Code Online (Sandbox Code Playgroud)

我们接受任何东西的地方,如果参数数量错误,就会产生错误.这会产生非常干净的错误,但不能正确执行SFINAE运算符重载.

我建议使用标签调度,但是我没有办法让它比SFINAE解决方案更清晰,除了另一方面,还有额外的decltype,全部的或更好的错误消息static_assert.


Die*_*ühl 9

我假设你希望你的参数都是相同的类型,可能使用整数类型(我只会使用int).一种简单的方法是利用您已有的参数包:

template <int>
struct shape_helper { typedef int type; };

template <typename T, int... Shape>
class Array
{
public:
    T& operator()(typename shape_helper<Shape>::type...);
}; 
Run Code Online (Sandbox Code Playgroud)