Перепривязка и копирование выделителя из стандартного контейнера - PullRequest
0 голосов
/ 08 мая 2018

Справочная информация:

Я хотел создать функцию, которая при 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);
}
...