使用模板将多个向量(函数的结果)组合成一个
Combine multiple vectors (results of function) into one with template
我想要一个接受 vector<T> v
和函数 op 的模板化函数,将 T
映射到 vector<U>
并希望连接应用 [= 的结果16=] 到 v
到 return 的每个元素向量 a vector<U>
= [ op(v[0]) 的元素,op(v[1]) 的元素 ...] .
我发现的一个有效选项是在函数中添加一个示例以允许模板推导:
template <typename Container>
Container& concat(Container& c1, Container const& c2) {
c1.insert(end(c1), begin(c2), end(c2));
return c1;
}
template <typename Container, typename UnaryOperation, typename U>
inline auto to_vec_from_vectors(Container& c, UnaryOperation&& op, U& ex)
-> std::vector<U> {
std::vector<U> v;
for (auto& e : c) {
std::vector<U> opv = op(e);
concat(v, opv);
}
return v;
}
但自然而然地,我想只用这两个参数产生相同的结果。
我的尝试[将U
替换为decltype(*std::begin(op(*std::begin(c))))
]:
template <typename Container, typename UnaryOperation, typename U>
inline auto to_vec_from_vectors(Container& c, UnaryOperation&& op, U& ex)
-> std::vector<decltype(*std::begin(op(*std::begin(c))))> {
std::vector<decltype(*std::begin(op(*std::begin(c))))> v;
for (auto& e : c) {
std::vector<decltype(*std::begin(op(*std::begin(c))))> opv = op(e);
concat(v, opv);
}
return v;
}
不幸的是,这没有编译。如果 op 是复杂的方法,我也担心浪费时间。
这给了:
error: conversion from ‘std::vector<U>’ to non-scalar type ‘std::vector<const U&, std::allocator<const U&> >’ requested
error: forming pointer to reference type ‘const U&
...
所以它似乎与 'const'.
有关
如何更正此变体?有更好的选择吗?
取消引用容器迭代器会产生一个引用(或一个 const 引用,如果容器是 const),这就是为什么 decltype(*std::begin(op(*std::begin(c))))
根据您的编译器错误产生 const U&
(而不是 U
).
您可以通过使用 std::remove_reference (or, if you want to also remove const
and volatile
, std::remove_cvref) 再次删除引用来解决这个问题,或者只询问向量它实际存储的内容:
decltype(*std::begin(op(*std::begin(c))))
-> typename decltype(op(*std::begin(c)))::value_type
我已经删除了不需要的 U& ex
参数。
template <typename Container, typename UnaryOperation>
inline auto to_vec_from_vectors(Container& c, UnaryOperation&& op)
-> std::vector<typename decltype(op(*std::begin(c)))::value_type> {
std::vector<typename decltype(op(*std::begin(c)))::value_type> v;
for (auto& e : c) {
std::vector<typename decltype(op(*std::begin(c)))::value_type> opv = op(e);
concat(v, opv);
}
return v;
}
您还可以通过命名来避免 decltype
颂歌的三次重复:
template <typename Container, typename UnaryOperation>
using applied_op_t = typename decltype(std::declval<UnaryOperation>()(*std::begin(std::declval<Container>())))::value_type;
我想要一个接受 vector<T> v
和函数 op 的模板化函数,将 T
映射到 vector<U>
并希望连接应用 [= 的结果16=] 到 v
到 return 的每个元素向量 a vector<U>
= [ op(v[0]) 的元素,op(v[1]) 的元素 ...] .
我发现的一个有效选项是在函数中添加一个示例以允许模板推导:
template <typename Container>
Container& concat(Container& c1, Container const& c2) {
c1.insert(end(c1), begin(c2), end(c2));
return c1;
}
template <typename Container, typename UnaryOperation, typename U>
inline auto to_vec_from_vectors(Container& c, UnaryOperation&& op, U& ex)
-> std::vector<U> {
std::vector<U> v;
for (auto& e : c) {
std::vector<U> opv = op(e);
concat(v, opv);
}
return v;
}
但自然而然地,我想只用这两个参数产生相同的结果。
我的尝试[将U
替换为decltype(*std::begin(op(*std::begin(c))))
]:
template <typename Container, typename UnaryOperation, typename U>
inline auto to_vec_from_vectors(Container& c, UnaryOperation&& op, U& ex)
-> std::vector<decltype(*std::begin(op(*std::begin(c))))> {
std::vector<decltype(*std::begin(op(*std::begin(c))))> v;
for (auto& e : c) {
std::vector<decltype(*std::begin(op(*std::begin(c))))> opv = op(e);
concat(v, opv);
}
return v;
}
不幸的是,这没有编译。如果 op 是复杂的方法,我也担心浪费时间。
这给了:
error: conversion from ‘std::vector<U>’ to non-scalar type ‘std::vector<const U&, std::allocator<const U&> >’ requested
error: forming pointer to reference type ‘const U&
... 所以它似乎与 'const'.
有关如何更正此变体?有更好的选择吗?
取消引用容器迭代器会产生一个引用(或一个 const 引用,如果容器是 const),这就是为什么 decltype(*std::begin(op(*std::begin(c))))
根据您的编译器错误产生 const U&
(而不是 U
).
您可以通过使用 std::remove_reference (or, if you want to also remove const
and volatile
, std::remove_cvref) 再次删除引用来解决这个问题,或者只询问向量它实际存储的内容:
decltype(*std::begin(op(*std::begin(c))))
-> typename decltype(op(*std::begin(c)))::value_type
我已经删除了不需要的 U& ex
参数。
template <typename Container, typename UnaryOperation>
inline auto to_vec_from_vectors(Container& c, UnaryOperation&& op)
-> std::vector<typename decltype(op(*std::begin(c)))::value_type> {
std::vector<typename decltype(op(*std::begin(c)))::value_type> v;
for (auto& e : c) {
std::vector<typename decltype(op(*std::begin(c)))::value_type> opv = op(e);
concat(v, opv);
}
return v;
}
您还可以通过命名来避免 decltype
颂歌的三次重复:
template <typename Container, typename UnaryOperation>
using applied_op_t = typename decltype(std::declval<UnaryOperation>()(*std::begin(std::declval<Container>())))::value_type;