namespace std::pmr {
  // [mem.res.class], class memory_resource
  class memory_resource;
  bool operator==(const memory_resource& a, const memory_resource& b) noexcept;
  bool operator!=(const memory_resource& a, const memory_resource& b) noexcept;
  // [mem.poly.allocator.class], class template polymorphic_allocator
  template <class Tp> class polymorphic_allocator;
  template <class T1, class T2>
    bool operator==(const polymorphic_allocator<T1>& a,
                    const polymorphic_allocator<T2>& b) noexcept;
  template <class T1, class T2>
    bool operator!=(const polymorphic_allocator<T1>& a,
                    const polymorphic_allocator<T2>& b) noexcept;
  // [mem.res.global], global memory resources
  memory_resource* new_delete_resource() noexcept;
  memory_resource* null_memory_resource() noexcept;
  memory_resource* set_default_resource(memory_resource* r) noexcept;
  memory_resource* get_default_resource() noexcept;
  // [mem.res.pool], pool resource classes
  struct pool_options;
  class synchronized_pool_resource;
  class unsynchronized_pool_resource;
  class monotonic_buffer_resource;
}
class memory_resource {
  static constexpr size_t max_align = alignof(max_align_t); // exposition only
public:
  virtual ~memory_resource();
  void* allocate(size_t bytes, size_t alignment = max_align);
  void deallocate(void* p, size_t bytes, size_t alignment = max_align);
  bool is_equal(const memory_resource& other) const noexcept;
private:
  virtual void* do_allocate(size_t bytes, size_t alignment) = 0;
  virtual void do_deallocate(void* p, size_t bytes, size_t alignment) = 0;
  virtual bool do_is_equal(const memory_resource& other) const noexcept = 0;
};~memory_resource();
void* allocate(size_t bytes, size_t alignment = max_align);
void deallocate(void* p, size_t bytes, size_t alignment = max_align);
bool is_equal(const memory_resource& other) const noexcept;
virtual void* do_allocate(size_t bytes, size_t alignment) = 0;
virtual void do_deallocate(void* p, size_t bytes, size_t alignment) = 0;
virtual bool do_is_equal(const memory_resource& other) const noexcept = 0;
template <class Tp>
class polymorphic_allocator {
  memory_resource* memory_rsrc; // exposition only
public:
  using value_type = Tp;
  // [mem.poly.allocator.ctor], constructors
  polymorphic_allocator() noexcept;
  polymorphic_allocator(memory_resource* r);
  polymorphic_allocator(const polymorphic_allocator& other) = default;
  template <class U>
    polymorphic_allocator(const polymorphic_allocator<U>& other) noexcept;
  polymorphic_allocator&
    operator=(const polymorphic_allocator& rhs) = delete;
  // [mem.poly.allocator.mem], member functions
  Tp* allocate(size_t n);
  void deallocate(Tp* p, size_t n);
  template <class T, class... Args>
  void construct(T* p, Args&&... args);
  template <class T1, class T2, class... Args1, class... Args2>
    void construct(pair<T1,T2>* p, piecewise_construct_t,
                   tuple<Args1...> x, tuple<Args2...> y);
  template <class T1, class T2>
    void construct(pair<T1,T2>* p);
  template <class T1, class T2, class U, class V>
    void construct(pair<T1,T2>* p, U&& x, V&& y);
  template <class T1, class T2, class U, class V>
    void construct(pair<T1,T2>* p, const pair<U, V>& pr);
  template <class T1, class T2, class U, class V>
    void construct(pair<T1,T2>* p, pair<U, V>&& pr);
  template <class T>
    void destroy(T* p);
  polymorphic_allocator select_on_container_copy_construction() const;
  memory_resource* resource() const;
};polymorphic_allocator() noexcept;
polymorphic_allocator(memory_resource* r);
template <class U>
  polymorphic_allocator(const polymorphic_allocator<U>& other) noexcept;
Tp* allocate(size_t n);
return static_cast<Tp*>(memory_rsrc->allocate(n * sizeof(Tp), alignof(Tp)));
void deallocate(Tp* p, size_t n);
template <class T, class... Args>
  void construct(T* p, Args&&... args);
template <class T1, class T2, class... Args1, class... Args2>
  void construct(pair<T1,T2>* p, piecewise_construct_t,
                 tuple<Args1...> x, tuple<Args2...> y);
template <class T1, class T2>
  void construct(pair<T1,T2>* p);
template <class T1, class T2, class U, class V>
  void construct(pair<T1,T2>* p, U&& x, V&& y);
construct(p, piecewise_construct,
          forward_as_tuple(std::forward<U>(x)),
          forward_as_tuple(std::forward<V>(y)));template <class T1, class T2, class U, class V>
  void construct(pair<T1,T2>* p, const pair<U, V>& pr);
construct(p, piecewise_construct,
          forward_as_tuple(pr.first),
          forward_as_tuple(pr.second));template <class T1, class T2, class U, class V>
  void construct(pair<T1,T2>* p, pair<U, V>&& pr);
construct(p, piecewise_construct,
          forward_as_tuple(std::forward<U>(pr.first)),
          forward_as_tuple(std::forward<V>(pr.second)));template <class T>
  void destroy(T* p);
polymorphic_allocator select_on_container_copy_construction() const;
memory_resource* resource() const;
template <class T1, class T2>
  bool operator==(const polymorphic_allocator<T1>& a,
                  const polymorphic_allocator<T2>& b) noexcept;
