我可以创建一个函数来接受 N 个整数,其中 N 是模板参数吗?

问题描述 投票:0回答:1

我遇到一种情况,需要传入可变数量的整数(在编译时已知)。

我需要实现这样的目标:

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

不幸的是,我无法在我的环境中分配内存),所以我必须在堆栈上执行所有操作(并且不能只接受可以检查其大小的向量)。

我认为自己有两个选择。

  1. 使用编译时大小且基于初始化列表长度的对象
  2. 使用一些神奇的递归 C++ 参数包语法来允许可变数量的整数,但这超出了我的能力范围。

谢谢!

c++ templates syntactic-sugar
1个回答
0
投票

您当然可以创建一个可变参数模板并根据您的要求限制参数:

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 });
© www.soinside.com 2019 - 2024. All rights reserved.