Blog 2025 03 26 C++26: an undeprecated feature
Post
Cancel

C++26: an undeprecated feature

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

This post is licensed under CC BY 4.0 by the author.