blob: 4b1108f19114eaa94acfc1c3ef9a41f4c94549bd [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef LIB_FIT_INCLUDE_LIB_FIT_INLINE_ANY_H_
#define LIB_FIT_INCLUDE_LIB_FIT_INLINE_ANY_H_
#include <lib/stdcompat/type_traits.h>
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <functional>
#include <type_traits>
#include <utility>
#include "inline_any_internal.h"
#include "traits.h"
#include "utility_internal.h"
namespace fit {
// |inline_any| is a polymorphic container used to implement type erasure.
//
// |inline_any| is movable and copyable, and any type placed inside of it must
// also be movable and copyable.
//
// A default constructed |inline_any| does not hold a value (it is empty).
// Moving from an |inline_any| resets it back to the empty state.
//
// It is similar to |std::any|, with the following notable differences:
// * The contained object must implement (i.e. be a subclass of) |Interface|.
// * It will never heap allocate.
//
// This avoids additional memory allocations while using a virtual interface.
// |Reserve| must be larger than the sizes of all of the individual |Interface|
// implementations.
template <typename Interface, size_t Reserve = sizeof(Interface), size_t Align = alignof(Interface)>
class inline_any : public internal::inline_any_impl<Interface, Reserve, Align,
internal::inline_any_is_pinned::no> {
public:
using base =
internal::inline_any_impl<Interface, Reserve, Align, internal::inline_any_is_pinned::no>;
using base::base;
using base::operator=;
inline_any(const inline_any&) = default;
inline_any& operator=(const inline_any&) = default;
inline_any(inline_any&&) noexcept = default;
inline_any& operator=(inline_any&&) noexcept = default;
};
// |pinned_inline_any| is a polymorphic container used to implement type
// erasure. Unlike |inline_any|, |pinned_inline_any| cannot be moved or copied,
// but it can hold non-movable types, such as types that lend out internal
// pointers. See also |inline_any|.
//
// Since |pinned_inline_any| contents cannot be moved or copy assigned, there
// are only two ways to initialize a |pinned_inline_any|:
// - At construction time: pass |cpp17::in_place_type_t<T>| to select the
// in-place constructor.
// - After default construction: via |emplace<T>|, whose arguments are forwarded
// to the |T| constructor.
template <typename Interface, size_t Reserve = sizeof(Interface), size_t Align = alignof(Interface)>
class pinned_inline_any : public internal::inline_any_impl<Interface, Reserve, Align,
internal::inline_any_is_pinned::yes> {
public:
using base =
internal::inline_any_impl<Interface, Reserve, Align, internal::inline_any_is_pinned::yes>;
using base::base;
using base::operator=;
pinned_inline_any(const pinned_inline_any&) = delete;
pinned_inline_any& operator=(const pinned_inline_any&) = delete;
pinned_inline_any(pinned_inline_any&&) = delete;
pinned_inline_any& operator=(pinned_inline_any&&) = delete;
};
} // namespace fit
#endif // LIB_FIT_INCLUDE_LIB_FIT_INLINE_ANY_H_