Bug 1319673 - Make it compile error when instantiate a Variant with duplicate type. r?Waldo draft
authorJames Cheng <jacheng@mozilla.com>
Wed, 23 Nov 2016 15:12:50 +0800
changeset 443247 b8d0961904b8f474721983d7662dcfed414c8416
parent 442775 0ddfec7126ec503b54df9c4b7c3b988906f6c882
child 538001 0fb56f244a0d98a0e03ade46f1323022569fe433
push id36936
push userbmo:jacheng@mozilla.com
push dateThu, 24 Nov 2016 03:42:37 +0000
reviewersWaldo
bugs1319673
milestone53.0a1
Bug 1319673 - Make it compile error when instantiate a Variant with duplicate type. r?Waldo MozReview-Commit-ID: IKoLU2FjtzA
mfbt/Variant.h
--- a/mfbt/Variant.h
+++ b/mfbt/Variant.h
@@ -19,16 +19,44 @@
 
 namespace mozilla {
 
 template<typename... Ts>
 class Variant;
 
 namespace detail {
 
+template <typename...>
+struct FirstTypeIsInRest;
+
+template <typename First>
+struct FirstTypeIsInRest<First> : FalseType {};
+
+template <typename First, typename Second, typename... Rest>
+struct FirstTypeIsInRest<First, Second, Rest...>
+{
+  static constexpr bool value =
+    IsSame<First, Second>::value ||
+    FirstTypeIsInRest<First, Rest...>::value;
+};
+
+template <typename...>
+struct TypesAreDistinct;
+
+template <>
+struct TypesAreDistinct<> : TrueType { };
+
+template<typename First, typename... Rest>
+struct TypesAreDistinct<First, Rest...>
+{
+  static constexpr bool value =
+    !FirstTypeIsInRest<First, Rest...>::value &&
+    TypesAreDistinct<Rest...>::value;
+};
+
 // 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;
@@ -423,16 +451,17 @@ struct AsVariantTemporary
  *       Variant<const char*, UniquePtr<char[]>> string;
  *
  *       ...
  *     };
  */
 template<typename... Ts>
 class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS Variant
 {
+  static_assert(detail::TypesAreDistinct<Ts...>::value, "Variant with duplicate types is not supported");
   using Tag = typename detail::VariantTag<Ts...>::Type;
   using Impl = detail::VariantImplementation<Tag, 0, Ts...>;
   using RawData = AlignedStorage<detail::MaxSizeOf<Ts...>::size>;
 
   // Raw storage for the contained variant value.
   RawData raw;
 
   // Each type is given a unique tag value that lets us keep track of the