我现在正在学习 C++,并尝试一些模板功能。我正在尝试创建一个通用模板,该模板接收F
来自U
to 的函数V
,std::array
类型为a U
,然后返回(通过 NRVO)类型为的数组V
。
这是我在第一遍时想到的。对于我未经训练的眼睛来说,这似乎是合理的,但编译器不喜欢它:
template <typename F, typename U, typename V, std::size_t N> std::array<V, N> map(F mapper, const std::array<U, N> &elements)
{
std::array<V, N> newArray{};
for (std::size_t i = 0; i < N; i++) {
newArray[i] = mapper(elements[i]);
}
return newArray;
}
// ...
int main()
{
std::array<int, 10> ints1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
auto doubles1 = map([](int x) -> double { return x*2.5; }, ints1);
}
我正在使用 clang 16.0.6,它告诉我:
functional.cpp:87:19: error: no matching function for call to 'map'
auto doubles1 = map([](int x) -> double { return x*2.5; }, ints1);
^~~~~~~~~~~~
functional.cpp:22:79: note: candidate template ignored: couldn't infer template argument 'V'
template <typename F, typename U, typename V, std::size_t N> std::array<V, N> map(F mapper, std::array<U, N> &elements)
^
1 error generated.
在我看来,我似乎应该做一些事情来提示编译器 lambda 返回一个 double,因此 应该auto
被推导为std::array<double, N>
。我缺少什么简单的东西吗?谢谢。
我当然希望代码能够编译,但有些事情不太正确。我对 C++ 术语还很陌生,所以我不知道到底要谷歌什么来解决这个问题。我想出的一种可能的解决方案是使用外参数:
template <typename F, typename U, typename V, std::size_t N> void map_outParam(F mapper, std::array<U, N> &elements, std::array<V, N> &out)
{
for (std::size_t i = 0; i < N; i++) {
out[i] = mapper(elements[i]);
}
}
这编译得很好,并且按预期工作。然而,它并不像我想要的那么干净。
您很接近,但模板参数的顺序令人困惑:
不同之处在于存在隐式模板参数的概念,编译器在其中推导模板类型。您最初订购它们的方式不符合
V
无法推断的要求,因此没有匹配的功能。因此上面的示例调整了顺序并明确定义了内容
V
。基本上,您可以使用回调函数的结果类型来确定结果数组的类型。
映射元素可能不可默认构造。
您可以在 的 CTAD
std::apply
的帮助下更轻松地完成此操作std::array