This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


On 27/05/2017 13:14, Jonathan Wakely wrote:
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.

Sure but like freedom which stop where start others' freedom so does those requirements :-). Because the Standard says that an allocator will be value-init when there is no default-init it makes usage of the C++11 default constructor more complicated.

But as it is unavoidable here is a type I tried to work on to keep current implementations as long as we inherit from __alloc_value_initializer.

I don't like it myself but I propose just in case you are interested.

Otherwise I am also going to rework my patch to keep this initialization.

François

diff --git a/libstdc++-v3/include/bits/allocator.h b/libstdc++-v3/include/bits/allocator.h
index 2081386..9e8afed 100644
--- a/libstdc++-v3/include/bits/allocator.h
+++ b/libstdc++-v3/include/bits/allocator.h
@@ -241,6 +241,52 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     };
 #endif
 
+  template<typename _Alloc, bool
+	   = !__is_empty(_Alloc) && __is_trivial(_Alloc)>
+    struct __alloc_value_initializer;
+
+  template<typename _Alloc>
+    struct __alloc_value_initializer<_Alloc, true> : public _Alloc
+    {
+      // Explicit value initialization.
+      __alloc_value_initializer() _GLIBCXX_USE_NOEXCEPT
+	: _Alloc()
+      { }
+
+      __alloc_value_initializer(const _Alloc& __other)
+	_GLIBCXX_NOEXCEPT_IF( noexcept(_Alloc(__other)) )
+	: _Alloc(__other)
+      { }
+
+#if __cplusplus >= 201103L
+      __alloc_value_initializer(_Alloc&& __other)
+	noexcept( noexcept(_Alloc(std::move(__other))) )
+	: _Alloc(std::move(__other))
+      { }
+#endif
+    };
+
+  template<typename _Alloc>
+    struct __alloc_value_initializer<_Alloc, false> : public _Alloc
+    {
+#if __cplusplus >= 201103L
+      __alloc_value_initializer() = default;
+
+      __alloc_value_initializer(_Alloc&& __other)
+	noexcept( noexcept(_Alloc(std::move(__other))) )
+	: _Alloc(std::move(__other))
+      { }
+#else
+      __alloc_value_initializer() throw()
+      { }
+#endif
+
+      __alloc_value_initializer(const _Alloc& __other)
+	_GLIBCXX_NOEXCEPT_IF(noexcept(_Alloc(__other)))
+	: _Alloc(__other)
+      { }
+    };
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]