Fix some of the notes mentioned by Andrey Semashev (more to come)

This commit is contained in:
Antony Polukhin
2014-05-06 16:27:03 +04:00
parent 2602569bc4
commit f7388d59b5
9 changed files with 103 additions and 80 deletions

View File

@ -33,7 +33,7 @@ Boost.TypeIndex library was designed to work around all those issues.
[classref boost::typeindex::type_info boost::typeindex::type_info] is a drop-in replacement for `std::type_info` and
[classref boost::typeindex::type_index boost::typeindex::type_index]
is a drop-in replacement for `std::type_index`. Unlike Standard Library versions those classes may work without RTTI.
is a drop-in replacement for `std::type_index`. Unlike Standard Library versions those classes can work without RTTI.
`type_index` provides the full set of comparison operators, hashing functions and ostream
operators, so it can be used with any container class.
@ -228,7 +228,7 @@ Issues with cross module type comparison on a bugged compilers are bypassed by d
[section Getting through the inheritance to receive a real type name ] [type_index_derived_example] [endsect]
[import ../examples/exact_types_match.cpp]
[section Exact type match: storing type with const, volatile and reference ] [type_index_exact_type_match_example] [endsect]
[section Exact type matching: storing type with const, volatile and reference qualifiers] [type_index_exact_type_match_example] [endsect]
[import ../examples/table_of_names.cpp]
[section Table of raw_name() and pretty_name() outputs with and without RTTI ] [type_index_names_table] [endsect]
@ -354,7 +354,7 @@ and `BOOST_TYPE_INDEX_CTTI_END_SKIP` 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`
provides a solution for mixing sources: just define [macroref BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY]
macro. This would lead to usage of same type_index class (`boost::typeindex::ctti_type_index` or
`boost::typeindex::stl_type_index`) all around the project.

View File

@ -9,9 +9,9 @@
The following example shows that `type_index` (and `type_info`) is able to store the exact type,
without stripping const, volatile and references. Example works with and without RTTI.
In this example we'll create a class, that stores pointer to function and remembers the exact type of a
parameter that function accepts. When an attempt to call the stored function will be made, type of input
parameter will be checked for exact match with initially erased type of function.
In this example we'll create a class that stores a pointer to function and remembers the exact type of the
parameter the function accepts. When the call to the bound function is made, he actual input parameter
type is checked against the stored parameter type and an exception is thrown in case of mismatch.
*/
#include <boost/type_index.hpp>
@ -20,8 +20,8 @@
#include <cassert>
class type_erased_unary_function {
void* function_ptr_;
boost::typeindex::type_index exact_param_t_;
void* function_ptr_;
boost::typeindex::type_index exact_param_t_;
public:
template <class ParamT>

View File

@ -14,11 +14,6 @@
/// By inclusion of this file most optimal type index classes will be included and used
/// as a boost::typeindex::type_index and boost::typeindex::type_info.
// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/config.hpp>
#if defined(BOOST_TYPE_INDEX_USER_TYPEINDEX)
@ -33,6 +28,10 @@
# include <boost/type_index/ctti_register_class.hpp>
#endif
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif
namespace boost { namespace typeindex {
#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
@ -82,7 +81,7 @@ typedef type_index::type_info_t type_info;
/// Put this macro into the public section of polymorphic class to allow runtime type detection.
///
/// Depending on the typeid() availability this macro will expand to nothing or to virtual helper function
/// `virtual const type_info& type_id_runtime() const`.
/// `virtual const type_info& boost_type_info_type_id_runtime_() const noexcept`.
///
/// \b Example:
/// \code

View File

@ -9,16 +9,15 @@
#ifndef BOOST_TYPE_INDEX_CTTI_REGISTER_CLASS_HPP
#define BOOST_TYPE_INDEX_CTTI_REGISTER_CLASS_HPP
// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
# pragma once
#endif
/// \file ctti_register_class.hpp
/// \brief Contains BOOST_TYPE_INDEX_REGISTER_CTTI_CLASS macro.
#include <boost/type_index/ctti_type_index.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif
namespace boost { namespace typeindex { namespace detail {
template <class T>
@ -33,11 +32,11 @@ inline const ctti_data& ctti_construct_typeid_ref(const T*) BOOST_NOEXCEPT {
/// and `typeid()` does not work.
///
/// BOOST_TYPE_INDEX_REGISTER_CTTI_CLASS macro expands to declaration and implementation of
/// `virtual const detail::ctti_data& type_id_runtime() const` method.
#define BOOST_TYPE_INDEX_REGISTER_CTTI_CLASS \
virtual const boost::typeindex::detail::ctti_data& type_id_runtime() const BOOST_NOEXCEPT { \
return boost::typeindex::detail::ctti_construct_typeid_ref(this); \
} \
/// `virtual const type_info& boost_type_info_type_id_runtime_() const noexcept` method.
#define BOOST_TYPE_INDEX_REGISTER_CTTI_CLASS \
virtual const boost::typeindex::detail::ctti_data& boost_type_index_type_id_runtime_() const BOOST_NOEXCEPT { \
return boost::typeindex::detail::ctti_construct_typeid_ref(this); \
} \
/**/
#endif // BOOST_TYPE_INDEX_CTTI_REGISTER_CLASS_HPP

View File

@ -9,11 +9,6 @@
#ifndef BOOST_TYPE_INDEX_CTTI_TYPE_INDEX_HPP
#define BOOST_TYPE_INDEX_CTTI_TYPE_INDEX_HPP
// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
# pragma once
#endif
/// \file ctti_type_index.hpp
/// \brief Contains boost::typeindex::ctti_type_index class.
///
@ -31,6 +26,10 @@
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_reference.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif
namespace boost { namespace typeindex {
namespace detail {
@ -42,12 +41,33 @@ namespace detail {
// 4) we need a compile-time control to make shure that user does not copy or
// default construct `struct-that-represents-type`
//
// Solution would be a standard-layout class with private constructors and assignment operators.
// Solution would be the following:
/// \class ctti_data
/// Standard-layout class with private constructors and assignment operators.
///
/// You can not work with this class directly. The purpose of this class is to hold type info
/// \b when \b RTTI \b is \b off and allow ctti_type_index construction from itself.
///
/// \b Example:
/// \code
/// const detail::ctti_data& foo();
/// ...
/// type_index ti = type_index(foo());
/// std::cout << ti.pretty_name();
/// \endcode
class ctti_data {
#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS
public:
ctti_data() = delete;
ctti_data(const ctti_data&) = delete;
ctti_data& operator=(const ctti_data&) = delete;
#else
private:
ctti_data();
ctti_data(const ctti_data&);
ctti_data& operator=(const ctti_data&);
#endif
};
} // namespace detail
@ -77,6 +97,10 @@ inline const detail::ctti_data& ctti_construct() BOOST_NOEXCEPT {
class ctti_type_index: public type_index_facade<ctti_type_index, detail::ctti_data> {
const detail::ctti_data* data_;
inline std::size_t get_raw_name_length() const BOOST_NOEXCEPT {
return std::strlen(raw_name() + detail::ctti_skip_size_at_end);
}
public:
typedef detail::ctti_data type_info_t;
@ -126,7 +150,7 @@ inline ctti_type_index ctti_type_index::type_id_with_cvr() BOOST_NOEXCEPT {
template <class T>
inline ctti_type_index ctti_type_index::type_id_runtime(const T& variable) BOOST_NOEXCEPT {
return variable.type_id_runtime();
return variable.boost_type_index_type_id_runtime_();
}
@ -136,14 +160,14 @@ inline const char* ctti_type_index::raw_name() const BOOST_NOEXCEPT {
inline std::string ctti_type_index::pretty_name() const {
std::size_t len = std::strlen(raw_name() + detail::ctti_skip_size_at_end);
std::size_t len = get_raw_name_length();
while (raw_name()[len - 1] == ' ') --len; // MSVC sometimes adds whitespaces
return std::string(raw_name(), len);
}
inline std::size_t ctti_type_index::hash_code() const BOOST_NOEXCEPT {
return boost::hash_range(raw_name(), raw_name() + std::strlen(raw_name() + detail::ctti_skip_size_at_end));
return boost::hash_range(raw_name(), raw_name() + get_raw_name_length());
}

View File

@ -9,16 +9,15 @@
#ifndef BOOST_TYPE_INDEX_STL_REGISTER_CLASS_HPP
#define BOOST_TYPE_INDEX_STL_REGISTER_CLASS_HPP
// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
# pragma once
#endif
/// \file stl_register_class.hpp
/// \brief Contains BOOST_TYPE_INDEX_REGISTER_STL_CLASS macro.
#include <boost/type_index/stl_type_index.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif
namespace boost { namespace typeindex { namespace detail {
template <class T>
@ -34,11 +33,11 @@ inline const stl_type_index::type_info_t& stl_construct_typeid_ref(const T*) BOO
/// and `typeid()` does work.
///
/// BOOST_TYPE_INDEX_REGISTER_STL_CLASS macro expands to declaration and implementation of
/// `virtual const std::type_info& type_id_runtime() const` method.
#define BOOST_TYPE_INDEX_REGISTER_STL_CLASS \
virtual const boost::typeindex::stl_type_index::type_info_t& type_id_runtime() const BOOST_NOEXCEPT { \
return boost::typeindex::detail::stl_construct_typeid_ref(this); \
} \
/// `virtual const type_info& boost_type_info_type_id_runtime_() const noexcept` method.
#define BOOST_TYPE_INDEX_REGISTER_STL_CLASS \
virtual const boost::typeindex::stl_type_index::type_info_t& boost_type_index_type_id_runtime_() const BOOST_NOEXCEPT { \
return boost::typeindex::detail::stl_construct_typeid_ref(this); \
} \
/**/
#endif // BOOST_TYPE_INDEX_STL_REGISTER_CLASS_HPP

View File

@ -9,11 +9,6 @@
#ifndef BOOST_TYPE_INDEX_STL_TYPE_INDEX_HPP
#define BOOST_TYPE_INDEX_STL_TYPE_INDEX_HPP
// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
# pragma once
#endif
/// \file stl_type_index.hpp
/// \brief Contains boost::typeindex::stl_type_index class.
///
@ -26,7 +21,6 @@
#include <boost/type_index/type_index_facade.hpp>
// MSVC is capable of calling typeid(T) even when RTTI is off
#if defined(BOOST_NO_RTTI) && !defined(BOOST_MSVC)
#error "File boost/type_index/stl_type_index.ipp is not usable when typeid() is not available."
@ -41,6 +35,7 @@
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/or.hpp>
#include <boost/functional/hash_fwd.hpp>
@ -51,6 +46,7 @@
#if !defined(BOOST_MSVC)
# include <boost/assert.hpp>
# include <boost/detail/no_exceptions_support.hpp>
# include <cstdlib> // std::free
#endif
#if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \
@ -58,6 +54,10 @@
# include <boost/type_traits/is_arithmetic.hpp>
#endif
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif
namespace boost { namespace typeindex {
/// \class stl_type_index
@ -143,11 +143,11 @@ inline std::string stl_type_index::pretty_name() const {
BOOST_TRY {
ret = demang; // may throw out of memory exception
} BOOST_CATCH (...) {
free(demang);
std::free(demang);
BOOST_RETHROW;
} BOOST_CATCH_END
free(demang);
std::free(demang);
#endif
std::string::size_type pos = ret.find("boost::typeindex::detail::cvr_saver<");
@ -234,10 +234,8 @@ namespace detail {
template <class T>
inline stl_type_index stl_type_index::type_id_with_cvr() BOOST_NOEXCEPT {
typedef typename boost::mpl::if_c<
boost::is_reference<T>::value
|| boost::is_const<T>::value
|| boost::is_volatile<T>::value,
typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_<
boost::mpl::or_<boost::is_reference<T>, boost::is_const<T>, boost::is_volatile<T> >,
detail::cvr_saver<T>,
T
>::type type;
@ -249,7 +247,7 @@ inline stl_type_index stl_type_index::type_id_with_cvr() BOOST_NOEXCEPT {
template <class T>
inline stl_type_index stl_type_index::type_id_runtime(const T& value) BOOST_NOEXCEPT {
#ifdef BOOST_NO_RTTI
return value.type_id_runtime();
return value.boost_type_index_type_id_runtime_();
#else
return typeid(value);
#endif

View File

@ -9,11 +9,6 @@
#ifndef BOOST_TYPE_INDEX_TYPE_INDEX_FACADE_HPP
#define BOOST_TYPE_INDEX_TYPE_INDEX_FACADE_HPP
// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/config.hpp>
#include <boost/functional/hash_fwd.hpp>
#include <string>
@ -27,6 +22,10 @@
#endif
#endif
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif
namespace boost { namespace typeindex {
/// \class type_index_facade
@ -65,46 +64,50 @@ private:
public:
typedef TypeInfo type_info_t;
#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
/// \b Override: This function \b must 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 {
return derived().type_info();
}
inline const type_info_t& type_info() const BOOST_NOEXCEPT;
/// \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 {
inline const char* raw_name() const BOOST_NOEXCEPT;
#endif
/// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw.
/// \return Name of a type. By default retuns Derived::raw_name().
inline const char* name() const BOOST_NOEXCEPT {
return derived().raw_name();
}
/// \b Override: This function \b must be redefined in Derived class. Overrides may throw.
/// \return Human redable type name.
/// \b Override: This function \b may be redefined in Derived class. Overrides may throw.
/// \return Human redable type name. By default retuns Derived::name().
inline std::string pretty_name() const {
return derived().pretty_name();
}
/// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw.
/// \return Name of a type. By default retuns raw_name().
inline const char* name() const BOOST_NOEXCEPT {
return raw_name();
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 {
return raw_name() == rhs.raw_name() || !std::strcmp(raw_name(), rhs.raw_name());
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 {
return raw_name() != rhs.raw_name() && std::strcmp(raw_name(), rhs.raw_name()) < 0;
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 <boost/functional/hash.hpp> has to be included if this function is used.
inline std::size_t hash_code() const BOOST_NOEXCEPT {
return boost::hash_range(raw_name(), raw_name() + std::strlen(raw_name()));
const char* const name = derived().raw_name();
return boost::hash_range(name, name + std::strlen(name));
}
#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
@ -260,7 +263,7 @@ bool operator ==, !=, <, ... (const TypeInfo& lhs, const type_index_facade& rhs)
/// Ostream operator that will output demangled name
template <class Derived, class TypeInfo>
inline std::ostream& operator<<(std::ostream& ostr, const type_index_facade<Derived, TypeInfo>& ind) {
ostr << ind.pretty_name();
ostr << static_cast<Derived const&>(ind).pretty_name();
return ostr;
}
/// @endcond
@ -271,13 +274,14 @@ inline std::basic_ostream<CharT, TriatT>& operator<<(
std::basic_ostream<CharT, TriatT>& ostr,
const type_index_facade<Derived, TypeInfo>& ind)
{
ostr << ind.pretty_name();
ostr << static_cast<Derived const&>(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 <boost/functional/hash.hpp> has to be included if this function is used.
template <class Derived, class TypeInfo>
inline std::size_t hash_value(const type_index_facade<Derived, TypeInfo>& lhs) BOOST_NOEXCEPT {
return static_cast<Derived const&>(lhs).hash_code();

View File

@ -297,7 +297,7 @@ BOOST_AUTO_TEST_CASE(comparators_type_id_runtime)
BOOST_CHECK(typeid(&rc1) == typeid(pb1));
BOOST_CHECK(typeid(&rb1) == typeid(pc1));
#else
BOOST_CHECK(boost::typeindex::type_index(pc1->type_id_runtime()).raw_name());
BOOST_CHECK(boost::typeindex::type_index(pc1->boost_type_index_type_id_runtime_()).raw_name());
#endif
BOOST_CHECK_EQUAL(boost::typeindex::type_id_runtime(rc1), boost::typeindex::type_id_runtime(*pc1));