blob: 9b1dc532015ce82228882726b56a6e84ee10000e [file] [log] [blame]
/*
* Copyright Andrey Semashev 2007 - 2015.
* 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)
*/
/*!
* \file type_info_wrapper.hpp
* \author Andrey Semashev
* \date 15.04.2007
*
* The header contains implementation of a type information wrapper.
*/
#ifndef BOOST_LOG_UTILITY_TYPE_INFO_WRAPPER_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_TYPE_INFO_WRAPPER_HPP_INCLUDED_
#include <typeinfo>
#include <string>
#include <boost/core/demangle.hpp>
#include <boost/core/explicit_operator_bool.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
/*!
* \brief A simple <tt>std::type_info</tt> wrapper that implements value semantic for type information objects
*
* The type info wrapper is very useful for storing type information objects in containers,
* as a key or value. It also provides a number of useful features, such as default construction
* and assignment support, an empty state and extended support for human-friendly type names.
*/
class type_info_wrapper
{
private:
#ifndef BOOST_LOG_DOXYGEN_PASS
//! An inaccessible type to indicate an uninitialized state of the wrapper
struct BOOST_SYMBOL_VISIBLE uninitialized {};
#endif // BOOST_LOG_DOXYGEN_PASS
private:
//! A pointer to the actual type info
std::type_info const* info;
public:
/*!
* Default constructor
*
* \post <tt>!*this == true</tt>
*/
type_info_wrapper() BOOST_NOEXCEPT : info(&typeid(uninitialized)) {}
/*!
* Copy constructor
*
* \post <tt>*this == that</tt>
* \param that Source type info wrapper to copy from
*/
type_info_wrapper(type_info_wrapper const& that) BOOST_NOEXCEPT : info(that.info) {}
/*!
* Conversion constructor
*
* \post <tt>*this == that && !!*this</tt>
* \param that Type info object to be wrapped
*/
type_info_wrapper(std::type_info const& that) BOOST_NOEXCEPT : info(&that) {}
/*!
* \return \c true if the type info wrapper was initialized with a particular type,
* \c false if the wrapper was default-constructed and not yet initialized
*/
BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
/*!
* Stored type info getter
*
* \pre <tt>!!*this</tt>
* \return Constant reference to the wrapped type info object
*/
std::type_info const& get() const BOOST_NOEXCEPT { return *info; }
/*!
* Swaps two instances of the wrapper
*/
void swap(type_info_wrapper& that) BOOST_NOEXCEPT
{
std::type_info const* temp = info;
info = that.info;
that.info = temp;
}
/*!
* The method returns the contained type name string in a possibly more readable format than <tt>get().name()</tt>
*
* \pre <tt>!!*this</tt>
* \return Type name string
*/
std::string pretty_name() const
{
if (!this->operator!())
return boost::core::demangle(info->name());
else
return "[uninitialized]";
}
/*!
* \return \c false if the type info wrapper was initialized with a particular type,
* \c true if the wrapper was default-constructed and not yet initialized
*/
bool operator! () const BOOST_NOEXCEPT { return (info == &typeid(uninitialized) || *info == typeid(uninitialized)); }
/*!
* Equality comparison
*
* \param that Comparand
* \return If either this object or comparand is in empty state and the other is not, the result is \c false.
* If both arguments are empty, the result is \c true. If both arguments are not empty, the result
* is \c true if this object wraps the same type as the comparand and \c false otherwise.
*/
bool operator== (type_info_wrapper const& that) const BOOST_NOEXCEPT
{
return (info == that.info || *info == *that.info);
}
/*!
* Ordering operator
*
* \pre <tt>!!*this && !!that</tt>
* \param that Comparand
* \return \c true if this object wraps type info object that is ordered before
* the type info object in the comparand, \c false otherwise
* \note The results of this operator are only consistent within a single run of application.
* The result may change for the same types after rebuilding or even restarting the application.
*/
bool operator< (type_info_wrapper const& that) const BOOST_NOEXCEPT
{
return static_cast< bool >(info->before(*that.info));
}
};
//! Inequality operator
inline bool operator!= (type_info_wrapper const& left, type_info_wrapper const& right) BOOST_NOEXCEPT
{
return !left.operator==(right);
}
//! Ordering operator
inline bool operator<= (type_info_wrapper const& left, type_info_wrapper const& right) BOOST_NOEXCEPT
{
return (left.operator==(right) || left.operator<(right));
}
//! Ordering operator
inline bool operator> (type_info_wrapper const& left, type_info_wrapper const& right) BOOST_NOEXCEPT
{
return !(left.operator==(right) || left.operator<(right));
}
//! Ordering operator
inline bool operator>= (type_info_wrapper const& left, type_info_wrapper const& right) BOOST_NOEXCEPT
{
return !left.operator<(right);
}
//! Free swap for type info wrapper
inline void swap(type_info_wrapper& left, type_info_wrapper& right) BOOST_NOEXCEPT
{
left.swap(right);
}
//! The function for exception serialization to string
inline std::string to_string(type_info_wrapper const& ti)
{
return ti.pretty_name();
}
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_TYPE_INFO_WRAPPER_HPP_INCLUDED_