我遇到一种情况,需要传入可变数量的整数(在编译时已知)。
我需要实现这样的目标:
template <unsigned N>
void myFunc(std::array<int, N> values)
{
// Do something useful with the values
}
我希望上面的代码能够工作,并且可以像这样方便地调用,而无需创建临时对象;
myFunc<4>({1, 2, 3, 4});
这确实有效,但问题是这也有效......
myFunc<4>({1, 2});
这当然会使其中两个值未初始化,而我和用户都不知道。
我相信这会起作用:
template <unsigned N>
void myFunc(std::vector<int> values)
{
assert(values.size() == N);
// Do something useful with the values
}
myFunc<4>({1, 2}); // Goes bang
myFunc<4>({1, 2, 3, 4}); // OK
不幸的是,我无法在我的环境中分配内存),所以我必须在堆栈上执行所有操作(并且不能只接受可以检查其大小的向量)。
我认为自己有两个选择。
谢谢!
您当然可以创建一个可变参数模板并根据您的要求限制参数:
template<size_t N, std::convertible_to<int>...Args>
requires (sizeof...(Args) == N)
void f(Args&&...args)
{
std::array<int, N> values{args...};
for (auto e : values)
{
std::cout << e << '\n';
}
}
...
f<4>(1, 2, 3, 4);
为什么要多次指定元素数量?只需使用 C++17 的功能进行 CTAD 并根据参数类型推断出函数的模板参数即可:
template<size_t N>
void f2(std::array<int, N> const& values)
{
for (auto e : values)
{
std::cout << e << '\n';
}
}
...
f2(std::array{ 1, 2, 3, 4 });
或者通过简单地使用
std::initializer_list<int>
作为函数参数来避免使用模板的必要性:
void f3(std::initializer_list<int> values)
{
for (auto e : values)
{
std::cout << e << '\n';
}
}
...
f3({ 1, 2, 3, 4 });