OSDN Git Service

libpdx: Decay variant types to correctly handle cv-reference types.
authorCorey Tabaka <eieio@google.com>
Mon, 3 Apr 2017 19:01:31 +0000 (12:01 -0700)
committerCorey Tabaka <eieio@google.com>
Wed, 5 Apr 2017 09:06:53 +0000 (02:06 -0700)
Decay the types used internally for storage in Variant and update
type matching logic to handle the decayed types.

Bug: 36401174
Test: build; pdx_tests passes.
Change-Id: I93c68cce47d6f7d195b901afe3e63685befc08fe

libs/vr/libpdx/private/pdx/rpc/variant.h
libs/vr/libpdx/variant_tests.cpp

index 09789e5..cb44a51 100644 (file)
@@ -39,15 +39,11 @@ using EnableIfNotConstructible =
 template <typename... Types>
 struct HasType : std::false_type {};
 template <typename T, typename U>
-struct HasType<T, U> : std::is_same<T, U> {};
+struct HasType<T, U> : std::is_same<std::decay_t<T>, std::decay_t<U>> {};
 template <typename T, typename First, typename... Rest>
 struct HasType<T, First, Rest...>
-    : std::integral_constant<
-          bool, std::is_same<T, First>::value || HasType<T, Rest...>::value> {};
-
-template <typename T, typename... Types>
-using HasTypeIgnoreRef =
-    HasType<typename std::remove_reference<T>::type, Types...>;
+    : std::integral_constant<bool, HasType<T, First>::value ||
+                                       HasType<T, Rest...>::value> {};
 
 // Defines set operations on a set of Types...
 template <typename... Types>
@@ -59,8 +55,8 @@ struct Set {
   struct IsSubset<T> : HasType<T, Types...> {};
   template <typename First, typename... Rest>
   struct IsSubset<First, Rest...>
-      : std::integral_constant<
-            bool, IsSubset<First>::value && IsSubset<Rest...>::value> {};
+      : std::integral_constant<bool, IsSubset<First>::value &&
+                                         IsSubset<Rest...>::value> {};
 };
 
 // Determines the number of elements of Types... that are constructible from
@@ -80,18 +76,18 @@ struct ConstructibleCount<From, First, Rest...>
 // Enable if T is an element of Types...
 template <typename R, typename T, typename... Types>
 using EnableIfElement =
-    typename std::enable_if<HasTypeIgnoreRef<T, Types...>::value, R>::type;
+    typename std::enable_if<HasType<T, Types...>::value, R>::type;
 // Enable if T is not an element of Types...
 template <typename R, typename T, typename... Types>
 using EnableIfNotElement =
-    typename std::enable_if<!HasTypeIgnoreRef<T, Types...>::value, R>::type;
+    typename std::enable_if<!HasType<T, Types...>::value, R>::type;
 
 // Enable if T is convertible to an element of Types... T is considered
 // convertible IIF a single element of Types... is assignable from T and T is
 // not a direct element of Types...
 template <typename R, typename T, typename... Types>
 using EnableIfConvertible =
-    typename std::enable_if<!HasTypeIgnoreRef<T, Types...>::value &&
+    typename std::enable_if<!HasType<T, Types...>::value &&
                                 ConstructibleCount<T, Types...>::value == 1,
                             R>::type;
 
@@ -102,7 +98,7 @@ using EnableIfConvertible =
 // in conversion.
 template <typename R, typename T, typename... Types>
 using EnableIfAssignable =
-    typename std::enable_if<HasTypeIgnoreRef<T, Types...>::value ||
+    typename std::enable_if<HasType<T, Types...>::value ||
                                 ConstructibleCount<T, Types...>::value == 1,
                             R>::type;
 
