C++ 可变函数

C++ 可变函数,c++,c++11,variadic-templates,variadic-functions,variadic,C++,C++11,Variadic Templates,Variadic Functions,Variadic,我试图编写一个类来表示一个张量张量,并希望为二维张量提供语法张量(I,j),为三维张量提供语法张量(I,j,k),以此类推 我想知道的是,是否有一种C++类型的安全方法来声明这样的张量:操作程序()(int,int,…)< /> >接受任何数量的 int 参数(除了C风格与宏 VAXSTATEVAXEDING/)以及如何在函数中使用这些参数。 谢谢您的时间。好吧,您可以随时使用普通的参数包;但强制编译失败,除非所有参数都是ints: #include <utility> #inclu

我试图编写一个类来表示一个张量
张量
,并希望为二维张量提供语法
张量(I,j)
,为三维张量提供语法
张量(I,j,k)
,以此类推

我想知道的是,是否有一种C++类型的安全方法来声明这样的<代码>张量:操作程序()(int,int,…)< /> >接受任何数量的<代码> int <代码>参数(除了C风格与宏<代码> VAXSTATEVAXEDING/<代码>)以及如何在函数中使用这些参数。


谢谢您的时间。

好吧,您可以随时使用普通的参数包;但强制编译失败,除非所有参数都是
int
s:

#include <utility>
#include <type_traits>


class foo {

public:

    template<typename ...Args,
         typename=std::void_t<std::enable_if_t
                      <std::is_same_v<Args, int>>...>>
    void operator()(Args ...args)
    {
    }
};

void bar()
{
    foo bar;

    bar(4, 2);
}

请注意,这不会编译:

unsigned baz=2;

bar(4, baz);
如果需要接受无符号的值,请相应地在模板上添加符号


请注意,模板不需要使用转发引用,因为唯一可接受的参数是纯
int
s。在模板函数中,您现在有了一个garden variety参数包,您可以使用与使用任何其他参数包相同的方法来使用它。

嗯,您可以始终使用普通参数包;但强制编译失败,除非所有参数都是
int
s:

#include <utility>
#include <type_traits>


class foo {

public:

    template<typename ...Args,
         typename=std::void_t<std::enable_if_t
                      <std::is_same_v<Args, int>>...>>
    void operator()(Args ...args)
    {
    }
};

void bar()
{
    foo bar;

    bar(4, 2);
}

请注意,这不会编译:

unsigned baz=2;

bar(4, baz);
如果需要接受无符号的值,请相应地在模板上添加符号


请注意,模板不需要使用转发引用,因为唯一可接受的参数是纯
int
s。在模板函数中,您现在有了一个garden variety参数包,您可以使用与使用任何其他参数包相同的方法。

也可以接受
无符号int
和其他可转换为
int
的类型,并且如果您可以接受上限(63,在下面的示例中)对于整数参数的个数,我建议如下

因此,您可以开发一个
打字机

template <typename T, std::size_t>
using typer = T;
继承自
proOp
Tensor
成为

struct Tensor : public proOp<int>
 {
   using proOp<int>::operator();
 };
结构张量:公共proOp { 使用proOp::operator(); }; 下面是一个完整的工作示例

#include <utility>

template <typename T, std::size_t>
using typer = T;

template <typename T, std::size_t N = 64U,
          typename = std::make_index_sequence<N>>
struct proOp;

template <typename T, std::size_t N, std::size_t... Is>
struct proOp<T, N, std::index_sequence<Is...>> : public proOp<T, N-1U>
 {
   using proOp<T, N-1U>::operator();

   void operator() (typer<T, Is>... ts)
    { }
 };

template <typename T>
struct proOp<T, 0U, std::index_sequence<>>
 {
   void operator() ()
    { }
 };

struct Tensor : public proOp<int>
 {
   using proOp<int>::operator();
 };

int main()
 {
   Tensor t;

   t(1, 2, 3);
   t(1, 2, 3, 4U); // accept also unsigned
   //t(1, "two"); // error
 }
