在以下代码中:
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++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 上测试。
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
),但很难说哪种方法适合您未公开的目的。
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}));
我个人更喜欢函数参数中的(或gsl::span
)。
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));