Hello Ai,
On Nov 2, 2:16 pm, Ai Azuma<
ai.az...@gmail.com> wrote:
> `std::allocator_traits<std::allocator<T>>::propagate_on_container_move_assignment'
> (hereafter, abbreviated as POCMA) is defined as `std::false_type',
> and it unduly imposes a burden on users.
>
> `std::allocator_traits' class template is not explicitly specialized
> for the default allocator (`std::allocator' class template),
> and `std::allocator' does not have the nested typedef named
> `propagate_on_container_move_assignment'.
> Thus, POCMA is specified to be `std::false_type'.
>
> However, in my humble opinion, nothing seems to prevent POCMA from
> being defined as `std::true_type'.
> No object of type `std::allocator<T>' has any object-specific state,
> and all objects always compare equal each other.
> Therefore, the move assignment operator of `std::allocator'
> with a "do-nothing" implementation would meet the requirement for
> POCMA to become `std::true_type'.
> Actually, the implicitly defined copy assignment operator can also
> function as the move one.
The POCMA trait has little to do with the movability of the allocator
(most allocators are movable whether POCMA is true or false) and
everything to do with whether a container that uses that allocator
should re-assign its allocator on move assignment. For most stateful
allocators, the answer is "no" because there is a well-established
invariant that the allocator used at construction never changes
throughout the lifetime of the container. Setting POCMA to true
breaks this invariant, which is why it is not the default.
For stateless allocators, such as std::allocator, it should not matter
semantically whether POCMA is true or false. All allocators of that
type are equal and the containers are explicitly required to perform
an O(1) move assignment (actually O(N) because of destructor calls)
when the allocators compare equal, regardless of the value of POCMA.
> This means that a practical problem may arise in a specific context.> From (23.2.1/14) and (Table 99), I conclude that the value type of
>
> allocator-aware containers
> with the default allocator type is required to be MoveInsertable and
> MoveAssignable
> when invoking the move assignment operator because POCMA is specified
> as `std::false_type'.
> However, I'm not convinced of this at all because it is at variance
> with the model in my mind.
> Such requirements are essentially unnecessary in the move assignment
> operator
> because allocator-aware containers with the default allocator type
> only have to
> swap the ownership of their resources in the move assignment operator.
> I think that the problem here boils down to the wrong specification of
> POCMA.
OK, I see your point here. We overlooked an additional requirement
imposed by having POCMA be false. This is a real issue -- and
possibly could be considered a defect.
> In addition, suppose that I am the author of an allocator-aware
> container.
> How can I implement the move assignment operator of that container as
> efficient as possible?
> Should I specialize the move assignment operator solely for the
> default allocator type?
Yes, as a work-around, if you don't want to impose the extra
requirement. Consider, however, your intended audience: will your
users really expect move-assignment to work quickly for elements that
are not MoveInsertable and MoveAssignable? Remember that
MoveInsertable and MoveAssignable do not imply speed -- move
operations can be implemented as copy operations (and will default as
such if not provided explicitly. Of course, these operations will not
actually be called when performing a move assignment of your
container, but is it likely that they will be absent?
> It is stupid.
Please don't say that. It hurts our feelings :-)
> If POCMA is defined as `std::true_type',
> compile-time dispatch on the value of
> `propagate_on_container_move_assignment'
> would be enough to implement an efficient move assignment
> and subsume the case of the default allocator type.
True, but you should also be checking for equal allocators, which will
also subsume the case of the default allocator type. The efficiency
argument doesn't change, which is why we did not put a lot of thought
into whether the default allocator should have POCMA set or not. (We
overlooked the requirements issue and did nothing on the theory of
minimal change.)
> I would like to request either of the following changes;
>
> i) adding the nested typedef like
> `typedef std::true_type propagate_on_container_move_assignment;'
> in the definition of std::allocator class template
>
> ii) adding the explicit partial specialization of
> `std::allocator_traits' class template
> for `std::allocator' class template, in which POCMA is specified
> as `std::true_type'.
This is a reasonable request. I think that (i) is the simpler
approach. Please do me a favor and write this up as an issue having
the following parts:
1. Affected section of the standard
2. Description of the problem (focus on the unneeded requirements on
client code)
3. Proposed resolution (you can pick one or both)
Here is a link to an existing issue that you can model yours after
(but don't worry about the details of formatting):
http://lwg.github.com/issues/lwg-active.html#2052
Either post this issue here or email it to me directly. I will submit
it to the active issues list.
Thanks,
-Pablo