作者:-苏小澄11m | 来源:互联网 | 2023-09-13 08:08
我想模仿C ++中Ruby的map()
方法。我正在努力自动找出返回类型:
#include
#include
#include
#include
typedef std::string T2;
template class UnaryPredicate>
std::vector map(std::vector in,UnaryPredicate pred)
{
std::vector res(in.size());
std::transform(in.begin(),in.end(),res.begin(),pred);
return res;
}
int main()
{
std::vector v1({1,2,3});
auto v2(map(v1,[](auto el) { return "'"+std::to_string(el+1)+"'"; }));
std::cout <}
通过这种方式进行编译,但是T2
固定为string
。如果我使用其他T2
定义,则编译器会抱怨couldn't deduce template parameter 'T2'
。
我也尝试使用std::declval
,但可能不是正确的方法-我无法解决问题。
使用decltype
+ std::decay_t
:
template
auto map(const std::vector& in,UnaryPredicate pred)
{
using result_t = std::decay_t;
std::vector res;
res.reserve(in.size());
std::transform(in.begin(),in.end(),std::back_inserter(res),pred);
return res;
}
用法示例:
std::vector v1{1,2,3};
auto v2 = map(v1,[](int el) { return "'" + std::to_string(el + 1) + "'"; });
std::cout <
(live demo)
也请注意我所做的以下更改:
-
我将in
更改为采用const引用而不是值。这样可以避免不必要的复制。
-
我使用了reserve
+ back_inserter
,而不是值初始化+赋值。
-
我使用auto
作为返回类型。这使得返回类型推导成为可能。保证res
向量不会被复制。还可以进行复制省略。
-
您可以直接从 braced-init-list 进行列表初始化,因此请删除 braced-init-list 周围的括号。
当std::endl
足够时,不应使用-
\n
。 std::endl
导致刷新缓冲区,而\n
则不刷新。不必要的冲洗会导致性能下降。参见std::endl
vs \n
。
,
为简化起见,请使用auto
作为返回类型,向量value_type
可以由declval
指定-为UnaryPredicate
调用T1
:
template
auto map(std::vector in,UnaryPredicate pred)
{
std::vector()(T1{})) > res(in.size());
std::transform(in.begin(),res.begin(),pred);
return res;
}
Demo