C ++: не может распространять polymorphic_allocator с помощью scoped_allocator_adaptor - PullRequest
0 голосов
/ 12 февраля 2019

У меня есть vector<vector<int>> и я хочу, чтобы вся память (т. Е. Как внешнего, так и внутреннего вектора) была взята из memory_resource.Вот урезанный пример, сначала скучная часть:

#include <boost/container/pmr/memory_resource.hpp>
#include <boost/container/scoped_allocator.hpp>
#include <boost/container/pmr/polymorphic_allocator.hpp>
#include <iostream>
#include <string>
#include <vector>

// Sample memory resource that prints debug information
class MemoryResource : public boost::container::pmr::memory_resource {
  void* do_allocate(std::size_t bytes, std::size_t alignment) {
    std::cout << "Allocate " << bytes << " bytes" << std::endl;
    return malloc(bytes);
  }
  void do_deallocate(void* p, std::size_t bytes, std::size_t alignment) { free(p); }
  bool do_is_equal(const memory_resource& other) const noexcept { return true; }
};

Это часть, которая меня интересует:

template <typename T>
using Alloc = boost::container::pmr::polymorphic_allocator<T>;
// using Alloc = std::allocator<T>;

template <typename T>
using PmrVector = std::vector<T, boost::container::scoped_allocator_adaptor<Alloc<T>>>;

using Inner = PmrVector<int>;

int main() {
  MemoryResource resource{};

  PmrVector<Inner> v(1000, Alloc<Inner>{&resource});
  // PmrVector<Inner> v(1337, Alloc<Inner>{});
  v[0].resize(100);
}

Это дает мне длинное предупреждение компилятора , фактически говоря, что он не может найти конструктор для внутреннего вектора.

Если вместо полиморфного распределителя я использую обычный распределитель (например, std :: allocator - посмотрите строки, которыезакомментировано), все вроде бы работает.

Сообщение об ошибке gcc немного лучше, чем у clang:

/usr/local/include/boost/container/allocator_traits.hpp:415:10:
error: no matching function for call to '
  std::vector<int, polymorphic_allocator<int> >::vector(
    scoped_allocator_adaptor<...>&, polymorphic_allocator<...>&
  )
'

Зачем форсировать пытаться построить вектор, передавая распределительдважды?

Кроме того, здесь - это версия, которая использует STL (экспериментальный) вместо boost.Этот факт выдает фактическое сообщение об ошибке «Конструкция с распределителем должна быть возможна, если в параметре used_allocator указано значение true», но это мне тоже не помогает.

Возможно, я понимаю что-то концептуально неправильное.Это способ сделать это или есть лучший способ решить исходную проблему?

1 Ответ

0 голосов
/ 12 февраля 2019

Argh.Объяснение скрыто в std::experimental::pmr::polymorphic_allocator::construct:

Эта функция вызывается (через std :: allocator_traits) любым объектом, распознающим распределитель, таким как std :: vector, чтов качестве распределителя использовать std :: polymorphic_allocator.Поскольку memory_resource * неявно преобразуется в polymorphic_allocator, указатель ресурса памяти будет распространяться на любые подобъекты с поддержкой распределителя с использованием полиморфных распределителей.

Таким образом, оказывается, что полиморфные распределители автоматически распространяются.Это также объясняет, почему распределитель передается дважды в сообщении об ошибке gcc.

Вот рабочая версия:

template <typename T>
using Alloc = std::experimental::pmr::polymorphic_allocator<T>;

template <typename T>
using PmrVector = std::vector<T, Alloc<T>>;

using Inner = PmrVector<int>;

int main() {
  MemoryResource resource{};

  PmrVector<Inner> v(1000, Alloc<Inner>{&resource});
  v[0].resize(100);
}

А вот информация, которая мне понадобится через пару часовназад:

Как мне использовать polymorphic_allocator и scoped_allocator_adaptor вместе?

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

...