Reading what is the new feature in c++20 [[no_unique_address]]? , I have been thinking about alternatives to Empty Base Optimisation prior to C++20's [[no_unique_address]]. One thing came to mind, since stateless deleters and allocators by definition do not store any state, is it allowed to instead construct them on demand whenever needed?
template <typename T, typename Deleter> struct not_pair { T first; }; template <typename T, typename Deleter> using maybe_pair = std::conditional< std::is_empty<Deleter>::value, not_pair<T*, Deleter>, std::pair<T*, Deleter> >::type; template <typename T, typename Deleter> void invoke_maybe_pair(std::pair<T*, Deleter>& storage) { storage.second(storage.first); } template <typename T, typename Deleter> void invoke_maybe_pair(std::not_pair<T*, Deleter>& storage) { Deleter{}(storage.first); } template <typename T, typename Deleter> class unique_ptr { maybe_pair<T*, Deleter> storage; public: ~unique_ptr() { if (storage.first) { invoke_deleter(storage); } } ... }; Would such an implementation be allowed by the standard, or are classes taking deleters and allocators (smart pointers, collections, etc.) required to call their constructors (including move and copy where applicable) and destructor when expected? We could explicitly only limit it to trivial classes to avoid any otherwise observable side effects.
There is no practical reason to prefer this over EBO outside of supporting final deleters, I am just testing the letter of the standard.