struct Tensor
 {
   // recursive case
   template <typename ... Ts>
   void operator() (int i0, Ts ... is)
    {
      // do something with i0
      this->operator()(is...); // recursion
    }

   void operator() ()
    { }
 };

int main()
 {
   Tensor t;

   t(1, 2, 3);
   t(1, 2, 3, 4U); // accept also unsigned
   //t(1, "two"); // error
 }
#包括
样板
使用typer=T;
样板
结构工程;
样板
结构项目:公共项目
{
使用proOp::operator();
void运算符()(打字机…ts)
{ }
};
样板
结构工程
{
void运算符()()
{ }
};
结构张量:公共proOp
{
使用proOp::operator();
};
int main()
{
张量t;
t(1,2,3);
t(1,2,3,4U);//也接受未签名
//t(1,“2”);//错误
}

要同时接受
无符号int
和其他可转换为
int
的类型,并且如果您可以接受整数参数数量的上限(在下面的示例中为63),我建议遵循

因此,您可以开发一个
打字机

template <typename T, std::size_t>
using typer = T;
继承自
proOp
Tensor
成为

struct Tensor : public proOp<int>
 {
   using proOp<int>::operator();
 };
结构张量:公共proOp { 使用proOp::operator(); }; 下面是一个完整的工作示例

#include <utility>

template <typename T, std::size_t>
using typer = T;

template <typename T, std::size_t N = 64U,
          typename = std::make_index_sequence<N>>
struct proOp;

template <typename T, std::size_t N, std::size_t... Is>
struct proOp<T, N, std::index_sequence<Is...>> : public proOp<T, N-1U>
 {
   using proOp<T, N-1U>::operator();

   void operator() (typer<T, Is>... ts)
    { }
 };

template <typename T>
struct proOp<T, 0U, std::index_sequence<>>
 {
   void operator() ()
    { }
 };

struct Tensor : public proOp<int>
 {
   using proOp<int>::operator();
 };

int main()
 {
   Tensor t;

   t(1, 2, 3);
   t(1, 2, 3, 4U); // accept also unsigned
   //t(1, "two"); // error
 }
struct Tensor
 {
   // recursive case
   template <typename ... Ts>
   void operator() (int i0, Ts ... is)
    {
      // do something with i0
      this->operator()(is...); // recursion
    }

   void operator() ()
    { }
 };

int main()
 {
   Tensor t;

   t(1, 2, 3);
   t(1, 2, 3, 4U); // accept also unsigned
   //t(1, "two"); // error
 }
#包括
样板
使用typer=T;
样板
结构工程;
样板
结构项目:公共项目
{
使用proOp::operator();
void运算符()(打字机…ts)
{ }
};
样板
结构工程
{
void运算符()()
{ }
};
结构张量:公共proOp
{
使用proOp::operator();
};
int main()
{
张量t;
t(1,2,3);
t(1,2,3,4U);//也接受未签名
//t(1,“2”);//错误
}

另一种方法是使
运算符()递归,并在每次递归中使用第一个参数

   // recursive case
   template <typename ... Ts>
   void operator() (int i0, Ts ... is)
    {
      // do something with i0
      this->operator()(is...); // recursion
    }

   void operator() ()
    { }
