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:
1 file changed
+19
-23
+19
-23
@@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user