From 2ef8924510af3a869c74d31cb9e088a0b6e97a34 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Fri, 7 Feb 2014 17:10:36 +0400 Subject: [PATCH] Documented some of the classes and features --- doc/type_index.qbk | 63 ++++----- include/boost/type_index.hpp | 121 +++++++++++++++--- include/boost/type_index/ctti_type_index.hpp | 13 +- include/boost/type_index/stl_type_index.hpp | 12 +- .../boost/type_index/type_index_facade.hpp | 50 +++++++- 5 files changed, 194 insertions(+), 65 deletions(-) diff --git a/doc/type_index.qbk b/doc/type_index.qbk index 643c32a..ae2d211 100644 --- a/doc/type_index.qbk +++ b/doc/type_index.qbk @@ -1,6 +1,6 @@ [library Boost.TypeIndex [quickbook 1.6] - [version 2.1] + [version 3.0] [copyright 2012-2013 Antony Polukhin] [category Language Features Emulation] [license @@ -24,7 +24,7 @@ Boost.TypeIndex library was designed to work around all those issues. [note `T` means type here. Think of it as of `T` in `template ` ] -[warning During the Boost review was decided, that it is better to use interface close to v1.0 of this library. Version 3.0 will attempt to fix all the issues found during the review. ] +[warning Version 3.0 of this library is waitning for Boost mini-review. ] [endsect] @@ -44,9 +44,6 @@ To start using Boost.TypeIndex: #include #include ``][`` - #include - #include -`` or `` #include ``]] @@ -54,10 +51,17 @@ To start using Boost.TypeIndex: std::type_info std::type_index ``][`` - boost::type_info boost::type_index ``]] +[[`` + std::type_info& + const std::type_info& +``][`` + boost::type_index& + const boost::type_index& +``]] + [[`` typeid(T) typeid(please_save_modifiers) @@ -66,8 +70,8 @@ To start using Boost.TypeIndex: ``][`` boost::type_id() boost::type_id_with_cvr() - boost::type_id().name_demangled() // human readable - boost::type_id_rtti_only(variable) + boost::type_id().pretty_name() // human readable + boost::type_id_runtime(variable) ``]] ] @@ -75,7 +79,7 @@ To start using Boost.TypeIndex: Here is how TypeIndex could be used in `boost/any.hpp`: [table:any [[Before] [With TypeIndex]] -[[``#include ``][``#include ``]] +[[``#include ``][``#include ``]] [[`` virtual const std::type_info & type() const BOOST_NOEXCEPT { @@ -86,7 +90,7 @@ Here is how TypeIndex could be used in `boost/any.hpp`: virtual const boost::type_info & type() const BOOST_NOEXCEPT { // now works even with RTTI disabled - return boost::type_id(); + return boost::type_id()->type_info(); } ``]] ] @@ -101,7 +105,7 @@ Here is how TypeIndex could be used in `boost/variant/variant.hpp`: #include // for typeid, std::type_info #endif // BOOST_NO_TYPEID ``][`` -#include +#include ``]] [[`` #if !defined(BOOST_NO_TYPEID) @@ -129,7 +133,7 @@ public: // visitor interfaces template const boost::type_info& operator()(const T&) const BOOST_NOEXCEPT { - return boost::type_id(); + return boost::type_id()->type_info(); } }; @@ -174,20 +178,21 @@ public: // visitor interfaces [section Space and Performance] -* `template_info` uses macro for getting full text representation of function name which could lead to code bloat, -so prefer using `type_info` type. -* `type_index` and `template_index` classes hold a single pointer, so they are easy and fast to copy. -* Calls to `const char* name()` do not require dynamic memory allocation and usually just return a pointer to an array of chars in a read-only section of the binary image. +* `ctti_type_info` uses macro for getting full text representation of function name which could lead to code bloat, +so prefer using `stl_type_info` type. +* `type_index` class hold a single pointer, so it is easy and fast to copy. +* Calls to `const char* raw_name()` do not require dynamic memory allocation and usually just return a pointer to an array of chars in a read-only section of the binary image. * Comparison operators are optimized as much as possible, and will at worst execute a single `std::strcmp`. -* Calls to `std::string name_demangled()` usually require dynamic memory allocation and some computations, so they are not recommended for usage in performance critical sections. +* Calls to `std::string pretty_name()` usually require dynamic memory allocation and some computations, so they are not recommended for usage in performance critical sections. [endsect] [section Code bloat] -Without RTTI TypeIndex library will switch from using `boost::type_info` class to `boost::template_info`. -`boost::template_info` uses macro for getting full text representation of function name for each type that -is passed to `type_id()` and `type_id_with_cvr()` functions. +Without RTTI TypeIndex library will switch from using `boost::typeind::stl_type_info` class to +`boost::typeind::ctti_type_info`. `boost::typeind::ctti_type_info` uses macro for getting full +text representation of function name for each type that is passed to `type_id()` and +`type_id_with_cvr()` functions. This leads to big strings in binary file: ``` @@ -224,10 +229,10 @@ feature request to add your compiler to supported compilers list. Include Consider the following example: With `BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` and `BOOST_TYPE_INDEX_CTTI_END_SKIP` set to `0`, -`boost::template_id().name()` returns "const char *__cdecl boost::detail::ctti::n(void)". -Then you shall set `BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` to -`sizeof("const char *__cdecl boost::detail::ctti<") - 1` and `BOOST_TYPE_INDEX_CTTI_END_SKIP` -to `sizeof(">::n(void)") - 1` +`boost::typeind::ctti_type_info::construct().raw_name()` returns +"const char *__cdecl boost::detail::ctti::n(void)". Then you shall set +`BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` to `sizeof("const char *__cdecl boost::detail::ctti<") - 1` +and `BOOST_TYPE_INDEX_CTTI_END_SKIP` to `sizeof(">::n(void)") - 1`. [endsect] @@ -236,8 +241,8 @@ to `sizeof(">::n(void)") - 1` Linking a binary from source files that were compiled with different RTTI flags is not a very good idea and may lead to a lot of surprises. However if there is a very strong need, TypeIndex library provides a solution for mixing sources: just define `BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY` -macro. This would lead to usage of `boost::template_index` instead of `boost::type_index` class -and `boost::template_info` instead of `boost::type_info` class. +macro. This would lead to usage of `boost::typeind::ctti_type_info` instead of +`boost::typeind::stl_type_info` class. [note Do not forget to rebuild *all* the projects with `BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY` macro defined ] @@ -249,7 +254,7 @@ RTTI flags: [table:diffs [[RTTI on] [RTTI off]] -[[`boost::type_index get_integer();`] [`boost::template_index get_integer();`]] +[[`boost::typeind::stl_type_info get_integer();`] [`boost::typeind::ctti_type_info get_integer();`]] ] Such differences are usually not detected by linker and lead to errors at runtime. @@ -266,8 +271,8 @@ Such differences are usually not detected by linker and lead to errors at runtim In order of helping and advising: -* Peter Dimov for writing source codes in late 2007, ideas from which were refined and put into this library. +* Peter Dimov for writing source codes in late 2007, that gave me an idea of how to emulate RTTI. * Agustín Bergé K-ballo for helping with docs and fixing a lot of typos. -* Niall Douglas for generating a lot of great ideas and reviewing the sources. +* Niall Douglas for generating a lot of great ideas, reviewing the sources and being the review manager for the library. [endsect] diff --git a/include/boost/type_index.hpp b/include/boost/type_index.hpp index 4937533..dec4530 100644 --- a/include/boost/type_index.hpp +++ b/include/boost/type_index.hpp @@ -9,16 +9,10 @@ #define BOOST_TYPE_INDEX_HPP /// \file boost/type_index.hpp -/// \brief Includes all the headers of the Boost.TypeIndex library. +/// \brief Includes minimal set of headers required to use the Boost.TypeIndex library. /// -/// By inclusion of this file all classes (boost::type_info + boost::type_index if RTTI is on -/// and boost::template_info + boost::template_index) will be available. -/// -/// Consider including if you do not want to include -/// boost::template_info and boost::template_index class while RTTI is available. -/// -/// Consider including if you need only boost::type_info class -/// and boost::type_id* functions. +/// By inclusion of this file most optimal type index classes will be included and used +/// as a boost::typeind::type_index and boost::typeind::type_info. // MS compatible compilers support #pragma once #if defined(_MSC_VER) @@ -27,8 +21,8 @@ #include -#if defined(BOOST_TYPE_INDEX_USER_TYPEINFO) && defined(BOOST_TYPE_INDEX_USER_TYPEINFO_NAME) -# include BOOST_TYPE_INDEX_USER_TYPEINFO +#if defined(BOOST_TYPE_INDEX_USER_TYPEINDEX) && defined(BOOST_TYPE_INDEX_USER_TYPEINDEX_NAME) +# include BOOST_TYPE_INDEX_USER_TYPEINDEX #elif (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC) # include #else @@ -37,44 +31,134 @@ namespace boost { namespace typeind { -#if defined(BOOST_TYPE_INDEX_USER_TYPEINFO) && defined(BOOST_TYPE_INDEX_USER_TYPEINFO_NAME) - typedef BOOST_TYPE_INDEX_USER_TYPEINFO_NAME type_index; +#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED) + /// Depending on a compiler flags, optimal implementation of type_index will be used + /// as a default boost::typeind::type_index. + /// + /// Could be a boost::typeind::stl_type_index, boost::typeind::ctti_type_index or + /// user defined type_index class. + typedef platform-specific type_index; +#elif defined(BOOST_TYPE_INDEX_USER_TYPEINDEX) && defined(BOOST_TYPE_INDEX_USER_TYPEINDEX_NAME) + typedef BOOST_TYPE_INDEX_USER_TYPEINDEX_NAME type_index; #elif (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC) typedef boost::typeind::stl_type_index type_index; #else typedef boost::typeind::ctti_type_index type_index; #endif +/// Depending on a compiler flags, optimal implementation of type_info will be used +/// as a default boost::typeind::type_info. +/// +/// Could be a std::type_info, boost::typeind::detail::ctti_data or +/// some user defined class. typedef type_index::type_info_t type_info; // TODO: // inline bool is_equal(const type_info&, const type_info&) BOOST_NOEXCEPT; // inline bool is_before(const type_info&, const type_info&) BOOST_NOEXCEPT; +#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED) -/// Function to get boost::type_index for a type T. -/// Strips const, volatile and & modifiers from T. +/// \def BOOST_TYPE_INDEX_USER_TYPEINFO +/// BOOST_TYPE_INDEX_USER_TYPEINFO can be defined to the path to header file +/// with user provided implementation of type_index. +/// +/// BOOST_TYPE_INDEX_USER_TYPEINDEX_NAME must be also defined! +#define BOOST_TYPE_INDEX_USER_TYPEINDEX + + +/// \def BOOST_TYPE_INDEX_USER_TYPEINDEX_NAME +/// BOOST_TYPE_INDEX_USER_TYPEINDEX_NAME can be defined to the fullty +/// qualified name of the user's type_index implementation. +/// +/// BOOST_TYPE_INDEX_USER_TYPEINDEX must be also defined! +#define BOOST_TYPE_INDEX_USER_TYPEINDEX_NAME my_namespace::my_type_index + +#endif // defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED) + + +/// Function to get boost::type_index for a type T. +/// Removes const, volatile && and & modifiers from T. +/// +/// \b Example: +/// \code +/// type_index ti = type_id(); +/// std::cout << ti.pretty_name(); // Outputs 'int' +/// \endcode +/// +/// \throw Nothing. +/// \return boost::typeind::type_index with information about the specified type T. template inline type_index type_id() BOOST_NOEXCEPT { return type_index::construct(); } -/// Function for constructing boost::type_index instance for type T. -/// Does not strip const, volatile, & and && modifiers from T. +/// Function for constructing boost::type_index instance for type T. +/// Does not remove const, volatile, & and && modifiers from T. +/// /// If T has no const, volatile, & and && modifiers, then returns exactly /// the same result as in case of calling `type_id()`. +/// +/// \b Example: +/// \code +/// type_index ti = type_id_with_cvr(); +/// std::cout << ti.pretty_name(); // Outputs 'int&' +/// \endcode +/// +/// \throw Nothing. +/// \return boost::typeind::type_index with information about the specified type T. template inline type_index type_id_with_cvr() BOOST_NOEXCEPT { return type_index::construct_with_cvr(); } /// Function that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index. +/// +/// Retunrs runtime information about specified type. +/// +/// \b Requirements: RTTI available or specially designed user type_info class must be provided +/// via BOOST_TYPE_INDEX_USER_TYPEINDEX and BOOST_TYPE_INDEX_USER_TYPEINDEX_NAME macro. +/// +/// \b Example: +/// \code +/// struct Base { virtual ~Base(){} }; +/// struct Derived: public Base {}; +/// ... +/// Derived d; +/// Base& b = d; +/// type_index ti = type_id_runtime(b); +/// std::cout << ti.pretty_name(); // Outputs 'Derived' +/// \endcode +/// +/// \param runtime_val Varaible which runtime type must be returned. +/// \throw Nothing. +/// \return boost::typeind::type_index with information about the specified variable. template inline type_index type_id_runtime(const T& runtime_val) BOOST_NOEXCEPT { return type_index::construct_runtime(runtime_val); } -/// Function that works exactly like C++ typeid(rtti_val) call, but returns boost::type_info. +/// Function that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index. +/// Function that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index. +/// +/// Retunrs runtime information about specified type. +/// +/// \b Requirements: RTTI available or specially designed user type_info class must be provided +/// via BOOST_TYPE_INDEX_USER_TYPEINDEX and BOOST_TYPE_INDEX_USER_TYPEINDEX_NAME macro. +/// +/// \b Example: +/// \code +/// struct Base { virtual ~Base(){} }; +/// struct Derived: public Base {}; +/// ... +/// Base* b = new Derived(); +/// type_index ti = type_id_runtime(b); +/// std::cout << ti.pretty_name(); // Outputs 'Derived*' +/// \endcode +/// +/// \param runtime_val Varaible which runtime type must be returned. +/// \throw Nothing. +/// \return boost::typeind::type_index with information about the specified variable. template inline type_index type_id_runtime(const T* runtime_val) { return type_index::construct_runtime(runtime_val); @@ -83,5 +167,6 @@ inline type_index type_id_runtime(const T* runtime_val) { }} // namespace boost::typeind + #endif // BOOST_TYPE_INDEX_HPP diff --git a/include/boost/type_index/ctti_type_index.hpp b/include/boost/type_index/ctti_type_index.hpp index c6b28c4..b880a7e 100644 --- a/include/boost/type_index/ctti_type_index.hpp +++ b/include/boost/type_index/ctti_type_index.hpp @@ -14,16 +14,14 @@ # pragma once #endif -/// \file stl_type_index.ipp -/// \brief Contains specialization of boost::type_index_base. +/// \file ctti_type_index.hpp +/// \brief Contains boost::typeind::ctti_type_index class. /// -/// boost::type_index_base class can be used as a drop-in replacement +/// boost::typeind::ctti_type_index class can be used as a drop-in replacement /// for std::type_index. /// -/// It is used in situations when RTTI is enabled or typeid() method is available. -/// When typeid() is not is disabled or BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY macro is defined boost::template_info -/// is usually used instead of it (some compilers allow calling typeid(T) -/// even if RTTI is disabled, those copilers will continue to use boost::type_info class). +/// It is used in situations when typeid() method is not available or +/// BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY macro is defined. #include #include @@ -50,6 +48,7 @@ inline const ctti_data& ctti_construct() BOOST_NOEXCEPT { } // namespace detail +/// \class ctti_type_index class ctti_type_index: public type_index_facade { const detail::ctti_data* data_; diff --git a/include/boost/type_index/stl_type_index.hpp b/include/boost/type_index/stl_type_index.hpp index 22813d9..080d9db 100644 --- a/include/boost/type_index/stl_type_index.hpp +++ b/include/boost/type_index/stl_type_index.hpp @@ -14,16 +14,15 @@ # pragma once #endif -/// \file stl_type_index.ipp -/// \brief Contains specialization of boost::type_index_base. +/// \file stl_type_index.hpp +/// \brief Contains boost::typeind::stl_type_index class. /// -/// boost::type_index_base class can be used as a drop-in replacement +/// boost::typeind::stl_type_index class can be used as a drop-in replacement /// for std::type_index. /// /// It is used in situations when RTTI is enabled or typeid() method is available. -/// When typeid() is not is disabled or BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY macro is defined boost::template_info -/// is usually used instead of it (some compilers allow calling typeid(T) -/// even if RTTI is disabled, those copilers will continue to use boost::type_info class). +/// When typeid() is disabled or BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY macro +/// is defined boost::typeind::ctti is usually used instead of boost::typeind::stl_type_index. #include @@ -61,6 +60,7 @@ namespace boost { namespace typeind { +/// \class stl_type_index class stl_type_index : public type_index_facade< stl_type_index, diff --git a/include/boost/type_index/type_index_facade.hpp b/include/boost/type_index/type_index_facade.hpp index 5f1d0b1..8d793fe 100644 --- a/include/boost/type_index/type_index_facade.hpp +++ b/include/boost/type_index/type_index_facade.hpp @@ -27,12 +27,35 @@ namespace boost { namespace typeind { -/// type_index_facade - use as a public base class for defining new -/// standard-conforming iterators. +/// \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. template class type_index_facade { private: + /// @cond Derived& derived() BOOST_NOEXCEPT { return *static_cast(this); } @@ -40,7 +63,7 @@ private: const Derived & derived() const BOOST_NOEXCEPT { return *static_cast(this); } - + /// @endcond public: typedef TypeInfo type_info_t; typedef type_index_facade this_type; @@ -74,7 +97,7 @@ public: } }; - +/// @cond template inline bool operator == (const type_index_facade& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { return lhs.equal(rhs); @@ -171,17 +194,33 @@ inline bool operator != (const type_index_facade& lhs, const // ######################### 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 << ind.pretty_name(); return ostr; } +/// @endcond #else -/// Ostream operator that will output demangled name +/// Ostream operator that will output demangled name. template inline std::basic_ostream& operator<<( std::basic_ostream& ostr, @@ -193,6 +232,7 @@ inline std::basic_ostream& operator<<( #endif // BOOST_NO_TEMPLATED_IOSTREAMS #endif // BOOST_NO_IOSTREAM +/// This free function is used by Boost's unordered containers. template inline std::size_t hash_value(const type_index_facade& lhs) BOOST_NOEXCEPT { return lhs.hash_code();