[PATCH] D48753: [libcxx] Use custom allocator's `construct` in C++03 when available.

Volodymyr Sapsai via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Jul 10 13:52:00 PDT 2018


vsapsai added a comment.

In https://reviews.llvm.org/D48753#1157695, @EricWF wrote:

> Why are we doing this?
>
> I can't find the language in the C++03 specification that requires us to call an allocators `construct` method if it's present.


The main reason I've ended up doing this because I thought correct `__has_construct` is required for https://reviews.llvm.org/D48342. It's not the case but I think this change is useful on its own.

I agree that C++03 specification doesn't require to call `construct` method. Requirement for containers 23.1[lib.container.requirements]p9 mentions that allocator should be used for memory allocation:

> Copy constructors for all container types defined in this clause copy an allocator argument from their respective first parameters. All other constructors for these container types take an Allocator& argument (20.1.6), an allocator whose value type is the same as the container’s value type. A copy of this argument is used for any memory allocation performed, by these constructors and by all member functions, during the lifetime of each container object. In all container types defined in this clause, the member get_allocator() returns a copy of the Allocator object used to construct the container.

And requirement for `allocate` 20.1.6[lib.allocator.requirements]table34 is not to construct objects:

> Memory is allocated for n objects of type T but objects are not constructed.[...]

Also for specific containers you can have a requirement to construct a container using the specified allocator, without explaining what exactly does it mean. E.g. 23.2.1.1[lib.deque.cons]p3:

>   explicit deque(size_type n, const T& value = T(),
>                  const Allocator & = Allocator ());
> 
> Effects: Constructs a deque with n copies of value , using the specified allocator.

So these requirements tell that at some point you need to construct an object and you have to use an allocator but they don't explicitly spell out that you have to call `construct`.

My main motivation for this change is that in C++11 and later we do call `construct` if it is available and it is required per 23.2.1[container.requirements.general]p3:

> For the components affected by this subclause that declare an allocator_type, objects stored in these components shall be constructed using the allocator_traits<allocator_type>::construct function and destroyed using the allocator_traits<allocator_type>::destroy function (20.7.8.2). These functions are called only for the container’s element type, not for internal types used by the container. [Note: This means, for example, that a node-based container might need to construct nodes containing aligned buffers and call construct to place the element into the buffer. — end note ]

I believe it is valuable and desirable to have the same behavior in different versions of C++ unless the semantic was explicitly changed. As far as I know, `allocator_traits` in C++11 wasn't supposed to be a breaking change.


https://reviews.llvm.org/D48753





More information about the cfe-commits mailing list