//递归大小写
样板
void运算符()(int i0,Ts…is)
{
//用i0做点什么
this->operator()(is…;//递归
}
void运算符()()
{ }
下面是一个完整的工作示例

#include <utility>

template <typename T, std::size_t>
using typer = T;

template <typename T, std::size_t N = 64U,
          typename = std::make_index_sequence<N>>
struct proOp;

template <typename T, std::size_t N, std::size_t... Is>
struct proOp<T, N, std::index_sequence<Is...>> : public proOp<T, N-1U>
 {
   using proOp<T, N-1U>::operator();

   void operator() (typer<T, Is>... ts)
    { }
 };

template <typename T>
struct proOp<T, 0U, std::index_sequence<>>
 {
   void operator() ()
    { }
 };

struct Tensor : public proOp<int>
 {
   using proOp<int>::operator();
 };

int main()
 {
   Tensor t;

   t(1, 2, 3);
   t(1, 2, 3, 4U); // accept also unsigned
   //t(1, "two"); // error
 }
struct Tensor
 {
   // recursive case
   template <typename ... Ts>
   void operator() (int i0, Ts ... is)
    {
      // do something with i0
      this->operator()(is...); // recursion
    }

   void operator() ()
    { }
 };

int main()
 {
   Tensor t;

   t(1, 2, 3);
   t(1, 2, 3, 4U); // accept also unsigned
   //t(1, "two"); // error
 }
结构张量 { //递归案例 样板 void运算符()(int i0,Ts…is) { //用i0做点什么 this->operator()(is…;//递归 } void运算符()() { } }; int main() { 张量t; t(1,2,3); t(1,2,3,4U);//也接受未签名 //t(1,“2”);//错误 }
另一种方法是使
运算符()递归,并在每次递归中使用第一个参数

   // recursive case
   template <typename ... Ts>
   void operator() (int i0, Ts ... is)
    {
      // do something with i0
      this->operator()(is...); // recursion
    }

   void operator() ()
    { }
//递归大小写
样板
void运算符()(int i0,Ts…is)
{
//用i0做点什么
this->operator()(is…;//递归
}
void运算符()()
{ }
下面是一个完整的工作示例

#include <utility>

template <typename T, std::size_t>
using typer = T;

template <typename T, std::size_t N = 64U,
          typename = std::make_index_sequence<N>>
struct proOp;

template <typename T, std::size_t N, std::size_t... Is>
struct proOp<T, N, std::index_sequence<Is...>> : public proOp<T, N-1U>
 {
   using proOp<T, N-1U>::operator();

   void operator() (typer<T, Is>... ts)
    { }
 };

template <typename T>
struct proOp<T, 0U, std::index_sequence<>>
 {
   void operator() ()
    { }
 };

struct Tensor : public proOp<int>
 {
   using proOp<int>::operator();
 };

int main()
 {
   Tensor t;

   t(1, 2, 3);
   t(1, 2, 3, 4U); // accept also unsigned
   //t(1, "two"); // error
 }
struct Tensor
 {
   // recursive case
   template <typename ... Ts>
   void operator() (int i0, Ts ... is)
    {
      // do something with i0
      this->operator()(is...); // recursion
    }

   void operator() ()
    { }
 };

int main()
 {
   Tensor t;

   t(1, 2, 3);
   t(1, 2, 3, 4U); // accept also unsigned
   //t(1, "two"); // error
 }
结构张量 { //递归案例 样板 void运算符()(int i0,Ts…is) { //用i0做点什么 this->operator()(is…;//递归 } void运算符()() { } }; int main() { 张量t; t(1,2,3); t(1,2,3,4U);//也接受未签名 //t(1,“2”);//错误 }
有一种更简洁的方法可以创建安全的变量函数,而无需使用递归和std::enable\u,如果:

template <typename ...Ints>
void function(int first, Ints... other)
{
    int values[] = {first, other...};
    for(int value : values)
    {
        //your code
    }
}
模板
无效函数(整数优先,整数…其他)
{
int值[]={first,other…};
for(int值:值)
{
//你的代码
}
}

这种方法也是类型安全的,
函数(1,“2”,3)
不会编译。

有一种更简洁的方法来创建安全的变量函数,而不使用递归和std::enable\u,如果:

template <typename ...Ints>
void function(int first, Ints... other)
{
    int values[] = {first, other...};
    for(int value : values)
    {
        //your code
    }
}
模板
无效函数(整数优先,整数…其他)
{
int值[]={first,other…};
for(int值:值)
{
//你的代码
}
}

这种方式也是类型安全的,函数(1,2),3)/>代码不能编译。< /P>什么是可变模板参数包?可以使用C++变量模板,并将参数约束为特定类型(或者转换为特定类型)。不过,使用生成的参数包有点麻烦。张量维度是运行时属性还是编译时属性?听起来像是在重新发明

std::tuple
。如果你的是