我现在正在学习 C++,并尝试一些模板功能。我正在尝试创建一个通用模板,该模板接收从
F
到 U
的函数 V
(std::array
类型的 U
),然后返回(通过 NRVO)类型为 V
的数组。
这是我第一次想到的。对于我未经训练的眼睛来说,这似乎是合理的,但编译器不喜欢它:
template <typename F, typename U, typename V, std::size_t N> std::array<V, N> map(F mapper, 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]);
}
}
编译得很好,并且按预期工作。然而,它并不像我想要的那么干净。
你很接近,但模板参数的顺序令人困惑:
#include <cstddef>
#include <array>
#include <iostream>
template <typename V, std::size_t N, typename F, typename U>
std::array<V, N> map(
F mapper,
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<double>(
[](int x) -> double {
return x*2.5;
},
ints1
);
for (auto it = doubles1.begin(); it != doubles1.end(); ++it) {
std::cout<<*it<<'\n';
}
}
区别在于存在隐式模板参数的概念,编译器在其中推导模板类型。您最初订购它们的方式不尊重无法推断出
V
,因此没有匹配的功能。
因此上面的示例调整了顺序并明确定义了
V
是什么。