varadic模板中的函数参数数量与类中的相同

variadic templates same number of function arguments as in class

本文关键字:参数 函数 varadic 数数      更新时间:2023-10-16

如何定义方法签名,使其接受与可变模板类定义相同数量的参数例如如何定义Array类:

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

所以你可以这样称呼它:

Array<int, 3, 4, 5> a;
a(1, 2, 3) = 2;
template<class T, int...Shape>
class Array {
  template<int>using index_t=int; // can change this
public:
  T& operator()(index_t<Shape>... is);
};

或:

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

或:

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

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

我发现decltypeusing更难理解触摸,尤其是如果您想将参数类型更改为不同于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);
};

其使用SFINAE。然而,它并没有强制要求Args是整数类型。如果我们愿意的话,我们可以添加另一个子句(比如说,所有的Args都可以转换为int)。

还有一种方法是让operator()采用一组值,比如std::array<sizeof...(Shape), int>。来电者必须:

Array<double, 3,2,1> arr;
arr({0,0,0});

使用一组{}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" );
  }
};

如果我们接受任何东西,那么如果参数的数量不对,就会产生错误。这会生成非常干净的错误,但不会进行适当的SFINAE运算符重载。

我建议进行标记调度,但我看不出有什么方法可以让它比SFINAE解决方案干净得多,因为它有额外的decltype等等,或者比static_assert版本更好的错误消息。

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

template <int>
struct shape_helper { typedef int type; };
template <typename T, int... Shape>
class Array
{
public:
    T& operator()(typename shape_helper<Shape>::type...);
};