@@ -362,15 +358,13 @@ class Variant {
   template <typename T>
   using TypeTag = detail::TypeTag<T>;
   template <typename T>
-  using TypeTagIgnoreRef = TypeTag<typename std::remove_reference<T>::type>;
+  using DecayedTypeTag = TypeTag<std::decay_t<T>>;
   template <std::size_t I>
   using TypeForIndex = detail::TypeForIndex<I, Types...>;
   template <std::size_t I>
   using TypeTagForIndex = detail::TypeTagForIndex<I, Types...>;
   template <typename T>
   using HasType = detail::HasType<T, Types...>;
-  template <typename T>
-  using HasTypeIgnoreRef = detail::HasTypeIgnoreRef<T, Types...>;
   template <typename R, typename T>
   using EnableIfElement = detail::EnableIfElement<R, T, Types...>;
   template <typename R, typename T>
@@ -381,13 +375,12 @@ class Variant {
   struct Direct {};
   struct Convert {};
   template <typename T>
-  using SelectConstructor =
-      detail::Select<HasTypeIgnoreRef<T>::value, Direct, Convert>;
+  using SelectConstructor = detail::Select<HasType<T>::value, Direct, Convert>;
 
   // Constructs by type tag when T is an direct element of Types...
   template <typename T>
   explicit Variant(T&& value, Direct)
-      : value_(0, &index_, TypeTagIgnoreRef<T>{}, std::forward<T>(value)) {}
+      : value_(0, &index_, DecayedTypeTag<T>{}, std::forward<T>(value)) {}
   // Conversion constructor when T is not a direct element of Types...
   template <typename T>
   explicit Variant(T&& value, Convert)
@@ -421,7 +414,7 @@ class Variant {
   // convertible to multiple elements of Types.
   template <typename T>
   EnableIfElement<Variant&, T> operator=(T&& value) {
-    Assign(TypeTagIgnoreRef<T>{}, std::forward<T>(value));
+    Assign(DecayedTypeTag<T>{}, std::forward<T>(value));
     return *this;
   }
 
@@ -487,7 +480,7 @@ class Variant {
   template <typename T>
   constexpr std::int32_t index_of() const {
     static_assert(HasType<T>::value, "T is not an element type of Variant.");
-    return value_.template index(TypeTag<T>{});
+    return value_.template index(DecayedTypeTag<T>{});
   }
 
   // Returns the index of the active type. If the Variant is empty -1 is
@@ -509,14 +502,14 @@ class Variant {
   template <typename T>
   T* get() {
     if (is<T>())
-      return &value_.template get(TypeTag<T>{});
+      return &value_.template get(DecayedTypeTag<T>{});
     else
       return nullptr;
   }
   template <typename T>
   const T* get() const {
     if (is<T>())
-      return &value_.template get(TypeTag<T>{});
+      return &value_.template get(DecayedTypeTag<T>{});
     else
       return nullptr;
   }
@@ -537,7 +530,7 @@ class Variant {
 
  private:
   std::int32_t index_ = kEmptyIndex;
-  detail::Union<Types...> value_;
+  detail::Union<std::decay_t<Types>...> value_;
 
   // Constructs an element from the given arguments and sets the Variant to the
   // resulting type.
index c30c055..325f33f 100644 (file)
@@ -368,6 +368,13 @@ TEST(Variant, Constructor) {
   }
 
   {
+    TestType<int> i(1);
+    Variant<int, bool, float> v(i.get());
+    ASSERT_TRUE(v.is<int>());
+    EXPECT_EQ(1, std::get<int>(v));
+  }
+
+  {
     TestType<bool> b(true);
     Variant<int, bool, float> v(b.take());
     ASSERT_TRUE(v.is<bool>());
@@ -375,6 +382,13 @@ TEST(Variant, Constructor) {
   }
 
   {
+    TestType<bool> b(true);
+    Variant<int, bool, float> v(b.get());
+    ASSERT_TRUE(v.is<bool>());
+    EXPECT_EQ(true, std::get<bool>(v));
+  }
+
+  {
     Variant<const char*> c("test");
     Variant<std::string> s(c);
     ASSERT_TRUE(s.is<std::string>());
@@ -1060,8 +1074,8 @@ TEST(Variant, HasType) {
   EXPECT_FALSE((detail::HasType<char, int, float, bool>::value));
   EXPECT_FALSE(detail::HasType<>::value);
 
-  EXPECT_TRUE((detail::HasTypeIgnoreRef<int&, int, float, bool>::value));
-  EXPECT_FALSE((detail::HasTypeIgnoreRef<char&, int, float, bool>::value));
+  EXPECT_TRUE((detail::HasType<int&, int, float, bool>::value));
+  EXPECT_FALSE((detail::HasType<char&, int, float, bool>::value));
 }
 
 TEST(Variant, Set) {