Справочная информация:
Я хотел создать функцию, которая при vector
V возвращает vector
из reference_wrapper
s VR каждому элементу в V.
Это тривиально, но я также хотел, чтобы возвращаемый вектор копировал распределитель отскока , если исходный вектор имеет (возможно, с сохранением состояния) пользовательский распределитель.
Я придумал MVCE ниже, который компилируется на Годболте.
Вопрос:
- Правильно ли мое понимание и реализация, особенно в отношении повторного связывания распределителя?
- Будет ли он работать для всех соответствующих пользовательских распределителей?
- Если нет, то что я пропустил?
Код:
#include <algorithm>
#include <string>
#include <vector>
#include <functional>
#include <type_traits>
// A class to make my nasty string unmoveable, and therefore expensive
// to sort
struct Nasty
{
Nasty(std::string s) : value_(std::move(s)) {}
Nasty(Nasty const&) = default;
Nasty& operator=(Nasty const&) = default;
auto value() const -> std::string const& {
return value_;
}
std::string value_;
};
// function object class to deduce types and perform the conversion
template<class V>
struct as_references_op
{
using vector_type = V;
using value_type = typename V::value_type;
static constexpr bool is_const = std::is_const<vector_type>::value;
using referred_type = std::conditional_t<is_const, std::add_const_t<value_type>, value_type>;
using allocator_type = typename V::allocator_type;
using a_traits = std::allocator_traits<allocator_type>;
using rebound_allocator = typename a_traits::template rebind_traits<referred_type>::allocator_type;
using result_type = std::vector<std::reference_wrapper<referred_type>, rebound_allocator>;
result_type operator()(V& v) const
{
auto result = result_type(v.begin(), v.end(), v.get_allocator());
return result;
}
};
// interface functions
template<class T, class A>
decltype(auto) as_references(std::vector<T, A> const& v)
{
auto op = as_references_op<std::vector<T, A> const>();
return op(v);
}
template<class T, class A>
decltype(auto) as_references(std::vector<T, A>& v)
{
auto op = as_references_op<std::vector<T, A>>();
return op(v);
}
// test
int main()
{
auto v = std::vector<Nasty> { Nasty("gah"), Nasty("bar"), Nasty("zoo"), Nasty("foo") };
auto sv = as_references(v);
auto by_dereferenced_value = [] (auto&& x, auto&& y) {
return x.get().value() < y.get().value();
};
std::sort(begin(sv), end(sv), by_dereferenced_value);
}