The short version of my question is this: How can I use something like std::bind()
with a standard library algorithm?
Since the short version is a bit devoid of details, here is a bit of an explanation: Assume I have the algorithms std::transform()
and now I want to implement std::copy()
(yes, I realize that there is std::cpopy()
in the standard C++ library). Since I'm hideously lazy, I clearly want to use the existing implementation of std::transform()
. I could, of course, do this:
struct identity {
template <typename T>
auto operator()(T&& value) const -> T&& { return std::forward<T>(value); }
};
template <typename InIt, typename OutIt>
auto copy(InIt begin, InIt end, OutIt to) -> OutIt {
return std::transform(begin, end, to, identity());
}
Somehow this implementation somewhat feels like a configuration of an algorithm. For example, it seems as if std::bind()
should be able to do the job but simply using std::bind()
doesn't work:
namespace P = std::placeholders;
auto copy = std::bind(std::transform, P::_1, P::_2, P::_3, identity());
The problem is that the compiler can't determine the appropriate template arguments from just the algorithm and it doesn't matter if there is an &
or not. Is there something which can make an approach like using std::bind()
work? Since this is looking forward, I'm happy with a solution working with anything which is already proposed for inclusion into the C++ standard. Also, to get away with my laziness I'm happy to do some work up front for later easier use. Think of it this way: in my role as a library implementer, I'll put things together once such that every library user can be lazy: I'm a busy implementer but a lazy user.
In case you want to have a ready-made test bed: here is a complete program.
#include <algorithm>
#include <functional>
#include <iostream>
#include <iterator>
#include <utility>
#include <vector>
using namespace std::placeholders;
struct identity {
template <typename T>
T&& operator()(T&& value) const { return std::forward<T>(value); }
};
int main()
{
std::vector<int> source{ 0, 1, 2, 3, 4, 5, 6 };
std::vector<int> target;
#ifdef WORKS
std::transform(source.begin(), source.end(), std::back_inserter(target),
identity());
#else
// the next line doesn't work and needs to be replaced by some magic
auto copy = std::bind(&std::transform, _1, _2, _3, identity());
copy(source.begin(), source.end(), std::back_inserter(target));
#endif
std::copy(target.begin(), target.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << "\n";
}
Aucun commentaire:
Enregistrer un commentaire