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

Oli*_*ker 0 c++ templates syntactic-sugar

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

我需要实现这样的目标:

template <unsigned N>
void myFunc(std::array<int, N> values)
{
    // Do something useful with the values
}
Run Code Online (Sandbox Code Playgroud)

我希望上面的代码能够工作,并且可以像这样方便地调用,而无需创建临时对象;

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
}
Run Code Online (Sandbox Code Playgroud)
myFunc<4>({1, 2}); // Goes bang
myFunc<4>({1, 2, 3, 4}); // OK
Run Code Online (Sandbox Code Playgroud)

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

我认为自己有两个选择。

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

fab*_*ian 7

std::array<int, 4> arr{ 0, 1};很好;未指定的元素只是零初始化。如果您不希望它起作用,那么这std::array不是适合您使用的正确类(或者更准确地说:您不能让它施加所需的限制)。

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

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);
Run Code Online (Sandbox Code Playgroud)

为什么要多次指定元素数量?只需使用 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 });
Run Code Online (Sandbox Code Playgroud)

或者通过简单地使用 as 函数参数来避免使用模板的必要性std::initializer_list<int>

void f3(std::initializer_list<int> values)
{
    for (auto e : values)
    {
        std::cout << e << '\n';
    }
}

...

f3({ 1, 2, 3, 4 });
Run Code Online (Sandbox Code Playgroud)