Title
scoped_allocator_adaptor construct and destroy don't use allocator_traits
Status
resolved
Section
[allocator.adaptor.members]
Submitter
Howard Hinnant

Created on 2010-02-16.00:00:00 last changed 170 months ago

Messages

Date: 2010-10-21.18:28:33

Proposed resolution:

In [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.

  • If uses_allocator<T, inner_allocator_type>::value is false and is_constructible<T, Args...>::value is true, calls OUTERMOST(*this). OUTERMOST_ALLOC_TRAITS(outer_allocator())::construct( OUTERMOST(outer_allocator()), p, std::forward<Args>(args)... ).
  • Otherwise, if uses_allocator<T, inner_allocator_type>::value is true and is_constructible<T, allocator_arg_t, inner_allocator_type, Args...>::value is true, calls OUTERMOST(*this). OUTERMOST_ALLOC_TRAITS(outer_allocator())::construct( OUTERMOST(outer_allocator()), p, allocator_arg, inner_allocator(), std::forward<Args>(args)... ).
  • Otherwise, if uses_allocator<T, inner_allocator_type>::value is true and is_constructible<T, Args..., inner_allocator_type>::value is true, calls OUTERMOST(*this). OUTERMOST_ALLOC_TRAITS(outer_allocator())::construct( OUTERMOST(outer_allocator()), p, std::forward<Args>(args)..., inner_allocator() ).
  • Otherwise, the program is ill-formed. [Note: an error will result if uses_allocator evaluates to true but the specific constructor does not take an allocator. This definition prevents a silent failure to pass an inner allocator to a contained element. — end note]
template <class T>
  void destroy(T* p);

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

Date: 2010-10-21.18:28:33

Rationale:

Solved by N3059.

Date: 2010-10-21.18:28:33

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

Date: 2010-10-21.18:28:33

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

Date: 2010-02-16.00:00:00

[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.

  • If uses_allocator<T, inner_allocator_type>::value is false and is_constructible<T, Args...>::value is true, calls OUTERMOST(*this).construct(p, std::forward<Args>(args)...).
  • Otherwise, if uses_allocator<T, inner_allocator_type>::value is true and is_constructible<T, allocator_arg_t, inner_allocator_type, Args...>::value is true, calls OUTERMOST(*this).construct(p, allocator_arg, inner_allocator(),std::forward<Args>(args)...).
  • Otherwise, if uses_allocator<T, inner_allocator_type>::value is true and is_constructible<T, Args..., inner_allocator_type>::value is true, calls OUTERMOST(*this).construct(p, std::forward<Args>(args)..., inner_allocator()).
  • Otherwise, the program is ill-formed. [Note: an error will result if uses_allocator evaluates to true but the specific constructor does not take an allocator. This definition prevents a silent failure to pass an inner allocator to a contained element. — end note]
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.

History
Date User Action Args
2010-11-19 19:04:45adminsetstatus: nad editorial -> resolved
2010-10-21 18:28:33adminsetmessages: + msg1594
2010-10-21 18:28:33adminsetmessages: + msg1593
2010-10-21 18:28:33adminsetmessages: + msg1592
2010-10-21 18:28:33adminsetmessages: + msg1591
2010-02-16 00:00:00admincreate