// 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& v) : value(v) { 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