/************************************************************************************ * * * Copyright (c) 2014 - 2018 Axel Menzel * * * * This file is part of RTTR (Run Time Type Reflection) * * License: MIT License * * * * Permission is hereby granted, free of charge, to any person obtaining * * a copy of this software and associated documentation files (the "Software"), * * to deal in the Software without restriction, including without limitation * * the rights to use, copy, modify, merge, publish, distribute, sublicense, * * and/or sell copies of the Software, and to permit persons to whom the * * Software is furnished to do so, subject to the following conditions: * * * * The above copyright notice and this permission notice shall be included in * * all copies or substantial portions of the Software. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * * SOFTWARE. * * * *************************************************************************************/ #ifndef RTTR_UTILITY_H_ #define RTTR_UTILITY_H_ #include "rttr/detail/base/core_prerequisites.h" #include "rttr/detail/misc/std_type_traits.h" #include "rttr/detail/misc/misc_type_traits.h" #include #include #include #include #include #include #ifdef RTTR_NO_CXX17_NOEXCEPT_FUNC_TYPE RTTR_BEGIN_DISABLE_EXCEPT_TYPE_WARNING #endif namespace rttr { namespace detail { ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// // This will add the c++14 integer sequence to c++11 template struct integer_sequence { template using append = integer_sequence; static std::size_t size() { return sizeof...(I); } using next = append; using type = T; }; template struct sequence_generator { using type = typename sequence_generator::type::next; }; template struct sequence_generator { using type = integer_sequence; }; template using index_sequence = integer_sequence; template using make_integer_sequence = typename sequence_generator::type; template using make_index_sequence = make_integer_sequence; template using index_sequence_for = make_index_sequence; ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// // will remove all numbers of the given index sequence till the given \p Index. // typename erase_sequence_till, 3>::type => index_sequence<3, 4> template struct erase_sequence_till; template struct erase_sequence_till, Index> { using type = conditional_t< Idx == Index, index_sequence, typename erase_sequence_till, Index>::type>; }; template struct erase_sequence_till, Index> { using type = index_sequence<>; }; ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// template struct remove_first_index_impl { using type = index_sequence<>; }; template struct remove_first_index_impl> { using type = detail::index_sequence; }; template using remove_first_index = typename remove_first_index_impl::type; ///////////////////////////////////////////////////////////////////////////////////////// template struct concat_index_sequence { }; template struct concat_index_sequence, index_sequence> { using type = index_sequence; }; ///////////////////////////////////////////////////////////////////////////////////////// template struct remove_last_index_impl; template struct remove_last_index_impl> { using type = index_sequence<>; }; template struct remove_last_index_impl> { using type = typename concat_index_sequence< index_sequence, typename remove_last_index_impl>::type >::type; }; template using remove_last_index = typename remove_last_index_impl::type; ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// //template //using type_identity = T; // template struct type_identity { using type = T; }; template> struct create_type_list; template struct create_type_list> { using type = type_list::type...>; }; // creates a type list with type T, N times in it // e.g. create_type_list_t => type_list template using create_type_list_t = typename create_type_list::type; ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// static RTTR_FORCE_INLINE bool check_all_true() { return true; } template static RTTR_INLINE bool check_all_true(bool arg1, BoolArgs... args) { return arg1 & check_all_true(args...); } ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// // copy the content of any arbitrary array, use it like: // copy_array(in, out); // works with every dimension template struct copy_array_impl { void operator()(const ElementType &in, ElementType &out) { out = in; } }; template struct copy_array_impl { void operator()(const ElementType (&in)[Count], ElementType (&out)[Count]) { for(std::size_t i = 0; i < Count; ++i) copy_array_impl()(in[i], out[i]); } }; template auto copy_array(const ElementType (&in)[Count], ElementType (&out)[Count]) -> ElementType (&)[Count] { copy_array_impl()(in, out); return out; } ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// // make_unqiue implementation for C++11 template struct _Unique_if { using _Single_object = std::unique_ptr; }; template struct _Unique_if { using _Unknown_bound = std::unique_ptr; }; template struct _Unique_if { using _Known_bound = void; }; template typename _Unique_if::_Single_object make_unique(Args&&... args) { return std::unique_ptr(new T(std::forward(args)...)); } template typename _Unique_if::_Unknown_bound make_unique(size_t n) { using U = typename std::remove_extent::type; return std::unique_ptr(new U[n]()); } template typename _Unique_if::_Known_bound make_unique(Args&&...) = delete; ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// template RTTR_CONSTEXPR RTTR_INLINE add_const_t& as_const(T& value) RTTR_NOEXCEPT { return value; } ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// template RTTR_FORCE_INLINE typename std::enable_if::value, void*>::type as_void_ptr(const T& obj) { return const_cast(reinterpret_cast(obj)); } template RTTR_FORCE_INLINE typename std::enable_if::value, void*>::type as_void_ptr(const T& obj) { return const_cast(reinterpret_cast(&obj)); } ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// /*! * Helper class to iterate in a ranged-based for loops backwards through a container. * use it like following: * \code{.cpp} * for(const auto& value: reverse(my_vector)) * std::cout << value << std::endl; * \endcode */ template class reverse_wrapper { public: reverse_wrapper(T& container) : m_container(container) { } decltype(std::declval().rbegin()) begin() { return m_container.rbegin(); } decltype(std::declval().rend()) end() { return m_container.rend(); } decltype(std::declval().crbegin()) begin() const { return m_container.crbegin(); } decltype(std::declval().crend()) end() const { return m_container.crend(); } private: reverse_wrapper& operator=(const reverse_wrapper& other); T& m_container; }; template class reverse_move_wrapper { public: reverse_move_wrapper(T&& container) : m_container(std::move(container)) { } decltype(std::declval().rbegin()) begin() { return m_container.rbegin(); } decltype(std::declval().rend()) end() { return m_container.rend(); } decltype(std::declval().crbegin()) begin() const { return m_container.crbegin(); } decltype(std::declval().crend()) end() const { return m_container.crend(); } private: T m_container; }; template auto reverse(T&& container) -> typename std::conditional< std::is_lvalue_reference::value, reverse_wrapper, reverse_move_wrapper >::type { return { std::forward(container) }; } ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// template using return_type_normal = add_pointer_t< remove_pointers_t >; template> using raw_addressof_return_type = std::conditional< is_function_ptr< remove_pointers_except_one_t >::value, add_pointer_t< remove_pointers_except_one_t >, return_type_normal >; template using raw_addressof_return_type_t = typename raw_addressof_return_type::type; template struct raw_addressof_impl { static RTTR_INLINE raw_addressof_return_type_t get(T& data) { return std::addressof(data); } }; template using is_raw_void_pointer = std::is_same > >; template using is_void_pointer = std::integral_constant::value && is_raw_void_pointer::value && pointer_count::value == 1>; template struct raw_addressof_impl::value && pointer_count::value >= 1 && !is_void_pointer::value) || (pointer_count::value == 1 && std::is_member_pointer >::value) > > { static RTTR_INLINE raw_addressof_return_type_t get(T& data) { return raw_addressof_impl< remove_pointer_t >::get(*data); } }; template struct raw_addressof_impl::value> > { static RTTR_INLINE raw_addressof_return_type_t get(T& data) { return data; // void pointer cannot be dereferenced to type "void" } }; /*! * \brief This function will return from its raw type \p T * its address as pointer. * * \see detail::raw_type * * \return The address of the raw type from the given object \p data as pointer. */ template static RTTR_INLINE raw_addressof_return_type_t raw_addressof(T& data) { return raw_addressof_impl::get(data); } ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// /*! * The \ref move_wrapper class wraps a move-only type in a copyable object. * */ template struct move_wrapper { move_wrapper(T&& value) : m_value(std::move(value)) { } move_wrapper(const move_wrapper& other) : m_value(std::move(other.m_value)) { } move_wrapper(move_wrapper&& other) : m_value(std::move(other.m_value)) { } move_wrapper& operator=(const move_wrapper& other) { m_value = std::move(other.m_value); return *this; } move_wrapper& operator=(move_wrapper&& other) { m_value = std::move(other.m_value); return *this; } mutable T m_value; }; /*! * \brief This function creates an instance of a move_wrapper class for type \p T. * * \return An instance of move_wrapper. */ template static RTTR_INLINE move_wrapper make_rref(T&& value) { return {std::move(value)}; } ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// /*! * \brief When the given shared_ptr \p obj is empty, it will create a new default one, * otherwise returns a copy. */ template static RTTR_INLINE std::shared_ptr create_if_empty(const std::shared_ptr& obj) { return (obj.get() ? obj : std::make_shared()); } ///////////////////////////////////////////////////////////////////////////////////////// /*! * \brief Generates a hash value for continuous sequence of char's */ RTTR_INLINE static std::size_t generate_hash(const char* text, std::size_t length) { const std::size_t magic_prime = static_cast(0x01000193); std::size_t hash = static_cast(0xcbf29ce4); for (std::size_t i = 0; i < length; ++i) hash = (hash ^ text[i]) * magic_prime; return hash; } ///////////////////////////////////////////////////////////////////////////////////////// // custom has functor, to make sure that "std::string" and "rttr::string_view" uses the same hashing algorithm template struct hash; template <> struct hash { public: size_t operator()(const std::string& text) const { return generate_hash(text.data(), text.length()); } }; ///////////////////////////////////////////////////////////////////////////////////////// template inline enable_if_t::value || std::is_same::value, bool> starts_with(const T& big_str, const T& small_str) { return (big_str.compare(0, small_str.size(), small_str) == 0); } template inline enable_if_t::value || std::is_same::value, bool> ends_with(const T& big_str, const T& small_str) { return (big_str.size() >= small_str.size() && big_str.compare(big_str.size() - small_str.size(), small_str.size(), small_str) == 0); } ///////////////////////////////////////////////////////////////////////////////////////// /*! * A simple identity function. Returns the same object, without doing anything. */ template static RTTR_INLINE T& identity_func(T& func) { return func; } ///////////////////////////////////////////////////////////////////////////////////////// } // end namespace detail } // end namespace rttr #ifdef RTTR_NO_CXX17_NOEXCEPT_FUNC_TYPE RTTR_END_DISABLE_EXCEPT_TYPE_WARNING #endif #endif //RTTR_UTILITY_H_