/* * 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 * * http://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. * * Copyright 2012-2017 Danny Robson */ #ifndef CRUFT_UTIL_TYPES_TRAITS_HPP #define CRUFT_UTIL_TYPES_TRAITS_HPP #include #include /////////////////////////////////////////////////////////////////////////////// /// applies a series of type-modifiers to a provided type. /// /// modifiers are applied in the order they are provided. /// /// use without any modifiers results in the identity modifier. namespace util { //------------------------------------------------------------------------- template class ...ModifierT> struct chain; //------------------------------------------------------------------------- template struct chain { using type = TypeT; }; //------------------------------------------------------------------------- template < typename TypeT, template class HeadT, template class ...TailT > struct chain : public chain< typename HeadT::type, TailT... > { }; //------------------------------------------------------------------------- template class ...Args> using chain_t = typename chain::type; } /////////////////////////////////////////////////////////////////////////////// template struct is_dereferencable : std::false_type { }; template struct is_dereferencable : std::true_type { }; template struct is_dereferencable> : std::true_type { }; template struct is_dereferencable> : std::true_type { }; template struct is_dereferencable> : std::true_type { }; /////////////////////////////////////////////////////////////////////////////// template struct dereferenced_type { typedef typename std::enable_if< std::is_pointer::value, std::remove_pointer >::type type; }; //----------------------------------------------------------------------------- template struct dereferenced_type> { typedef T type; }; template struct dereferenced_type> { typedef T type; }; template struct dereferenced_type> { typedef T type; }; /////////////////////////////////////////////////////////////////////////////// /// find the unsigned version of a type if one exists template struct try_unsigned { typedef typename std::make_unsigned::type type; }; //----------------------------------------------------------------------------- template <> struct try_unsigned { typedef double type; }; template <> struct try_unsigned { typedef float type; }; /////////////////////////////////////////////////////////////////////////////// /// find the signed version of a type if one exists template struct try_signed { typedef typename std::make_signed::type type; }; //----------------------------------------------------------------------------- template <> struct try_signed { typedef double type; }; template <> struct try_signed { typedef float type; }; /////////////////////////////////////////////////////////////////////////////// /// checks if a type can be converted in all cases without modification template struct is_lossless_cast : std::enable_if< std::is_integral::value && std::is_integral::value && std::is_signed::value == std::is_signed::value && sizeof (T) <= sizeof (U), std::true_type >::value { }; /////////////////////////////////////////////////////////////////////////////// template struct remove_restrict { using type = T; }; template struct remove_restrict { using type = T*; }; template using remove_restrict_t = typename remove_restrict::type; /////////////////////////////////////////////////////////////////////////////// /// removes the noexcept type specifier from invokable types namespace detail { template struct remove_noexcept { using type = T; }; //------------------------------------------------------------------------- template struct remove_noexcept { using type = ResultT(&)(Args...); }; //------------------------------------------------------------------------- template struct remove_noexcept { using type = ResultT(*const)(Args...); }; //------------------------------------------------------------------------- template struct remove_noexcept { using type = ResultT(*)(Args...); }; //------------------------------------------------------------------------- template struct remove_noexcept { using type = ResultT(ClassT::*)(Args...); }; //------------------------------------------------------------------------- template struct remove_noexcept { using type = ResultT(ClassT::*)(Args...) const; }; }; //----------------------------------------------------------------------------- template struct remove_noexcept : public detail::remove_noexcept { }; //----------------------------------------------------------------------------- template using remove_noexcept_t = typename remove_noexcept::type; /////////////////////////////////////////////////////////////////////////////// /// removes any `const' qualifier from the supplied member function template struct remove_member_const { using type = FuncT; }; //----------------------------------------------------------------------------- template struct remove_member_const { using type = ReturnT(ClassT::*const)(Args...); }; //----------------------------------------------------------------------------- template struct remove_member_const { using type = ReturnT(ClassT::*)(Args...); }; /////////////////////////////////////////////////////////////////////////////// /// type traits class for querying invokable type return values and argument /// types. /// /// if the type is invokable the alias `return_type' will be defined for the /// return type, and the alias tuple `argument_types' will be defined for the /// arguments; namespace detail { template struct func_traits { }; //------------------------------------------------------------------------- template struct func_traits { using return_type = ResultT; using argument_types = std::tuple; }; //------------------------------------------------------------------------- template struct func_traits { using return_type = ResultT; using argument_types = std::tuple; }; //------------------------------------------------------------------------- template struct func_traits { using return_type = ResultT; using argument_types = std::tuple; }; }; //----------------------------------------------------------------------------- template struct func_traits : public ::detail::func_traits< // we apply as many transforms as possible before palming it off to the // detail class so that we don't have to write as many distinct cases. ::util::chain_t > { // we may as well record the underlying type here. it might prove useful // to someone. using type = T; }; #endif