/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Copyright 2011-2019 Danny Robson */ #pragma once #include "types/description.hpp" #include #include #include #include #include /////////////////////////////////////////////////////////////////////////////// // analogue of std::data for use until we get proper c++17 support namespace cruft { template auto data (T &t) { return t.data (); } //------------------------------------------------------------------------- template auto data (const T &t) { return t.data (); } //------------------------------------------------------------------------- template constexpr T* data (T (&t)[N]) { return &t[0]; } //------------------------------------------------------------------------- template constexpr const T* data (const T (&t)[N]) { return &t[0]; } } /////////////////////////////////////////////////////////////////////////////// /// returns the first argument from a parameter pack which can evaluate to true. template T first (T a) { if (a) return a; throw std::logic_error ("no valid object"); } //----------------------------------------------------------------------------- template T first (T a, Args&& ...b) { if (a) return a; return first (std::forward(b)...); } namespace cruft { /////////////////////////////////////////////////////////////////////////// /// A tag type that is used when type_tag dispatching descriptions that /// claim to be enums. The underlying type can be recovered from the 'type' /// typedef of this class. template struct unknown_enum_tag { using type = UnderlyingT; }; //------------------------------------------------------------------------- template struct is_unknown_enum_tag : public std::false_type {}; //------------------------------------------------------------------------- template < typename UnderlyingT > struct is_unknown_enum_tag< unknown_enum_tag >: public std::true_type {}; //------------------------------------------------------------------------- template constexpr auto is_unknown_enum_tag_v = is_unknown_enum_tag::value; /////////////////////////////////////////////////////////////////////////// /// represents a type as a POD struct (but is statically recoverable via /// the 'type' member). template struct type_tag { typedef T type; }; //------------------------------------------------------------------------- template struct type_tag> { cruft::types::description desc; }; ///------------------------------------------------------------------------ /// count the number of parameters we are given. useful for counting /// arguments in variadic macros (ie, sizeof... (__VA_ARGS__)) template constexpr size_t param_count (const T... t) { // prevent unused variable warnings by never forwarding recursively // ideally we'd use void casting, but it doesn't work for parameter // packs if (false) return param_count (t...); return sizeof... (t); } /////////////////////////////////////////////////////////////////////////// /// A trait that tests for the presence of a 'native' member function. /// /// Not terrifically useful by itself, but it is use reasonably frequently /// in various library wrappers that we maintain (to return the underlying /// native objects). template > struct has_native : public std::false_type {}; //------------------------------------------------------------------------- template < typename ValueT > struct has_native< ValueT, std::void_t< decltype(std::declval ().native ()) > > : public std::true_type {}; //------------------------------------------------------------------------- template constexpr auto has_native_v = has_native::value; /////////////////////////////////////////////////////////////////////////// /// Unconditionally ignore the first argument, and store the second as `type`. /// /// This aids converting parameter packs types. eg, converting all types /// to strings by using an expression of the form: /// `convert_t...` template struct convert { using type = ResultT; }; template using convert_t = typename convert::type; }