| // Copyright 2019 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #ifndef dap_variant_h |
| #define dap_variant_h |
| |
| #include "any.h" |
| |
| namespace dap { |
| |
| // internal functionality |
| namespace detail { |
| template <typename T, typename...> |
| struct TypeIsIn { |
| static constexpr bool value = false; |
| }; |
| |
| template <typename T, typename List0, typename... ListN> |
| struct TypeIsIn<T, List0, ListN...> { |
| static constexpr bool value = |
| std::is_same<T, List0>::value || TypeIsIn<T, ListN...>::value; |
| }; |
| } // namespace detail |
| |
| // variant represents a type-safe union of DAP types. |
| // variant can hold a value of any of the template argument types. |
| // variant defaults to a default-constructed T0. |
| template <typename T0, typename... Types> |
| class variant { |
| public: |
| // constructors |
| inline variant(); |
| template <typename T> |
| inline variant(const T& val); |
| |
| // assignment |
| template <typename T> |
| inline variant& operator=(const T& val); |
| |
| // get() returns the contained value of the type T. |
| // If the any does not contain a value of type T, then get() will assert. |
| template <typename T> |
| inline T& get() const; |
| |
| // is() returns true iff the contained value is of type T. |
| template <typename T> |
| inline bool is() const; |
| |
| // accepts() returns true iff the variant accepts values of type T. |
| template <typename T> |
| static constexpr bool accepts(); |
| |
| private: |
| friend class Serializer; |
| friend class Deserializer; |
| any value; |
| }; |
| |
| template <typename T0, typename... Types> |
| variant<T0, Types...>::variant() : value(T0()) {} |
| |
| template <typename T0, typename... Types> |
| template <typename T> |
| variant<T0, Types...>::variant(const T& value) : value(value) { |
| static_assert(accepts<T>(), "variant does not accept template type T"); |
| } |
| |
| template <typename T0, typename... Types> |
| template <typename T> |
| variant<T0, Types...>& variant<T0, Types...>::operator=(const T& v) { |
| static_assert(accepts<T>(), "variant does not accept template type T"); |
| value = v; |
| return *this; |
| } |
| |
| template <typename T0, typename... Types> |
| template <typename T> |
| T& variant<T0, Types...>::get() const { |
| static_assert(accepts<T>(), "variant does not accept template type T"); |
| return value.get<T>(); |
| } |
| |
| template <typename T0, typename... Types> |
| template <typename T> |
| bool variant<T0, Types...>::is() const { |
| return value.is<T>(); |
| } |
| |
| template <typename T0, typename... Types> |
| template <typename T> |
| constexpr bool variant<T0, Types...>::accepts() { |
| return detail::TypeIsIn<T, T0, Types...>::value; |
| } |
| |
| } // namespace dap |
| |
| #endif // dap_variant_h |