Краткая версия моего вопроса такова: как я могу использовать что-то вроде std::bind()
со стандартным алгоритмом библиотеки?
Поскольку короткая версия немного лишена деталей, вот немного объяснения: предположим, что у меня есть алгоритмы std::transform()
, и теперь я хочу реализовать std::copy()
(да, я понимаю, что есть std::copy()
в стандартной библиотеке С++). Поскольку я ужасно ленив, я явно хочу использовать существующую реализацию std::transform()
. Я мог бы, конечно, сделать это:
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());
}
Как-то эта реализация несколько похожа на конфигурацию алгоритма. Например, кажется, что std::bind()
должен уметь выполнять задание, но просто используя std::bind()
не работает:
namespace P = std::placeholders;
auto copy = std::bind(std::transform, P::_1, P::_2, P::_3, identity());
Проблема заключается в том, что компилятор не может определить соответствующие аргументы шаблона только из алгоритма, и не имеет значения, существует ли &
или нет. Есть ли что-то, что может сделать такой подход, как использование std::bind()
работы? Поскольку это с нетерпением ждет, я доволен решением, работающим со всем, что уже предлагается для включения в стандарт С++. Кроме того, чтобы уйти с моей леностью, я счастлив сделать некоторые работы перед тем, чтобы более легко использовать их. Подумайте об этом так: в моей роли библиотекаря я собираюсь собрать вещи один раз, чтобы каждый пользователь библиотеки мог лениться: я занят реализацией, но ленивый пользователь.
Если вы хотите иметь готовое тестовое постели: вот полная программа.
#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";
}