Issue #2166 - Part 4: Use alignas/alignof to define Variant's internal raw storage

Based on https://bugzilla.mozilla.org/show_bug.cgi?id=1338374
This commit is contained in:
FranklinDM committed 2023-03-17 20:29:20 +08:00
1 parent 88d2d5eef6
commit 53adec5e96
1 file changed
+19 -23
+19 -23
View File
@@ -8,9 +8,9 @@
#include <new>
#include <stdint.h>
#include "mozilla/Alignment.h"
#include "mozilla/Assertions.h"
#include "mozilla/Move.h"
#include "mozilla/TemplateLib.h"
#include "mozilla/TypeTraits.h"
#ifndef mozilla_Variant_h
@@ -23,22 +23,6 @@ class Variant;
namespace detail {
// MaxSizeOf computes the maximum sizeof(T) for each T in Ts.
template<typename T, typename... Ts>
struct MaxSizeOf
{
static const size_t size = sizeof(T) > MaxSizeOf<Ts...>::size
? sizeof(T)
: MaxSizeOf<Ts...>::size;
};
template<typename T>
struct MaxSizeOf<T>
{
static const size_t size = sizeof(T);
};
// The `IsVariant` helper is used in conjunction with static_assert and
// `mozilla::EnableIf` to catch passing non-variant types to `Variant::is<T>()`
// and friends at compile time, rather than at runtime. It ensures that the
@@ -429,23 +413,35 @@ struct AsVariantTemporary
*
* ...
* };
*
* Because Variant must be aligned suitable to hold any value stored within it,
* and because |alignas| requirements don't affect platform ABI with respect to
* how parameters are laid out in memory, Variant can't be used as the type of a
* function parameter. Pass Variant to functions by pointer or reference
* instead.
*/
template<typename... Ts>
class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS Variant
class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant
{
using Tag = typename detail::VariantTag<Ts...>::Type;
using Impl = detail::VariantImplementation<Tag, 0, Ts...>;
using RawData = AlignedStorage<detail::MaxSizeOf<Ts...>::size>;
static const size_t RawDataAlignment = tl::Max<alignof(Ts)...>::value;
static const size_t RawDataSize = tl::Max<sizeof(Ts)...>::value;
// Raw storage for the contained variant value.
RawData raw;
alignas(RawDataAlignment) unsigned char rawData[RawDataSize];
// Each type is given a unique tag value that lets us keep track of the
// contained variant value's type.
Tag tag;
void* ptr() {
return reinterpret_cast<void*>(&raw);
return rawData;
}
const void* ptr() const {
return rawData;
}
public:
@@ -552,7 +548,7 @@ public:
static_assert(detail::IsVariant<T, Ts...>::value,
"provided a type not found in this Variant's type list");
MOZ_ASSERT(is<T>());
return *reinterpret_cast<T*>(&raw);
return *static_cast<T*>(ptr());
}
/** Immutable const reference. */
@@ -561,7 +557,7 @@ public:
static_assert(detail::IsVariant<T, Ts...>::value,
"provided a type not found in this Variant's type list");
MOZ_ASSERT(is<T>());
return *reinterpret_cast<const T*>(&raw);
return *static_cast<const T*>(ptr());
}
/**