blob: e7f69025e5daf7e51737837d23bf192b51eed476 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
#pragma once
#include <new>
#include <type_traits>
#include "WAVM/Inline/BasicTypes.h"
namespace WAVM {
// A type that holds an optional instance of another type. The lifetime of the contained
// instance is defined by the user of this type, and the user is responsible for calling
// construct and destruct.
template<typename Contents,
bool hasTrivialDestructor = std::is_trivially_destructible<Contents>::value>
struct OptionalStorage
{
template<typename... Args> void construct(Args&&... args)
{
new(&contents) Contents(std::forward<Args>(args)...);
}
void destruct() { get().~Contents(); }
#if __cplusplus >= 201703L
Contents& get() { return *std::launder(reinterpret_cast<Contents*>(&contents)); }
const Contents& get() const
{
return *std::launder(reinterpret_cast<const Contents*>(&contents));
}
#else
Contents& get() { return *reinterpret_cast<Contents*>(&contents); }
const Contents& get() const { return *reinterpret_cast<const Contents*>(&contents); }
#endif
private:
typename std::aligned_storage<sizeof(Contents), alignof(Contents)>::type contents;
};
// Partial specialization for types with trivial destructors.
template<typename Contents> struct OptionalStorage<Contents, true>
{
template<typename... Args> void construct(Args&&... args)
{
new(&contents) Contents(std::forward<Args>(args)...);
}
void destruct() {}
#if __cplusplus >= 201703L
Contents& get() { return *std::launder(reinterpret_cast<Contents*>(&contents)); }
const Contents& get() const
{
return *std::launder(reinterpret_cast<const Contents*>(&contents));
}
#else
Contents& get() { return *reinterpret_cast<Contents*>(&contents); }
const Contents& get() const { return *reinterpret_cast<const Contents*>(&contents); }
#endif
private:
typename std::aligned_storage<sizeof(Contents), alignof(Contents)>::type contents;
};
namespace OptionalStorageAssertions {
struct NonTrivialType
{
NonTrivialType();
};
static_assert(std::is_trivial<OptionalStorage<NonTrivialType>>::value,
"OptionalStorage<NonTrivialType> is non-trivial");
};
}
|