Копирование-назначение неупорядоченной карты с несовместимыми распределителями - PullRequest
0 голосов
/ 09 октября 2018

Рассмотрим следующий фиктивный распределитель (созданный для примера):

template<typename T> class C
{
public:
    typedef T value_type;

    C() = default;

    template<typename U>
    C(C<U> const &a)
    {}


    T* allocate(std::size_t n, T const* = nullptr)
    {
        return new T[n];
    }

    void deallocate(T* p, std::size_t n)
    {
        return;
    }

    typedef value_type       *pointer;
    typedef const value_type *const_pointer;
    typedef value_type       &      reference;
    typedef value_type const &const_reference;
    typedef std::size_t       size_type;
    typedef std::ptrdiff_t    difference_type;
    static       pointer address(reference x) { return &x; }
    static const_pointer address(const_reference x) { return &x; }
    static size_type max_size() { return std::numeric_limits<size_type>::max(); }
    template <typename U> static void destroy(U* ptr) { ptr->~U(); }
    template <typename U> struct rebind { using other = C<U>; };

    template<typename U, typename... Args>
    static void construct(U* ptr, Args&&... args) {
        new (ptr) U(std::forward<Args>(args)...);
    }
};

template<class T1, class T2>
bool operator==(C<T1> const& lhs, C<T2> const& rhs)
{
    return std::addressof(lhs) == std::addressof(rhs);
}

template<class T1, class T2>
bool operator!=(C<T1> const& lhs, C<T2> const& rhs)
{
    return !(lhs == rhs);
}

Большая часть этого кода является котельной.Важным моментом является то, что любые два экземпляра распределителя будут считаться несовместимыми - bool operator== всегда возвращает false.Когда я пытаюсь использовать этот распределитель с большинством контейнеров STL, таких как std::vector, для копирования-назначения очень простых элементов, таких как:

std::vector<int, C<int>> a;
a = std::vector<int, C<int>>();

Все работает, и я получаю ожидаемое поведение.Однако, когда я делаю то же самое, но вместо этого std::unordered_map, я получаю разное поведение на двух платформах, которые мне нужно поддерживать.В Linux с GCC 7.1 я продолжаю получать ожидаемое поведение.Однако в Windows с VS 2015 я получаю сообщение об ошибке, утверждающее containers incompatible for swap в заголовке VS под названием xmemory0.Обратите внимание, что код, используемый для std::unordered_map, в значительной степени совпадает с приведенным выше для std::vector:

using B = std::unordered_map<int, int, std::hash<int>, std::equal_to<int>, C<std::pair<int const, int>>>;
B b;
b = B();

Что-то не так с моим распределителем, и GCC 7.1 дает мне неопределенное поведение?Если нет, то это сбой библиотеки времени выполнения VS 2015?Если так, то почему эта ошибка присутствует только с unordered_map?

Ответы [ 2 ]

0 голосов
/ 09 октября 2018

Это не соответствующий распределитель.Все копии распределителя, включая восстановленные, должны сравниваться равными друг другу.


Кроме того, unordered_map value_type равно pair<const Key, Value>, так что ваш примерследует использовать C<pair<const int, int>>.

0 голосов
/ 09 октября 2018

У вас не может быть распределителей, которые уникально владеют состоянием, они должны быть CopyConstructible .Например, вы должны переключиться с std::unique_ptr с на std::shared_ptr с.

Вам следует ослабить свои сравнения

template<class T1, class T2>
bool operator==(C<T1> const& lhs, C<T2> const& rhs)
{
    return /* check equality of some member of C */;
}

template<class T1, class T2>
bool operator!=(C<T1> const& lhs, C<T2> const& rhs)
{
    return !(lhs == rhs);
}

Возможно, вы также можете извлечь пользу из соблюдения правила , равного нулю./ five и определение propogate_on_container_copy_assignment, propogate_on_container_move_assignment и propogate_on_container_swap как std::true_type

Подсказка относительно того, где MSVC срабатывает

Примечание: заменадва контейнера с неравными распределителями, если propagate_on_container_swap равно false - неопределенное поведение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...