【问题标题】:Pass array of template size to function using an initializer list使用初始化列表将模板大小的数组传递给函数
【发布时间】:2020-04-23 15:09:14
【问题描述】:

我有一个模板函数,它以任意大小的std::array 作为参数。大致是这样的:

template <size_t n>
void foo(const std::array<int, n>& numbers) {
    for (const auto & number: numbers) {
        // ... do stuff ...
    }
}

我可以称之为例如像这样:

std::array<int, 2> ints = {4, 5};
foo(ints);

一切都很好。

不幸的是,我无法使用初始化列表直接调用该函数。这段代码:

foo({4, 5});

给我以下错误:

错误:没有匹配的成员函数调用“foo” 注意:候选模板被忽略:无法推断模板参数“n”

有没有办法让我的函数使用初始化列表或类似的东西工作?

【问题讨论】:

  • void foo(std::initializer_list&lt;int&gt; numbers) ?
  • 除此之外foo&lt;2&gt;({4, 5}); 也可以工作。是的,丑陋,但可能会更糟。
  • @Jarod42 那么我不能再传递已经存在的数组了,可以吗?
  • @ypnos 啊是的,这行得通……谢谢。但是,如果没有专门的模板,为什么这不起作用呢?

标签: c++ templates initializer-list


【解决方案1】:

{/*..*/}没有类型,因此除了std::initializer_list&lt;T&gt;和C数组T (&amp;a)[N]之外,不能在模板函数中推导出来。

所以你必须

  • 添加重载以处理 std::initializer_list&lt;int&gt; 或 C 数组。

    // span (C++20) has constructor from std::array :)
    void foo(const std::span<int>& numbers) {
        for (const auto & number: numbers) {
            // ... do stuff ...
        }
    }
    
    void foo(std::initializer_list<int> numbers) {
        foo(std::span{numbers.begin(), numbers.size()});
    }
    
  • 或提供非推导模板参数:foo&lt;2&gt;({4, 5});

  • 或将类型提供给{}(使用 C++17 的 CTAD 更容易):foo(std::array{4, 5});

【讨论】:

  • std::span 很棒,但请注意它是由 C++20 引入的(不要从答案中删除,以防万一有人想尝试代码示例)。
  • @ypnos:确实,我使用span 来避免重复代码。在以前的标准中,我们可能会使用带有 2 个迭代器或重新实现 span 的版本。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-19
  • 2016-02-25
  • 2021-03-06
  • 1970-01-01
  • 1970-01-01
  • 2020-02-03
  • 1970-01-01
相关资源
最近更新 更多