diff options
| author | 2017-04-03 12:01:31 -0700 | |
|---|---|---|
| committer | 2017-04-05 02:06:53 -0700 | |
| commit | a44b9f94aa53e69ccbfb86a35b13872b6faf8e52 (patch) | |
| tree | ab826763fd3e2267c4c31dedc68835766f0e4bce | |
| parent | f6b5b93708333bf7ac746fa75f78d4b2acdf89c2 (diff) | |
libpdx: Decay variant types to correctly handle cv-reference types.
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
| -rw-r--r-- | libs/vr/libpdx/private/pdx/rpc/variant.h | 41 | ||||
| -rw-r--r-- | libs/vr/libpdx/variant_tests.cpp | 18 |
2 files changed, 33 insertions, 26 deletions
diff --git a/libs/vr/libpdx/private/pdx/rpc/variant.h b/libs/vr/libpdx/private/pdx/rpc/variant.h index 09789e5a46..cb44a51b8d 100644 --- a/libs/vr/libpdx/private/pdx/rpc/variant.h +++ b/libs/vr/libpdx/private/pdx/rpc/variant.h @@ -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. diff --git a/libs/vr/libpdx/variant_tests.cpp b/libs/vr/libpdx/variant_tests.cpp index c30c055a7f..325f33f3c5 100644 --- a/libs/vr/libpdx/variant_tests.cpp +++ b/libs/vr/libpdx/variant_tests.cpp @@ -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) { |