将int数组转换为可变进值模板
Convert int array to variadic template
假设我有一个像int arr[N]
这样的int数组,并且假设arr[i]
来自一个很小的域(例如1-10)。假设我还有一个可变的模板化类,它有一个公共接口(抽象类)
template <int... A>
class FooImpl : public Foo
{
}
问题是我如何实现一个函数:
Foo* getFoo(int arr[N]);
或者更好:
Foo* getFoo(int* pint, int size);
这将返回FooImpl
与模板参数对应我的数组?例如,对于arr = {4,2,6,1}
,我将得到FooImpl<4,2,6,1>
我找到了问题的答案。诀窍是使用结构变量模板,而不是我最初尝试的函数变量模板。我使用_getFoo_impl结构体和func函数逐个元素构建。
让我们假设元素的范围为[1-5],大小为<= 4,然后代码如下所示:
class Foo
{
};
template <int...A>
class FooImpl : Foo {
};
template<int...As>
struct _getFoo_impl
{
static Foo* func(int *arr, int sz)
{
if (sz == 0)
return new FooImpl<As...>;
switch (*arr)
{
case 1: return _getFoo_impl<As..., 1>::func(arr + 1, sz - 1);
case 2: return _getFoo_impl<As..., 2>::func(arr + 1, sz - 1);
case 3: return _getFoo_impl<As..., 3>::func(arr + 1, sz - 1);
case 4: return _getFoo_impl<As..., 4>::func(arr + 1, sz - 1);
case 5: return _getFoo_impl<As..., 5>::func(arr + 1, sz - 1);
default: throw "element out of range";
}
}
};
template<int A1, int A2, int A3, int A4, int A5>
struct _getFoo_impl<A1, A2, A3, A4, A5>
{
static Foo* func(int*, int sz) {
std::terminate();
}
};
Foo* getFoo(int *arr, int size)
{
return _getFoo_impl<>::func(arr, size);
}
不能从类模板中存储或生成类型
template <int... N>
class FooImpl;
使用运行时整数作为模板参数。但是,如果以下内容也适合您的实际问题,则可以存储并查找指向函数的指针
template <int... N>
R FooFun(A...);
给出运行时整数作为模板参数,假设所有模板参数的函数签名R(A...)
相同。注意,A...
不是这里的模板参数包;它只是您自己的具体函数参数类型的占位符,例如FooFun(int, int)
。
在我看来,这个公式确实适合你的问题,因为你有一个没有输入参数的工厂函数,返回一个指向对象FooImpl<N...>
的指针,总是被视为Foo*
,所以在你的情况下,FooFun
看起来像
template <int... N>
Foo* FooFun();
这种转换的一般解决方案是基于指针到函数的查找表,并在我之前的问题的答案中给出,将非constexpr整数值应用于非类型模板参数(顺便说一下,现在工作非常顺利,我对此非常满意-我的实际实现在这里)。
您的情况的不同之处在于您需要一个多维查找表。我建议你首先定义一个函数"dispatcher",只有一个整型模板参数
template <int OFFSET>
R FooDispatch(A...);
表示多维表中的线性偏移量。在这种情况下,前面的解决方案直接应用于FooDispatch
。然后,您必须在编译时将OFFSET
转换为一组多维索引N...
。为此,您还需要在编译时知道表的维度,或者更好的是它的步长。在推导出参数N...
之后,FooDispatch
现在可以调用FooFun<N...>(...)
。
更准确地说,这种偏移量到索引转换的逻辑与Matlab的函数ind2sub完全相同,只是它是一个编译时操作。这将需要一些工作,所以如果你喜欢这种方法,并在这最后一步需要帮助,我很乐意协助。在这种情况下,我认为你最好发布一个新的问题,并适当地制定子问题。
以上所有内容都意味着维数在编译时也是已知的,因此最终的形式为
的函数Foo* getFoo(int arr[N]);
可以作为接口,但是
Foo* getFoo(int* pint, int size);
没有多大意义;您只能在后一种情况下进行运行时检查,如果维度不一致,可能会抛出异常。
最后,请注意,在运行时使用超出范围的索引将产生与在普通C数组中使用超出范围的索引相同的效果。
- 按字符值访问int数组
- 将 int 数组转换为 std::vector<int*>
- C++,在int数组中输入字符串或字符会输出0,而不是ascii或error
- 整数区间(或 int 数组)中每个数字的出现次数
- Int 数组到C++容器
- C++ 未初始化的本地(非全局)int 数组中的元素类型到底是什么?
- 如何检测将文本文件读入 int 数组的新行
- C++快速将 int 数组内容转储到文本文件中
- <string> 如何在使用 SWIG 时将 int 数组和 List 作为参数传递给 C# C++
- 如何制作不允许重复值的 C++ int 数组循环?
- 如何将逗号分隔的文件读取为 2D int 数组?
- int 数组,但索引是字符?
- 使用可变参数函数将整数和/或整数数组放入单个 int 数组中
- 将 int 数组转换为带有小数C++的双精度数组
- 将双精度值分配给 int 数组时的类型转换
- 已编辑 我如何将其拆分为 char 和 int 数组
- 从 C++ 中的 int ** 数组访问元素
- C++程序无法分配 int 数组?
- 我正在编写一个代码来将 int 数组存储在文件中,然后用 c++ 检索它,但是检索第一项是假值,我该如何解决这个问题?
- 如何通过头文件中的函数初始化 const int 数组?