Default std::vector<bool> default and move constructor

Jonathan Wakely jwakely@redhat.com
Sat May 27 11:14:00 GMT 2017


On 26/05/17 23:13 +0200, François Dumont wrote:
>On 25/05/2017 18:28, Jonathan Wakely wrote:
>>On 15/05/17 19:57 +0200, François Dumont wrote:
>>>Hi
>>>
>>>   Following what I have started on RbTree here is a patch to 
>>>default implementation of default and move constructors on 
>>>std::vector<bool>.
>>>
>>>   As in _Rb_tree_impl the default allocator is not value 
>>>initialized anymore. We could add a small helper type arround the 
>>>allocator to do this value initialization per default. Should I do 
>>>so ?
>>
>>It's required to be value-initialized, so if your patch changes that
>>then it's a problem.
>>
>>Did we decide it's OK to do that for RB-trees? Did we actually discuss
>>that part of the r243379 changes?
>
>I remember a message pointing this issue but after the commit AFAIR. I 
>thought it was from Tim but I can't find it on the archive.
>
>What is the rational of this requirement ? I started working on a type 
>to do the allocator value initialization if there is no default 
>constructor but it seems quite complicated to do so. It is quite sad 
>that we can't fully benefit from this nice C++11 feature just because 
>of this requirement. If there is any initialization needed it doesn't 
>sound complicated to provide a default constructor.

The standard says that the default constructor is:

  vector() : vector(Allocator()) { }

That value-initializes the allocator. If the allocator type behaves
differently for value-init and default-init (e.g. it has data members
that are left uninitialized by default-init) then the difference
matters. If you change the code so it only does default-init of the
allocator then you will introduce an observable difference.

I don't see any requirement that a DefaultConstructible allocator
cannot leave members uninitialized, so that means the standard
requires default construction of vector<bool> to value-init the
allocator. Not default-init.

Here's an allocator that behaves differently if value-initialized or
default-initialized:

template<typename T>
struct Alloc {
  using value_type = T;
  Alloc() = default;
  template<typename U>
    Alloc(const Alloc<U>& a) : mem(a.mem) { }
  T* allocate(std::size_t n) {
    if (mem)
      throw 1;
    return std::allocator<T>().allocate(n);
  }
  void deallocate(T* p, std::size_t n) {
    std::allocator<T>().deallocate(p, n);
  }

  int mem;
};

template<typename T, typename U>
bool operator==(const Alloc<T>& t, const Alloc<U>& u)
{ return t.mem == u.mem; }

template<typename T, typename U>
bool operator!=(const Alloc<T>& t, const Alloc<U>& u)
{ return !(t == u); }



More information about the Libstdc++ mailing list