Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkAnySubclass.h
Go to the documentation of this file.
1/*
2 * Copyright 2023 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkAnySubclass_DEFINED
9#define SkAnySubclass_DEFINED
10
12
13#include <cstddef>
14#include <new>
15#include <type_traits> // IWYU pragma: keep
16#include <utility>
17
18/**
19 * Stores any subclass `T` of `Base`, where sizeof(T) <= `Size`, without using the heap.
20 * Doesn't need advance knowledge of T, so it's particularly suited to platform or backend
21 * implementations of a generic interface, where the set of possible subclasses is finite and
22 * known, but can't be made available at compile-time.
23 */
24template <typename Base, size_t Size>
26public:
27 SkAnySubclass() = default;
29 this->reset();
30 }
31
32 SkAnySubclass(const SkAnySubclass&) = delete;
36
37 template <typename T, typename... Args>
38 void emplace(Args&&... args) {
39 static_assert(std::is_base_of_v<Base, T>);
40 static_assert(sizeof(T) <= Size);
41 // We're going to clean up our stored object by calling ~Base:
42 static_assert(std::has_virtual_destructor_v<Base> || std::is_trivially_destructible_v<T>);
43 SkASSERT(!fValid);
44 new (fData) T(std::forward<Args>(args)...);
45 fValid = true;
46 }
47
48 void reset() {
49 if (fValid) {
50 this->get()->~Base();
51 }
52 fValid = false;
53 }
54
55 const Base* get() const {
56 SkASSERT(fValid);
57 return std::launder(reinterpret_cast<const Base*>(fData));
58 }
59
60 Base* get() {
61 SkASSERT(fValid);
62 return std::launder(reinterpret_cast<Base*>(fData));
63 }
64
65 Base* operator->() { return this->get(); }
66 const Base* operator->() const { return this->get(); }
67
68private:
69 alignas(8) std::byte fData[Size];
70 bool fValid = false;
71};
72
73#endif // SkAnySubclass_DEFINED
#define SkASSERT(cond)
Definition SkAssert.h:116
SkAnySubclass & operator=(SkAnySubclass &&)=delete
Base * operator->()
const Base * get() const
SkAnySubclass()=default
SkAnySubclass & operator=(const SkAnySubclass &)=delete
void emplace(Args &&... args)
SkAnySubclass(const SkAnySubclass &)=delete
SkAnySubclass(SkAnySubclass &&)=delete
const Base * operator->() const
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
#define T