I\'m trying to implement a function similar to std::transform
algorithm but instead of taking the output iterator by an argument I want to create and return a c
The major difficulty is to somehow get the container type Container
from Conainer
. I have shamelessly stolen the code from template metaprogramming: (trait for?) dissecting a specified template into types T
#include
#include
#include
// stolen from Kerrek SB's answer
template
struct tmpl_rebind {
typedef T type;
};
template class Tmpl, typename ...T, typename ...Args>
struct tmpl_rebind, Args...> {
typedef Tmpl type;
};
// end of stolen code
template ::type,
typename NewContainer = typename tmpl_rebind::type >
NewContainer convert(const Container& c, Func f) {
NewContainer nc;
std::transform(std::begin(c), std::end(c), std::inserter(nc, std::end(nc)), f);
return nc;
}
int main() {
std::vector vi{ 1, 2, 3, 4, 5 };
auto vs = convert(vi, [] (int i) { return std::to_string(i); });
assert( vs == std::vector( {"1", "2", "3", "4", "5"} ) );
return 0;
}
I have tested this code with gcc 4.7.2 and clang 3.5 and works as expected.
As Yakk points out, there are quite a few caveats with this code though: "... should your rebind replace all arguments, or just the first one? Uncertain. Should it recursively replace T0
with T1
in later arguments? Ie std::map
-> std::map
?" I also see traps with the above code (e.g. how to deal with different allocators, see also Useless' answer).
Nevertheless, I believe the above code is already useful for simple use cases. If we were writing a utility function to be submitted to boost, then I would be more motivated to investigate these issues further. But there is already an accepted answer so I consider the case closed.
Many thanks to Constructor, dyp and Yakk for pointing out my mistakes / missed opportunities for improvements.