During the last two weeks, first we saw what are the language features deprecated or removed from C++26 then we did the same for library features. Life is not so straight and easy though. Sometimes, features cannot be removed after deprecation. There is an example for that in C++26 too. Which we are going to review today.
Undeprecate polymorphic_allocator::destroy
for C++26
C++23 deprecated the std::polymorphic_allocator::destroy
member function and instead of having it removed, it’s being added back to C++26 by P2875R4.
The short reason for the deprecation and a hoped removal was that the purposes of std::polymorphic_allocator::destroy
are satisfied by std::allocator_traits
too. But it turned out in practice, that some use-cases of polymorphic_allocator::destroy
don’t involve generic code that would use std::allocator_traits
.
But reading through the proposal unveils a more complex and interesting story. To understand what happened, we must travel back in time almost ten years.
There was already an issue filed for C++17 claiming that the implementations of the above-mentioned polymorphic_allocator::destroy
function and allocator_traits::destroy
function are equivalent. And that was true! That led to the deprecation of polymorphic_allocator::destroy
.
But in C++20, the contract of allocator_traits::destroy
changed! The implementation doesn’t produce the same code anymore as polymorphic_allocator::destroy
. It might call destroy_at
- in case the allocator doesn’t have a destroy
member function - which adds another level of indirection, it’s not noexcept
itself, the optimizer might be as efficient anymore in removing unwinding code.
And while, C++23 - despite the above contract change - finally deprecated polymorphic_allocator::destroy
, allocator_traits
must still dispatch calls to it. That’s because it will dispatch calls whenever the allocator’s have a destroy member function.
An additional and important problem with allocator_traits::destroy
is that it takes non-const&
to an allocator and it might not work correctly when you deal with hierarchies of allocators as the right type must be known at compile time. polymorphic_allocator
was designed to be type-agnostic through type deduction of the pointer.
If these problems wouldn’t be enough on their own, polymorphic_allocator::destroy
is a natural counterpart of polymorphic_allocator::construct
. It just feels right and easy to use the two together.
As a result, polymorphic_allocator::destroy
is undeprecated and kept as part of the standard library.
Conclusion
In this article, we saw that the deprecation of functionality in C++ doesn’t necessarily mean a guaranteed removal. Sometimes, intentions and contracts change or people understand that deprecation is simply not the right direction. In C++26, as far as I found, there is one (library) feature undeprecated, and that’s polymorphic_allocator::destroy
. For further analysis, feel free to read P2875R4.
Connect deeper
If you liked this article, please
- hit on the like button,
- subscribe to my newsletter