template <class T1, class T2>
  bool operator!=(const polymorphic_allocator<T1>& a,
                  const polymorphic_allocator<T2>& b) noexcept;
memory_resource* new_delete_resource() noexcept;
memory_resource* null_memory_resource() noexcept;
memory_resource* set_default_resource(memory_resource* r) noexcept;
memory_resource* get_default_resource() noexcept;
struct pool_options {
  size_t max_blocks_per_chunk = 0;
  size_t largest_required_pool_block = 0;
};
class synchronized_pool_resource : public memory_resource {
public:
  synchronized_pool_resource(const pool_options& opts,
                             memory_resource* upstream);
  synchronized_pool_resource()
      : synchronized_pool_resource(pool_options(), get_default_resource()) {}
  explicit synchronized_pool_resource(memory_resource* upstream)
      : synchronized_pool_resource(pool_options(), upstream) {}
  explicit synchronized_pool_resource(const pool_options& opts)
      : synchronized_pool_resource(opts, get_default_resource()) {}
  synchronized_pool_resource(const synchronized_pool_resource&) = delete;
  virtual ~synchronized_pool_resource();
  synchronized_pool_resource&
    operator=(const synchronized_pool_resource&) = delete;
  void release();
  memory_resource* upstream_resource() const;
  pool_options options() const;
protected:
  void *do_allocate(size_t bytes, size_t alignment) override;
  void do_deallocate(void *p, size_t bytes, size_t alignment) override;
  bool do_is_equal(const memory_resource& other) const noexcept override;
};
class unsynchronized_pool_resource : public memory_resource {
public:
  unsynchronized_pool_resource(const pool_options& opts,
                               memory_resource* upstream);
  unsynchronized_pool_resource()
      : unsynchronized_pool_resource(pool_options(), get_default_resource()) {}
  explicit unsynchronized_pool_resource(memory_resource* upstream)
      : unsynchronized_pool_resource(pool_options(), upstream) {}
  explicit unsynchronized_pool_resource(const pool_options& opts)
      : unsynchronized_pool_resource(opts, get_default_resource()) {}
  unsynchronized_pool_resource(const unsynchronized_pool_resource&) = delete;
  virtual ~unsynchronized_pool_resource();
  unsynchronized_pool_resource&
    operator=(const unsynchronized_pool_resource&) = delete;
  void release();
  memory_resource *upstream_resource() const;
  pool_options options() const;
protected:
  void* do_allocate(size_t bytes, size_t alignment) override;
  void do_deallocate(void* p, size_t bytes, size_t alignment) override;
  bool do_is_equal(const memory_resource& other) const noexcept override;
};size_t max_blocks_per_chunk;
size_t largest_required_pool_block;
synchronized_pool_resource(const pool_options& opts, memory_resource* upstream);
unsynchronized_pool_resource(const pool_options& opts, memory_resource* upstream);
virtual ~synchronized_pool_resource();
virtual ~unsynchronized_pool_resource();
void release();
memory_resource* upstream_resource() const;
pool_options options() const;
void* do_allocate(size_t bytes, size_t alignment) override;
void do_deallocate(void* p, size_t bytes, size_t alignment) override;
bool synchronized_pool_resource::do_is_equal(
    const memory_resource& other) const noexcept override;
bool unsynchronized_pool_resource::do_is_equal(
    const memory_resource& other) const noexcept override;
class monotonic_buffer_resource : public memory_resource {
  memory_resource *upstream_rsrc; // exposition only
  void *current_buffer;           // exposition only
  size_t next_buffer_size;        // exposition only
public:
  explicit monotonic_buffer_resource(memory_resource *upstream);
  monotonic_buffer_resource(size_t initial_size, memory_resource *upstream);
  monotonic_buffer_resource(void *buffer, size_t buffer_size,
                            memory_resource *upstream);
  monotonic_buffer_resource()
      : monotonic_buffer_resource(get_default_resource()) {}
  explicit monotonic_buffer_resource(size_t initial_size)
      : monotonic_buffer_resource(initial_size, get_default_resource()) {}
  monotonic_buffer_resource(void *buffer, size_t buffer_size)
      : monotonic_buffer_resource(buffer, buffer_size, get_default_resource()) {}
  monotonic_buffer_resource(const monotonic_buffer_resource&) = delete;
  virtual ~monotonic_buffer_resource();
  monotonic_buffer_resource
    operator=(const monotonic_buffer_resource&) = delete;
  void release();
  memory_resource* upstream_resource() const;
protected:
  void* do_allocate(size_t bytes, size_t alignment) override;
  void do_deallocate(void* p, size_t bytes, size_t alignment) override;
  bool do_is_equal(const memory_resource& other) const noexcept override;
};explicit monotonic_buffer_resource(memory_resource* upstream);
monotonic_buffer_resource(size_t initial_size, memory_resource* upstream);
monotonic_buffer_resource(void* buffer, size_t buffer_size, memory_resource* upstream);
~monotonic_buffer_resource();
void release();
memory_resource* upstream_resource() const;
void* do_allocate(size_t bytes, size_t alignment) override;
void do_deallocate(void* p, size_t bytes, size_t alignment) override;
bool do_is_equal(const memory_resource& other) const noexcept override;