// // Copyright (c) 2013-2019 Antony Polukhin. // // // 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) // #ifndef BOOST_TYPE_INDEX_TYPE_INDEX_FACADE_HPP #define BOOST_TYPE_INDEX_TYPE_INDEX_FACADE_HPP #include #include #include #include #if !defined(BOOST_NO_IOSTREAM) #if !defined(BOOST_NO_IOSFWD) #include // for std::basic_ostream #else #include #endif #endif #ifdef BOOST_HAS_PRAGMA_ONCE # pragma once #endif namespace boost { namespace typeindex { /// \class type_index_facade /// /// This class takes care about the comparison operators, hash functions and /// ostream operators. Use this class as a public base class for defining new /// type_info-conforming classes. /// /// \b Example: /// \code /// class stl_type_index: public type_index_facade /// { /// public: /// typedef std::type_info type_info_t; /// private: /// const type_info_t* data_; /// /// public: /// stl_type_index(const type_info_t& data) noexcept /// : data_(&data) /// {} /// // ... /// }; /// \endcode /// /// \tparam Derived Class derived from type_index_facade. /// \tparam TypeInfo Class that will be used as a base type_info class. /// \note Take a look at the protected methods. They are \b not \b defined in type_index_facade. /// Protected member functions raw_name() \b must be defined in Derived class. All the other /// methods are mandatory. /// \see 'Making a custom type_index' section for more information about /// creating your own type_index using type_index_facade. template class type_index_facade { private: /// @cond BOOST_CXX14_CONSTEXPR const Derived & derived() const BOOST_NOEXCEPT { return *static_cast(this); } /// @endcond public: typedef TypeInfo type_info_t; /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw. /// \return Name of a type. By default returns Derived::raw_name(). inline const char* name() const BOOST_NOEXCEPT { return derived().raw_name(); } /// \b Override: This function \b may be redefined in Derived class. Overrides may throw. /// \return Human readable type name. By default returns Derived::name(). inline std::string pretty_name() const { return derived().name(); } /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw. /// \return True if two types are equal. By default compares types by raw_name(). inline bool equal(const Derived& rhs) const BOOST_NOEXCEPT { const char* const left = derived().raw_name(); const char* const right = rhs.raw_name(); return left == right || !std::strcmp(left, right); } /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw. /// \return True if rhs is greater than this. By default compares types by raw_name(). inline bool before(const Derived& rhs) const BOOST_NOEXCEPT { const char* const left = derived().raw_name(); const char* const right = rhs.raw_name(); return left != right && std::strcmp(left, right) < 0; } /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw. /// \return Hash code of a type. By default hashes types by raw_name(). /// \note Derived class header \b must include , \b unless this function is redefined in /// Derived class to not use boost::hash_range(). inline std::size_t hash_code() const BOOST_NOEXCEPT { const char* const name_raw = derived().raw_name(); return boost::hash_range(name_raw, name_raw + std::strlen(name_raw)); } #if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED) protected: /// \b Override: This function \b must be redefined in Derived class. Overrides \b must not throw. /// \return Pointer to unredable/raw type name. inline const char* raw_name() const BOOST_NOEXCEPT; /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw. /// \return Const reference to underlying low level type_info_t. inline const type_info_t& type_info() const BOOST_NOEXCEPT; /// This is a factory method that is used to create instances of Derived classes. /// boost::typeindex::type_id() will call this method, if Derived has same type as boost::typeindex::type_index. /// /// \b Override: This function \b may be redefined and made public in Derived class. Overrides \b must not throw. /// Overrides \b must remove const, volatile && and & modifiers from T. /// \tparam T Type for which type_index must be created. /// \return type_index for type T. template static Derived type_id() BOOST_NOEXCEPT; /// This is a factory method that is used to create instances of Derived classes. /// boost::typeindex::type_id_with_cvr() will call this method, if Derived has same type as boost::typeindex::type_index. /// /// \b Override: This function \b may be redefined and made public in Derived class. Overrides \b must not throw. /// Overrides \b must \b not remove const, volatile && and & modifiers from T. /// \tparam T Type for which type_index must be created. /// \return type_index for type T. template static Derived type_id_with_cvr() BOOST_NOEXCEPT; /// This is a factory method that is used to create instances of Derived classes. /// boost::typeindex::type_id_runtime(const T&) will call this method, if Derived has same type as boost::typeindex::type_index. /// /// \b Override: This function \b may be redefined and made public in Derived class. /// \param variable Variable which runtime type will be stored in type_index. /// \return type_index with runtime type of variable. template static Derived type_id_runtime(const T& variable) BOOST_NOEXCEPT; #endif }; /// @cond template BOOST_CXX14_CONSTEXPR inline bool operator == (const type_index_facade& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { return static_cast(lhs).equal(static_cast(rhs)); } template BOOST_CXX14_CONSTEXPR inline bool operator < (const type_index_facade& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { return static_cast(lhs).before(static_cast(rhs)); } template BOOST_CXX14_CONSTEXPR inline bool operator > (const type_index_facade& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { return rhs < lhs; } template BOOST_CXX14_CONSTEXPR inline bool operator <= (const type_index_facade& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { return !(lhs > rhs); } template BOOST_CXX14_CONSTEXPR inline bool operator >= (const type_index_facade& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { return !(lhs < rhs); } template BOOST_CXX14_CONSTEXPR inline bool operator != (const type_index_facade& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { return !(lhs == rhs); } // ######################### COMPARISONS with Derived ############################ // template inline bool operator == (const TypeInfo& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { return Derived(lhs) == rhs; } template inline bool operator < (const TypeInfo& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { return Derived(lhs) < rhs; } template inline bool operator > (const TypeInfo& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { return rhs < Derived(lhs); } template inline bool operator <= (const TypeInfo& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { return !(Derived(lhs) > rhs); } template inline bool operator >= (const TypeInfo& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { return !(Derived(lhs) < rhs); } template inline bool operator != (const TypeInfo& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { return !(Derived(lhs) == rhs); } template inline bool operator == (const type_index_facade& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { return lhs == Derived(rhs); } template inline bool operator < (const type_index_facade& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { return lhs < Derived(rhs); } template inline bool operator > (const type_index_facade& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { return Derived(rhs) < lhs; } template inline bool operator <= (const type_index_facade& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { return !(lhs > Derived(rhs)); } template inline bool operator >= (const type_index_facade& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { return !(lhs < Derived(rhs)); } template inline bool operator != (const type_index_facade& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { return !(lhs == Derived(rhs)); } // ######################### COMPARISONS with Derived END ############################ // /// @endcond #if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED) /// noexcept comparison operators for type_index_facade classes. bool operator ==, !=, <, ... (const type_index_facade& lhs, const type_index_facade& rhs) noexcept; /// noexcept comparison operators for type_index_facade and it's TypeInfo classes. bool operator ==, !=, <, ... (const type_index_facade& lhs, const TypeInfo& rhs) noexcept; /// noexcept comparison operators for type_index_facade's TypeInfo and type_index_facade classes. bool operator ==, !=, <, ... (const TypeInfo& lhs, const type_index_facade& rhs) noexcept; #endif #ifndef BOOST_NO_IOSTREAM #ifdef BOOST_NO_TEMPLATED_IOSTREAMS /// @cond /// Ostream operator that will output demangled name template inline std::ostream& operator<<(std::ostream& ostr, const type_index_facade& ind) { ostr << static_cast(ind).pretty_name(); return ostr; } /// @endcond #else /// Ostream operator that will output demangled name. template inline std::basic_ostream& operator<<( std::basic_ostream& ostr, const type_index_facade& ind) { ostr << static_cast(ind).pretty_name(); return ostr; } #endif // BOOST_NO_TEMPLATED_IOSTREAMS #endif // BOOST_NO_IOSTREAM /// This free function is used by Boost's unordered containers. /// \note has to be included if this function is used. template inline std::size_t hash_value(const type_index_facade& lhs) BOOST_NOEXCEPT { return static_cast(lhs).hash_code(); } }} // namespace boost::typeindex #endif // BOOST_TYPE_INDEX_TYPE_INDEX_FACADE_HPP