如何推断 std::array 的大小?

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

在以下代码中:

template<size_t N>
int b(int q, const std::array<int, N>& types)
{
    int r = q;
    for (int t : types)
    {
        r = r + t;
    }
    return r;
}

int main()
{
    b<2>(9, { 2,3 });
}

如何避免在调用

2
时指定
b
来表示
N
?为什么这个类型不能自动推导呢?没有它我会得到错误:

'b': 没有找到匹配的重载函数 'int b(int,const std::array &)': 无法推断出 'N' 的模板参数

c++ c++14 template-argument-deduction stdarray function-templates
4个回答
24
投票

C++17

std::array
类模板参数推导 (CTAD)

从 C++17 开始,这个新的语言功能现在由标准库使用,现在还允许我们省略模板类型,以便进行以下操作:

主.cpp

#include <array> int main() { std::array a{1, 2, 3}; }

而不是

std::array<int, 3> a{1, 2, 3};



测试:

g++ -ggdb3 -O0 -std=c++17 -Wall -Wextra -pedantic -o main.out main.cpp

如果我们设置

-std=c++14

 例如,它无法编译:

error: missing template arguments before ‘a’

在 Ubuntu 18.04、GCC 7.5.0 上测试。


9
投票
模板参数推导依赖于实际参数和形式参数之间的直接类型匹配。实际参数是一个初始值设定项列表。它与

array

 类型不匹配(最多可以匹配 
std::array
 中的内部原始数组,但语言规则不支持这一点)。

相反,您可以只使用原始数组,即:

#include <stddef.h> #include <array> template<size_t N> int b(int q, int const (&types)[N] ) { int r = q; for (int t : types) { r = r + t; } return r; } int main() { b( 9, { 2, 3 } ); }

或者,如果您在编译时绝对不需要

N

,则可以使用 
std::initializer_list

还有许多其他可能相关的方法(例如,可变参数模板函数,或定义一个运算符来构建

std::vector

),但很难说哪种方法适合您未公开的目的。


9
投票
从 C++20 开始,我们可以使用

std::to_array()

 进行类型和大小推导。

您的情况:

int b(int q, const auto& types) { int r = q; for (int t : types) { r = r + t; } return r; } b(9, std::to_array({2, 3})); // --- or --- b(9, std::to_array<int>({2, 3}));
我个人更喜欢函数参数中的

std::span

(或gsl::span
)。


1
投票
为了推导

std::array

 大小,您可以使用通用 lambda (C++14):

auto b = [](int q, const auto& types) { int r = q; for (int t : types) { r = r + t; } return r; }; int main() { std::array<int, 2> arr = {{2,3}}; b(9, arr); }

std::make_array

(在 Library Fundamentals TS 中)将由编译器实现时(或者您将使用
一些自己的实现),您在构造时也不需要传递数组大小,只需使用

b(9, std::make_array(2,3));
    
© www.soinside.com 2019 - 2024. All rights reserved.