2311. Allocator requirements should be further minimized

Section: 20.5.3.5 [allocator.requirements] Status: NAD Submitter: Stephan T. Lavavej Opened: 2013-09-21 Last modified: 2016-02-10

Priority: 2

View other active issues in [allocator.requirements].

View all other issues in [allocator.requirements].

View all issues with NAD status.

Discussion:

C++11's minimized allocator requirements are great, but they're still requiring more things from users than absolutely necessary.

[2014-02-14 Issaquah: Close as NAD]

Different vendors rely on each of the different elements suggested to be removed.

While value_type my be deduced as suggested, far too much wording relies on it being available, and the standard churn is likely to be much harder than presented here.

Proposed resolution:

This wording is relative to N3691.

  1. Change in 20.5.3.5 [allocator.requirements], Table 28 — "Allocator requirements" as indicated:

    Table 28 — Allocator requirements (continued)
    Expression Return type Assertion/note pre-/post-condition Default
    X::value_type Identical to T   See Note B, below.
    a1 == a2 bool returns true only if storage
    allocated from each can be
    deallocated via the other.
    operator== shall be reflexive,
    symmetric, and transitive, and
    shall not exit via an exception.
    true
    a1 != a2 bool same as !(a1 == a2)  
    a == b bool same as a ==
    Y::rebind<T>::other(b)
     
    a != b bool same as !(a == b)  
    X a(b);   Shall not exit via an exception.
    post: Y(a) == b, a == X(b)
     
    X a(move(b));   Shall not exit via an exception.
    post: a equals the prior value of X(b).
     
  2. After 20.5.3.5 [allocator.requirements] p3, add a new paragraph:

    Note B: If Allocator is a class template instantiation of the form SomeAllocator<T, Args>, where Args is zero or more type arguments, and Allocator does not supply a nested type named value_type, the standard allocator_traits template uses T in place of Allocator::value_type by default. For allocator types that are not template instantiations of the above form, no default is provided.

  3. In the example provided in 20.5.3.5 [allocator.requirements]/5, delete as indicated:

    template <class Tp>
    struct SimpleAllocator {
      typedef Tp value_type;
      SimpleAllocator(ctor args);
      template <class T> SimpleAllocator(const SimpleAllocator<T>& other);
      Tp *allocate(std::size_t n);
      void deallocate(Tp *p, std::size_t n);
    };
    
    template <class T, class U>
    bool operator==(const SimpleAllocator<T>&, const SimpleAllocator<U>&);
    template <class T, class U>
    bool operator!=(const SimpleAllocator<T>&, const SimpleAllocator<U>&);
    
  4. Edit 23.10.9 [allocator.traits]p1, class template allocator_traits synopsis, as indicated:

    namespace std {
      template <class Alloc> struct allocator_traits {
        typedef Alloc allocator_type;
    
        typedef typename Alloc::value_typesee below value_type;
    
        […]
    
        static Alloc select_on_container_copy_construction(const Alloc& rhs);
    
        static bool equal(const Alloc& a1, const Alloc& a2) noexcept;
      };
    }
    
  5. At the beginning of 23.10.9.1 [allocator.traits.types], add a new paragraph:

    typedef see below value_type;
    

    Type: Alloc::value_type if such a type exists; otherwise, T if Alloc is a class template instantiation of the form Alloc<T, Args>, where Args is zero or more type arguments; otherwise, the program is ill-formed.

  6. At the end of 23.10.9.2 [allocator.traits.members], add a new paragraph:

    static bool equal(const Alloc& a1, const Alloc& a2) noexcept;
    

    -?- Returns: a1 == a2 if that expression is well-formed; otherwise, true.