Let's say I have this function: (which pretty much runs a function on each value in container, and then returns a vector of the result of each iteration)
#include <vector>
using std::vector;
template<class F, class V>
auto vmap(const F &f, const V &v) -> vector<decltype(f(v[0]))> {
vector<decltype(f(v[0]))> result;
result.reserve(v.size());
for (auto &p : v)
result.push_back(f(p));
return result;
}
I can't call it like this:
vector<int> vint = {1,2,3,4,5};
vmap([](auto &p) {return p++;},vint);
Because the parametered vector
is const
, to make it happen I will have to create two vmap
that get non-const
V
and one that is const
.
It starts to feel too much when there are multiple containers/vector
s passed to a function, because it makes me write 2^containers_count
functions.
Is there any(-dirty but working) solution for this?
You could use an forwarding reference to bind to both normal l-value references (e.g. std::vector<int>&
) and r-value references (std::vector<int>&&
).
The downside is that you're never able to pass by value (only ref, const ref, or r-value ref), though I don't think that'll be a problem for you:
template<class F, class V>
auto vmap(F&& f, V&& v) {
vector<decltype(f(v[0]))> result;
result.reserve(v.size());
for (auto& p : v)
result.push_back(f(p));
return result;
}
Note that the lambda you pass must be applicable to both const if you're going to pass a const container (Thanks, Miles), so p++
is out of the question (Although beware that one template instantiation modifies the input and the other doesn't, which may be unexpected):
vector<int> vint = {1,2,3,4,5};
vmap([](auto &p) {return p++;},vint);
const std::vector<int> vint2 = vint;
vmap([](auto &p) {return p+1;},vint2);