4

According to current Standard (20.7.9), std::allocator has a member propagate_on_container_move_assignment which is set to true_type:

template class allocator
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
template struct rebind { typedef allocator other; };
typedef true_type propagate_on_container_move_assignment;
typedef true_type is_always_equal;
[...]

std::allocator has no data members and always compared as equal with any other std::allocator. Is there any reason to move those default allocators on move assignment?

1
  • 2
    This isn't C++11. is_always_equal was added post-C++14. Commented Feb 5, 2017 at 12:27

1 Answer 1

7

I'm answering relative to C++11, as you indicated in the tag:

If the trait weren't true, then assignment operations would need to perform a runtime check on whether the allocators are equal. Yes, of course the allocators would always be equal, but the code doesn't know that and would still have to perform the check, and thus you cannot offer a noexcept guarantee. With POCMA = true, you can statically know that you will steal resources and thus won't throw.

C++14 made the std::allocator have POCMA = true (in LWG2103). It was false in C++11.

C++17 introduced the new trait is_always_equal (in N4258) to allow a non-throwing exception specification for operations even when POCMA is false.

(I think it's fair to say that the design of allocators has never quite been completed, and to this day nobody is entirely sure how they are supposed to work.)

Sign up to request clarification or add additional context in comments.

6 Comments

The reason it was made POCMA is that it affects the requirements on the container elements, not just the exception specification. Without POCMA (or is_always_equal) you have to allow for the possibility of element-wise move.
I have a corollary question: why not defining a constexpr operator==? why this pocma necessary. I would imagine that if I were using such an operator as the condition of an if statement, dead code elimination would produce the same code as if I were using tag dispatch with POCMA no?
@Oliv A constexpr operator== would be possible, and is discussed in lwg 2108. To use that you'd need to try the equality comparison in a SFINAE context to see if it's a valid constant expression (because not all allocators would have a constexpr operator==). Tag dispatching is simpler. Dead code elimination still works for a non-constexpr operator== that always returns true. In practice it doesn't make much difference.
@JonathanWakely Thank you for the answer. I'd like to share some peace of experiment. I am getting used to program with concept TS since a while and using it, I discovered that most of my design decision where motivated by the difficulty I had to use and maintain code using SFINAE. It seems to be the case in the STL. I have read the standard N4618: "is_always_equal:true_type only if the expression a1 == a2 is guaranteed to be true for any two...". This is an unnecessary constraint propagation to a programmer of an allocator. This requirement can be hard coded. Why not hard coding it?
@Oliv I don't understand the question (defining using is_always_equal = true_type; for an allocator does hardcode it), but I don't think it belongs in a comment here. StackOverflow comments are not for discussion. Stick to the topic of this answer. Ask a new question if you have questions.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.