// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #if 0 #pragma qt_sync_skip_header_check #pragma qt_sync_stop_processing #endif #ifndef QFUNCTIONALTOOLS_IMPL_H #define QFUNCTIONALTOOLS_IMPL_H #include #include #include QT_BEGIN_NAMESPACE /*! \class QtPrivate::CompactStorage \internal CompactStorage is a small utility class that stores an object in the most space-efficient way possible. If the stored type is empty and not marked as \c final, CompactStorage inherits from it directly, allowing the compiler to apply the Empty Base Optimization (EBO). Otherwise, the object is stored as a regular data member. This class is typically used as a private base class for utility types that need to optionally carry extra data without increasing their size. The stored object can be accessed through the \c object() accessor, which returns the contained object in any const/reference combination. Example 1: // FileHandle carries a lightweight context describing // the underlying OS resource. struct Context { int fd = -1; bool isTemporary = false; }; struct FileHandle : private QtPrivate::CompactStorage { using Storage = QtPrivate::CompactStorage; FileHandle(int descriptor, bool temp) : Storage(Context{descriptor, temp}) {} void open(int descriptor, bool temp) noexcept { object().fd = descriptor; object().isTemporary = temp; } void close() noexcept { if (object().isTemporary) ::close(object().fd); } }; Example 2: // When the stored type is empty, EBO removes any overhead. struct EmptyContext {}; struct LightweightHandle : private QtPrivate::CompactStorage { using Storage = QtPrivate::CompactStorage; int handle = -1; void reset(int h) noexcept { handle = h; } }; static_assert(sizeof(LightweightHandle) == sizeof(int)); */ namespace QtPrivate { namespace detail { #define FOR_EACH_CVREF(op) \ op(&) \ op(const &) \ op(&&) \ op(const &&) \ /* end */ template struct StorageByValue { Object o; #define MAKE_GETTER(cvref) \ constexpr Object cvref object() cvref noexcept \ { return static_cast(o); } FOR_EACH_CVREF(MAKE_GETTER) #undef MAKE_GETTER }; template struct StorageEmptyBaseClassOptimization : Object { StorageEmptyBaseClassOptimization() = default; StorageEmptyBaseClassOptimization(Object &&o) : Object(std::move(o)) {} StorageEmptyBaseClassOptimization(const Object &o) : Object(o) {} #define MAKE_GETTER(cvref) \ constexpr Object cvref object() cvref noexcept \ { return static_cast(*this); } FOR_EACH_CVREF(MAKE_GETTER) #undef MAKE_GETTER }; } // namespace detail template using CompactStorage = typename std::conditional_t< std::conjunction_v< std::is_empty, std::negation> >, detail::StorageEmptyBaseClassOptimization, detail::StorageByValue >; } // namespace QtPrivate #undef FOR_EACH_CVREF QT_END_NAMESPACE #endif // QFUNCTIONALTOOLS_IMPL_H