1321. scoped_allocator_adaptor construct and destroy don't use allocator_traits

Section: 20.5.4 [allocator.adaptor.members] Status: Resolved Submitter: Howard Hinnant Opened: 2010-02-16 Last modified: 2016-01-28

Priority: Not Prioritized

View all other issues in [allocator.adaptor.members].

View all issues with Resolved status.

Discussion:

20.5.4 [allocator.adaptor.members] p8-9 says:

template <class T, class... Args>
  void construct(T* p, Args&&... args);

8 Effects: let OUTERMOST(x) be x if x does not have an outer_allocator() function and OUTERMOST(x.outer_allocator()) otherwise.

template <class T>
  void destroy(T* p);

9 Effects: calls outer_allocator().destroy(p).

In all other calls where applicable scoped_allocator_adaptor does not call members of an allocator directly, but rather does so indirectly via allocator_traits. For example:

size_type max_size() const;

7 Returns: allocator_traits<OuterAlloc>::max_size(outer_allocator()).

Indeed, without the indirection through allocator_traits the definitions for construct and destroy are likely to fail at compile time since the outer_allocator() may not have the members construct and destroy.

[ The proposed wording is a product of Pablo, Daniel and Howard. ]

[ 2010 Pittsburgh: Moved to NAD Editorial. Rationale added below. ]

Rationale:

Solved by N3059.

Proposed resolution:

In 20.5.4 [allocator.adaptor.members] move and change p8 as indicated, and change p9 as indicated:

Let OUTERMOST(x) be x if x does not have an outer_allocator() member function and OUTERMOST(x.outer_allocator()) otherwise. Let OUTERMOST_ALLOC_TRAITS(x) be allocator_traits<decltype(OUTERMOST(x))>. [Note: OUTERMOST(x) and OUTERMOST_ALLOC_TRAITS(x) are recursive operations. It is incumbent upon the definition of outer_allocator() to ensure that the recursion terminates. It will terminate for all instantiations of scoped_allocator_adaptor. — end note]

template <class T, class... Args>
  void construct(T* p, Args&&... args);

8 Effects: let OUTERMOST(x) be x if x does not have an outer_allocator() function and OUTERMOST(x.outer_allocator()) otherwise.

template <class T>
  void destroy(T* p);

9 Effects: calls outer_allocator(). OUTERMOST_ALLOC_TRAITS(outer_allocator())::destroy( OUTERMOST(outer_allocator()), p).