我正在尝试编写一个表示张量Tensor
的类,并希望为2维张量提供语法tensor(i, j)
,为3维张量提供tensor (i, j, k)
等等
我想知道的是,是否有一种c ++类型的安全方式来声明这样的Tensor:operator()(int, int, ...)
接受任意数量的int
个参数(除了C样式和宏va_start va_end
)以及如何在函数内使用所述参数。
感谢您的时间。
答案 0 :(得分:2)
好吧,你总是可以使用普通的参数包;但强制编译失败,除非所有参数都是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);
}
那将编译,但不是:
bar(4, "foo");
或
bar(4, 2.3);
请注意,这不会编译:
unsigned baz=2;
bar(4, baz);
如果您需要接受无符号值,请相应地调整模板。
请注意,模板不需要使用转发引用,因为唯一可接受的参数是普通int
s。在模板功能中,您现在拥有一个多种多样的参数包,您可以使用与使用任何其他参数包相同的方式。
答案 1 :(得分:1)
同时接受unsigned int
和其他可转换为int
的类型,如果你可以接受上限(63,在下面的例子中)到整数参数的数量,我建议关注an example from W.F.。
所以你可以开发一个typer
template <typename T, std::size_t>
using typer = T;
和递归struct proOp
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() ()
{ }
};
继承proOp<int>
,Tensor
成为
struct Tensor : public proOp<int>
{
using proOp<int>::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
}
答案 2 :(得分:1)
另一种方法是使operator()
递归并在每次递归中使用第一个参数
// recursive case
template <typename ... Ts>
void operator() (int i0, Ts ... is)
{
// do something with i0
this->operator()(is...); // recursion
}
void operator() ()
{ }
以下是一个完整的工作示例
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
}
答案 3 :(得分:0)
有一种更简洁的方法来创建安全的可变参数函数,而不使用递归和std :: enable_if:
template <typename ...Ints>
void function(int first, Ints... other)
{
int values[] = {first, other...};
for(int value : values)
{
//your code
}
}
这种方式也是类型安全的,function(1, "2", 3)
无法编译。