//-------------------------------------- // utils/traits: Additional type traits //-------------------------------------- // // Copyright kennytm (auraHT Ltd.) 2011. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) /** ```` --- Additional type traits ================================================= This module provides additional type traits and related functions, missing from the standard library. */ #ifndef TRAITS_HPP_9ALQFEFX7TO #define TRAITS_HPP_9ALQFEFX7TO 1 #include #include #include #include #include namespace fplus { // source: https://github.com/kennytm/utils namespace utils { #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Weffc++" #endif /** .. macro:: DECLARE_HAS_TYPE_MEMBER(member_name) This macro declares a template ``has_member_name`` which will check whether a type member ``member_name`` exists in a particular type. Example:: DECLARE_HAS_TYPE_MEMBER(result_type) ... printf("%d\n", has_result_type< std::plus >::value); // ^ prints '1' (true) printf("%d\n", has_result_type< double(*)() >::value); // ^ prints '0' (false) */ #define DECLARE_HAS_TYPE_MEMBER(member_name) \ template \ struct has_##member_name \ { enum { value = false }; }; \ template \ struct has_##member_name::type> \ { enum { value = true }; }; /** .. type:: struct utils::function_traits Obtain compile-time information about a function object *F*. This template currently supports the following types: * Normal function types (``R(T...)``), function pointers (``R(*)(T...)``) and function references (``R(&)(T...)`` and ``R(&&)(T...)``). * Member functions (``R(C::*)(T...)``) * ``std::function`` * Type of lambda functions, and any other types that has a unique ``operator()``. * Type of ``std::mem_fn`` (only for GCC's libstdc++ and LLVM's libc++). Following the C++ spec, the first argument will be a raw pointer. */ template struct function_traits : public function_traits {}; namespace xx_impl { template struct memfn_type { typedef typename std::conditional< std::is_const::value, typename std::conditional< std::is_volatile::value, R (C::*)(A...) const volatile, R (C::*)(A...) const >::type, typename std::conditional< std::is_volatile::value, R (C::*)(A...) volatile, R (C::*)(A...) >::type >::type type; }; } template struct function_traits { /** .. type:: type result_type The type returned by calling an instance of the function object type *F*. */ typedef ReturnType result_type; /** .. type:: type function_type The function type (``R(T...)``). */ typedef ReturnType function_type(Args...); /** .. type:: type member_function_type The member function type for an *OwnerType* (``R(OwnerType::*)(T...)``). */ template using member_function_type = typename xx_impl::memfn_type< typename std::remove_pointer::type>::type, ReturnType, Args... >::type; /** .. data:: static const size_t arity Number of arguments the function object will take. */ enum { arity = sizeof...(Args) }; /** .. type:: type arg::type The type of the *n*-th argument. */ template struct arg { typedef typename std::tuple_element>::type type; }; }; template struct function_traits : public function_traits {}; template struct function_traits : public function_traits { typedef ClassType& owner_type; }; template struct function_traits : public function_traits { typedef const ClassType& owner_type; }; template struct function_traits : public function_traits { typedef volatile ClassType& owner_type; }; template struct function_traits : public function_traits { typedef const volatile ClassType& owner_type; }; template struct function_traits> : public function_traits {}; #if defined(_GLIBCXX_FUNCTIONAL) #define MEM_FN_SYMBOL_XX0SL7G4Z0J std::_Mem_fn #elif defined(_LIBCPP_FUNCTIONAL) #define MEM_FN_SYMBOL_XX0SL7G4Z0J std::__mem_fn #endif #ifdef MEM_FN_SYMBOL_XX0SL7G4Z0J template struct function_traits> : public function_traits {}; template struct function_traits> : public function_traits {}; template struct function_traits> : public function_traits {}; template struct function_traits> : public function_traits {}; template struct function_traits> : public function_traits {}; #undef MEM_FN_SYMBOL_XX0SL7G4Z0J #endif template struct function_traits : public function_traits {}; template struct function_traits : public function_traits {}; template struct function_traits : public function_traits {}; template struct function_traits : public function_traits {}; template struct function_traits : public function_traits {}; template struct function_traits : public function_traits {}; template struct function_traits : public function_traits {}; template struct function_traits : public function_traits {}; #define FORWARD_RES_8QR485JMSBT \ typename std::conditional< \ std::is_lvalue_reference::value, \ T&, \ typename std::remove_reference::type&& \ >::type /** .. function:: auto utils::forward_like(T&& t) noexcept Forward the reference *t* like the type of *Like*. That means, if *Like* is an lvalue (reference), this function will return an lvalue reference of *t*. Otherwise, if *Like* is an rvalue, this function will return an rvalue reference of *t*. This is mainly used to propagate the expression category (lvalue/rvalue) of a member of *Like*, generalizing ``std::forward``. */ template FORWARD_RES_8QR485JMSBT forward_like(T&& input) noexcept { return static_cast(input); } #undef FORWARD_RES_8QR485JMSBT /** .. type:: struct utils::copy_cv Copy the CV qualifier between the two types. For example, ``utils::copy_cv::type`` will become ``const double``. */ template struct copy_cv { private: typedef typename std::remove_cv::type raw_To; typedef typename std::conditional::value, const raw_To, raw_To>::type const_raw_To; public: /** .. type:: type type Result of cv-copying. */ typedef typename std::conditional::value, volatile const_raw_To, const_raw_To>::type type; }; /** .. type:: struct utils::pointee Returns the type by derefering an instance of *T*. This is a generalization of ``std::remove_pointer``, that it also works with iterators. */ template struct pointee { /** .. type:: type type Result of dereferencing. */ typedef typename std::remove_reference())>::type type; }; /** .. function:: std::add_rvalue_reference::type utils::rt_val() noexcept Returns a value of type *T*. It is guaranteed to do nothing and will not throw a compile-time error, but using the returned result will cause undefined behavior. */ template typename std::add_rvalue_reference::type rt_val() noexcept { return std::move(*static_cast(nullptr)); } #ifdef __GNUC__ #pragma GCC diagnostic pop #endif } } namespace fplus { namespace internal { template struct is_std_function : std::false_type { }; template struct is_std_function> : std::true_type { }; // Those traits are needed to not perform arity checks on a generic-lambd // or a templated/overloaded operator() template struct has_function_traits : std::false_type { }; // There is a bug with GCC 7 when a std::function is passed as T. // It produces an ambiguous call between this one and the std::function overload // It's related to our void_t implementation, the C++14 compatible version does not // work, whereas the C++17 one does... // // So, help GCC a bit with is_std_function template struct has_function_traits::value, void_t>> : std::true_type { }; template struct has_function_traits : std::true_type { }; template struct has_function_traits : std::true_type { }; template struct has_function_traits : std::true_type { }; template struct has_function_traits : std::true_type { }; template struct has_function_traits : std::true_type { }; template struct has_function_traits : std::true_type { }; template struct has_function_traits : std::true_type { }; template struct has_function_traits : std::true_type { }; template struct has_function_traits : std::true_type { }; template struct has_function_traits : std::true_type { }; template struct has_function_traits : std::true_type { }; template struct has_function_traits : std::true_type { }; template struct has_function_traits : std::true_type { }; template struct has_function_traits : std::true_type { }; template struct has_function_traits> : std::true_type { }; } } #endif