Tra*_*Cpp 5 c++ templates stdvector c++11
I'd like to have a templated function taking in a vector<T> v and a function op, mapping T to vector<U> and would like to concatenate the results of applying f to every element vector of v to return a vector<U> = [ Elements of op(v[0]), Elements of op(v[1]) ...].
A working option I found was adding an example in the function to allow for template deduction:
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;
}
Run Code Online (Sandbox Code Playgroud)
But naturally I'd like to produce the same result with only the two parameters.
My attempt [replacing U with 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;
}
Run Code Online (Sandbox Code Playgroud)
Unfortunately this didn't compile. I'm also worried of wasting time if op is complex method.
This gave:
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&
Run Code Online (Sandbox Code Playgroud)
... so it seems to be related to 'const'.
How would this variant be corrected? Are there better alternatives?
解引用容器迭代器产生参考(或const引用,如果容器是常数),这就是为什么decltype(*std::begin(op(*std::begin(c))))产率const U&根据你的编译器错误(和不U)。
您可以通过以下方法解决此问题:通过使用std :: remove_reference再次删除引用(或者,如果您也要删除const和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;
}
Run Code Online (Sandbox Code Playgroud)
您还可以decltype通过命名来避免圣歌的三重重复:
template <typename Container, typename UnaryOperation>
using applied_op_t = typename decltype(std::declval<UnaryOperation>()(*std::begin(std::declval<Container>())))::value_type;
Run Code Online (Sandbox Code Playgroud)