Initial commit

This commit is contained in:
Antony Polukhin
2012-06-03 14:13:40 +04:00
commit a83bd35fee
5 changed files with 822 additions and 0 deletions

404
boost/type_index.hpp Normal file
View File

@@ -0,0 +1,404 @@
//
// Copyright (c) Antony Polukhin, 2012.
//
//
// 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_HPP
#define BOOST_TYPE_INDEX_HPP
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <cstring>
#include <string>
#include <boost/config.hpp>
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/current_function.hpp>
#include <boost/functional/hash_fwd.hpp>
#ifndef BOOST_NO_RTTI
#include <typeinfo>
#endif
#if !defined(BOOST_NO_IOSTREAM)
#if !defined(BOOST_NO_IOSFWD)
#include <iosfwd> // for std::basic_ostream
#else
#include <ostream>
#endif
#endif
#ifdef __GNUC__
#include <cxxabi.h>
#endif
namespace boost {
namespace detail {
#ifdef _MSC_VER
// sizeof("const char *__cdecl boost::detail::template_info<") - 1
BOOST_STATIC_CONSTANT(std::size_t, template_info_skip_size_at_begin = 49);
// sizeof(">::name(void)") - 1
BOOST_STATIC_CONSTANT(std::size_t, template_info_skip_size_at_end = 13);
#elif defined __clang__
// sizeof("static const char *boost::detail::template_info<") - 1
BOOST_STATIC_CONSTANT(std::size_t, template_info_skip_size_at_begin = 48);
// == sizeof(">::name()") - 1
BOOST_STATIC_CONSTANT(std::size_t, template_info_skip_size_at_end = 9);
#elif defined __GNUC__
// sizeof("static const char* boost::detail::template_info<T>::name() [with T = ") - 1
BOOST_STATIC_CONSTANT(std::size_t, template_info_skip_size_at_begin = 69);
// == sizeof("]") - 1
BOOST_STATIC_CONSTANT(std::size_t, template_info_skip_size_at_end = 1);
#else
// TODO: Code for other platforms
BOOST_STATIC_CONSTANT(std::size_t, template_info_skip_size_at_begin = 0); // skip nothing
BOOST_STATIC_CONSTANT(std::size_t, template_info_skip_size_at_end = 0); // skip nothing
#endif
/// Noncopyable type_info that does not require RTTI
template <class T>
struct template_info {
typedef T template_type;
typedef template_info this_type;
/// Retrurns raw name
static const char* name() {
return BOOST_CURRENT_FUNCTION + detail::template_info_skip_size_at_begin;
}
/// Returns true if the type precedes the type of rhs in the collation order.
/// The collation order is just an internal order.
template <class BefT>
static bool before() {
return std::strcmp(this_type::name(), template_info<BefT>::name_begin()) < 0;
}
/// Returns length of demangled name
static std::size_t name_length() {
return std::strlen(this_type::name()) - detail::template_info_skip_size_at_end;
}
/// Retrurns user-friendly name
static std::string name_demangled() {
return std::string(this_type::name(), this_type::name_length());
}
};
} // namespace detail
/// Copyable type_info that does not require RTTI
class template_index {
const char* name_;
explicit template_index(const char* name)
: name_(name)
{}
public:
/// Factory method for constructing template_index instance for type T
/// Strips const, volatile and & modifiers from T
template <class T>
static template_index construct(){
typedef BOOST_DEDUCED_TYPENAME boost::remove_reference<T>::type no_ref_t;
typedef BOOST_DEDUCED_TYPENAME boost::remove_cv<no_ref_t>::type no_cvr_t;
# if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \
|| (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744)
BOOST_STATIC_ASSERT_MSG( !boost::is_arithmetic<no_cvr_t>::type::value
, "Your EDG-based compiler seems to mistakenly distinguish 'int' from 'signed int', in typeid() expressions.");
#endif
return template_index(detail::template_info<no_cvr_t>::name());
}
/// Factory method for constructing template_index instance for type T.
/// Does not strips const, volatile and & modifiers from T
template <class T>
static template_index construct_with_cvr() {
# if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \
|| (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744)
BOOST_STATIC_ASSERT_MSG( !boost::is_arithmetic<T>::type::value
, "Your EDG-based compiler seems to mistakenly distinguish 'int' from 'signed int', in typeid() expressions.");
#endif
return template_index(detail::template_info<T>::name());
}
/// Returns true if the type precedes the type of rhs in the collation order.
/// The collation order is just an internal order.
bool before(const template_index& rhs) const {
return std::strcmp(name(), rhs.name()) < 0;
}
/// Retrurns raw name
const char* name() const {
return name_;
}
/// Retrurns user-friendly name
std::string name_demangled() const {
return std::string(name_, std::strlen(name_) - detail::template_info_skip_size_at_end);
}
bool operator == (const template_index& rhs) const {
return !std::strcmp(name_, rhs.name());
}
bool operator != (const template_index& rhs) const {
return !!std::strcmp(name_, rhs.name());
}
bool operator < (const template_index& rhs) const {
return std::strcmp(name_, rhs.name()) < 0;
}
bool operator > (const template_index& rhs) const {
return std::strcmp(name_, rhs.name()) > 0;
}
bool operator <= (const template_index& rhs) const {
return std::strcmp(name_, rhs.name()) <= 0;
}
bool operator >= (const template_index& rhs) const {
return std::strcmp(name_, rhs.name()) >= 0;
}
std::size_t hash_code() const {
return boost::hash_range(name_, name_ + std::strlen(name_));
}
};
#ifndef BOOST_NO_IOSTREAM
#ifdef BOOST_NO_TEMPLATED_IOSTREAMS
inline std::ostream& operator<<(std::ostream& ostr, template_index const& ind) {
ostr << ind.name_demangled();
return ostr;
}
#else
template <class CharT, class TriatT>
inline std::basic_ostream<CharT, TriatT>& operator<<(std::basic_ostream<CharT, TriatT>& ostr, template_index const& ind) {
ostr << ind.name_demangled();
return ostr;
}
#endif
#endif
inline std::size_t hash_value(template_index const& v) {
return v.hash_code();
}
template <>
struct hash<template_index> : public std::unary_function<template_index, std::size_t> {
std::size_t operator()(template_index const& v) const {
return boost::hash_value(v);
}
};
/// Method for constructing template_index instance for type T
/// Strips const, volatile and & modifiers from T
template <class T>
template_index template_id() {
return template_index::construct<T>();
}
/// Factory method for constructing template_index instance for type T.
/// Does not strips const, volatile and & modifiers from T
template <class T>
template_index template_id_with_cvr() {
return template_index::construct_with_cvr<T>();
}
#ifndef BOOST_NO_RTTI
// for this compiler at least, cross-shared-library type_info
// comparisons don't work, so use typeid(x).name() instead. It's not
// yet clear what the best default strategy is.
# if (defined(__GNUC__) && __GNUC__ >= 3) \
|| defined(_AIX) \
|| ( defined(__sgi) && defined(__host_mips)) \
|| (defined(__hpux) && defined(__HP_aCC)) \
|| (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC))
# define BOOST_CLASSINFO_COMPARE_BY_NAMES
# endif
/// Copyable type_info class that requires RTTI
class type_index {
public:
#ifdef BOOST_NO_STD_TYPEINFO
typedef type_info stl_type_index;
#else
typedef std::type_info stl_type_index;
#endif
const stl_type_index* pinfo_;
explicit type_index(const stl_type_index& inf)
: pinfo_(&inf)
{}
public:
/// Factory method for constructing type_index instance for type T
/// Strips const, volatile and & modifiers from T
template <class T>
static type_index construct() {
typedef BOOST_DEDUCED_TYPENAME boost::remove_reference<T>::type no_ref_t;
typedef BOOST_DEDUCED_TYPENAME boost::remove_cv<no_ref_t>::type no_cvr_t;
# if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \
|| (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744)
BOOST_STATIC_ASSERT_MSG( !boost::is_arithmetic<no_cvr_t>::type::value
, "Your EDG-based compiler seems to mistakenly distinguish 'int' from 'signed int', in typeid() expressions.");
#endif
return type_index(typeid(no_cvr_t));
}
/// Returns true if the type precedes the type of rhs in the collation order.
/// The collation order is just an internal order.
bool before(type_index const& rhs) const {
return !!pinfo_->before(*rhs.pinfo_);
}
/// Retrurns raw name
const char* name() const {
#ifdef _MSC_VER
return pinfo_->raw_name();
#else
return pinfo_->name();
#endif
}
/// Retrurns user-friendly name
std::string name_demangled() const {
#if defined(__GNUC__)
int status = 0 ;
char* demang = abi::__cxa_demangle(pinfo_->name(), NULL, 0, &status);
BOOST_ASSERT(!status);
std::string ret(demang);
free(demang);
return ret;
#else
return pinfo_->name();
#endif
}
bool operator == (type_index const& rhs) const {
#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
return !std::strcmp(pinfo_->name(), rhs.pinfo_->name());
#else
return *pinfo_ == *rhs.pinfo_;
#endif
}
bool operator != (type_index const& rhs) const {
return !(*this == rhs);
}
bool operator < (type_index const& rhs) const {
#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
return std::strcmp(pinfo_->name(), rhs.pinfo_->name()) < 0;
#else
return before(rhs);
#endif
}
bool operator > (type_index const& rhs) const {
return (rhs < *this);
}
bool operator <= (type_index const& rhs) const {
return !(*this > rhs);
}
bool operator >= (type_index const& rhs) const {
return !(*this < rhs);
}
std::size_t hash_code() const {
return boost::hash_range(name(), name() + std::strlen(name()));
}
};
#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
#undef BOOST_CLASSINFO_COMPARE_BY_NAMES
#endif
#ifndef BOOST_NO_IOSTREAM
#ifdef BOOST_NO_TEMPLATED_IOSTREAMS
inline std::ostream& operator<<(std::ostream& ostr, type_index const& ind) {
ostr << ind.name_demangled();
return ostr;
}
#else
template <class CharT, class TriatT>
inline std::basic_ostream<CharT, TriatT>& operator<<(std::basic_ostream<CharT, TriatT>& ostr, type_index const& ind) {
ostr << ind.name_demangled();
return ostr;
}
#endif
#endif
inline std::size_t hash_value(type_index const& v) {
return v.hash_code();
}
template <>
struct hash<type_index> : public std::unary_function<type_index, std::size_t> {
std::size_t operator()(type_index const& v) const {
return boost::hash_value(v);
}
};
/// Function, to get class_index for a type T
/// Strips const, volatile and & modifiers from T
template <class T>
type_index type_id() {
return type_index::construct<T>();
}
#else
// BOOST_NO_RTTI is defined
/// Default copyable type_info like class
typedef template_index type_index;
/// Function, to get class_index for a type T
/// Strips const, volatile and & modifiers from T
template <class T>
type_index type_id() {
return template_index::construct<T>();
}
#endif
} // namespace boost
#endif // BOOST_TYPE_INDEX_HPP

View File

@@ -0,0 +1,17 @@
# Copyright Antony Polukhin 2011.
# Use, modification, and distribution are
# subject to 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)
using quickbook ;
import boostbook : boostbook ;
xml type_index : type_index.qbk ;
boostbook standalone
:
type_index
:
<xsl:param>boost.root=../../../..
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html
;

View File

@@ -0,0 +1,123 @@
[library Boost.TypeIndex
[quickbook 1.5]
[version 1.0]
[copyright 2012 Antony Polukhin]
[category Language Features Emulation]
[license
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])
]
]
[section Motivation]
Sometimes getting and storing at runtime information about template type is required. For such cases usually used a construction like `&typeid(T)` or C++11 class `std::type_index`. And that is the point, where problems strat:
* `typeid(T)` and `std::type_index` require Run Time Type Info (RTTI)
* `typeid(T)` strips const, volatile and references from type
* some compilers have bugs and do not correctly compare `std::type_info` across shared libraries
* some implementations of `typeid(T)` do not strip const, volatile and references
* only a few STLs have `std::type_index` implementation
* no easy way to store type info without stripping const, volatile and references
* no nice and portable way to get human readable type name
Boost.TypeIndex was designed to work around those issues.
[endsect]
[section Getting started]
In short:
Just replace `&typeid(T)`, `typeid(T)` with `boost::type_id<T>()` and `const std::type_info&`, `std::type_index` with `boost::type_index`. That's all, you are now using Boost.TypeIndex.
To get nice human readable name, use `name_demangled()` member function:
``
type_index ti = type_id<T>();
std::string nice_name = ti.name_demangled();
...
std::string nice_name_with_const_volatile_ref = template_id_with_cvr<ParamT&>().name_demangled();
``
`template_index` and `type_index` have full set of comparison operators, hashing functions and ostream operators. Thay can be used with any container class.
If you need to save `const`, `volatile` and references, use `boost::template_index` instead of `boost::type_index`; `boost::template_id_with_cvr<T>()` instead of `boost::type_id<T>()`.
[endsect]
[section Examples]
All the code in examples will work with and without RTTI support.
Class that allows to register type only once.
``
class types_registry {
unordered_set<type_index> types_;
public:
template <class T>
void add_type() {
type_index ti = type_id<T>();
std::cout << "Adding type " << ti << " to registry \n";
if (!types_.insert(ti).second)
throw std::logic_error("Type " + ti.name_demangled() + " already in registry");
}
template <class T>
bool has_type() const {
return types_.cend() != types_.find(type_id<T>());
}
};
int main () {
types_registry tr;
tr.add_type<int>();
tr.add_type<float>();
std::cout << "Has type int: " << tr.has_type<int>()
<< "\nHas type std::string: " << tr.has_type<std::string>()
<< '\n';
}
``
This will output:
``
Adding type int to registry
Adding type float to registry
Has type int: 1
Has type std::string: 0
``
Another example (this time checking for exact parameter match).
`my_unary_function` is a class, that stroes function with result type `ResultT` and any input parameter type. In `opertaor()`, it checks for input parameter match and then executes the stored function:
``
template <class ResultT>
class my_unary_function {
void* function_ptr_;
template_index exact_param_t_;
...
template <class ParamT>
ResultT operator()(ParamT& v) {
BOOST_ASSERT(exact_param_t_ == template_id_with_cvr<ParamT&>());
return (static_cast<ResultT(ParamT&)>(function_ptr_))(v);
}
};
``
[endsect]
[section Reference]
TODO:
[endsect]
[section Performance]
`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 read-only section of binary file. Comparison operators are optimized as much as possible, and in worst case only execute `std::strcmp`. Calls to `std::string name_demangled()` for `type_index` do usually require dynamic memory allocation and some computations, so they are not recomended for usage in performance critical sections. Calls to `std::string name_demangled()` for `template_index` require only `std::strlen` call and are much faster than `std::string name_demangled()` for `type_index`.
`template_index` uses `BOOST_CURRENT_FUNCTION` macro, which could lead to code bloat. So if you do not need to save `const`, `volatile` and references, use `type_index`.
[endsect]

View File

@@ -0,0 +1,19 @@
# Copyright (C) 2012 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)
#
import testing ;
import feature ;
project
: requirements
<library>/boost/test//boost_unit_test_framework
<link>static
;
test-suite type_index
: [ run type_index_test.cpp ]
;

View File

@@ -0,0 +1,259 @@
//
// Copyright Antony Polukhin, 2012.
//
// 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)
#define BOOST_TEST_MODULE type_index_test_module
#include <boost/test/unit_test.hpp>
#include <boost/type_index.hpp>
#include <boost/functional/hash.hpp>
#include <boost/lexical_cast.hpp>
BOOST_AUTO_TEST_CASE(names_matches_type_id)
{
using namespace boost;
BOOST_CHECK_EQUAL(type_id<int>().name_demangled(), "int");
BOOST_CHECK_EQUAL(type_id<double>().name_demangled(), "double");
BOOST_CHECK_EQUAL(type_id<int>().name(), type_id<int>().name());
BOOST_CHECK_NE(type_id<int>().name(), type_id<double>().name());
BOOST_CHECK_NE(type_id<double>().name(), type_id<int>().name());
BOOST_CHECK_EQUAL(type_id<double>().name(), type_id<double>().name());
}
BOOST_AUTO_TEST_CASE(names_matches_template_id)
{
using namespace boost;
BOOST_CHECK_EQUAL(template_id<int>().name_demangled(), "int");
BOOST_CHECK_EQUAL(template_id<double>().name_demangled(), "double");
BOOST_CHECK_EQUAL(template_id<int>().name(), template_id<int>().name());
BOOST_CHECK_NE(template_id<int>().name(), template_id<double>().name());
BOOST_CHECK_NE(template_id<double>().name(), template_id<int>().name());
BOOST_CHECK_EQUAL(template_id<double>().name(), template_id<double>().name());
}
BOOST_AUTO_TEST_CASE(comparators_type_id)
{
using namespace boost;
type_index t_int = type_id<int>();
type_index t_double = type_id<double>();
BOOST_CHECK_EQUAL(t_int, t_int);
BOOST_CHECK_LE(t_int, t_int);
BOOST_CHECK_GE(t_int, t_int);
BOOST_CHECK_NE(t_int, t_double);
BOOST_CHECK_LE(t_double, t_double);
BOOST_CHECK_GE(t_double, t_double);
BOOST_CHECK_NE(t_double, t_int);
BOOST_CHECK(t_double < t_int || t_int < t_double);
BOOST_CHECK(t_double > t_int || t_int > t_double);
}
BOOST_AUTO_TEST_CASE(comparators_template_id)
{
using namespace boost;
template_index t_int = template_id<int>();
template_index t_double = template_id<double>();
BOOST_CHECK_EQUAL(t_int, t_int);
BOOST_CHECK_LE(t_int, t_int);
BOOST_CHECK_GE(t_int, t_int);
BOOST_CHECK_NE(t_int, t_double);
BOOST_CHECK_LE(t_double, t_double);
BOOST_CHECK_GE(t_double, t_double);
BOOST_CHECK_NE(t_double, t_int);
BOOST_CHECK(t_double < t_int || t_int < t_double);
BOOST_CHECK(t_double > t_int || t_int > t_double);
}
BOOST_AUTO_TEST_CASE(hash_code_type_id)
{
using namespace boost;
std::size_t t_int1 = type_id<int>().hash_code();
std::size_t t_double1 = type_id<double>().hash_code();
std::size_t t_int2 = type_id<int>().hash_code();
std::size_t t_double2 = type_id<double>().hash_code();
BOOST_CHECK_EQUAL(t_int1, t_int2);
BOOST_CHECK_NE(t_int1, t_double2);
BOOST_CHECK_LE(t_double1, t_double2);
}
BOOST_AUTO_TEST_CASE(hash_code_template_id)
{
using namespace boost;
std::size_t t_int1 = template_id<int>().hash_code();
std::size_t t_double1 = template_id<double>().hash_code();
std::size_t t_int2 = template_id<int>().hash_code();
std::size_t t_double2 = template_id<double>().hash_code();
BOOST_CHECK_EQUAL(t_int1, t_int2);
BOOST_CHECK_NE(t_int1, t_double2);
BOOST_CHECK_LE(t_double1, t_double2);
}
template <class T1, class T2>
static void test_with_modofiers() {
using namespace boost;
template_index t1 = template_id_with_cvr<T1>();
template_index t2 = template_id_with_cvr<T2>();
BOOST_CHECK_NE(t2, t1);
BOOST_CHECK(t1 < t2 || t2 < t1);
BOOST_CHECK(t1 > t2 || t2 > t1);
BOOST_CHECK_EQUAL(t1, template_id_with_cvr<T1>());
BOOST_CHECK_EQUAL(t2, template_id_with_cvr<T2>());
BOOST_CHECK_EQUAL(t1.hash_code(), template_id_with_cvr<T1>().hash_code());
BOOST_CHECK_EQUAL(t2.hash_code(), template_id_with_cvr<T2>().hash_code());
BOOST_CHECK_NE(t1.hash_code(), template_id_with_cvr<T2>().hash_code());
BOOST_CHECK_NE(t2.hash_code(), template_id_with_cvr<T1>().hash_code());
}
BOOST_AUTO_TEST_CASE(template_id_storing_modifiers)
{
test_with_modofiers<int, const int>();
test_with_modofiers<int, const int&>();
test_with_modofiers<int, int&>();
test_with_modofiers<int, volatile int>();
test_with_modofiers<int, volatile int&>();
test_with_modofiers<int, const volatile int>();
test_with_modofiers<int, const volatile int&>();
test_with_modofiers<const int, int>();
test_with_modofiers<const int, const int&>();
test_with_modofiers<const int, int&>();
test_with_modofiers<const int, volatile int>();
test_with_modofiers<const int, volatile int&>();
test_with_modofiers<const int, const volatile int>();
test_with_modofiers<const int, const volatile int&>();
test_with_modofiers<const int&, int>();
test_with_modofiers<const int&, const int>();
test_with_modofiers<const int&, int&>();
test_with_modofiers<const int&, volatile int>();
test_with_modofiers<const int&, volatile int&>();
test_with_modofiers<const int&, const volatile int>();
test_with_modofiers<const int&, const volatile int&>();
test_with_modofiers<int&, const int>();
test_with_modofiers<int&, const int&>();
test_with_modofiers<int&, int>();
test_with_modofiers<int&, volatile int>();
test_with_modofiers<int&, volatile int&>();
test_with_modofiers<int&, const volatile int>();
test_with_modofiers<int&, const volatile int&>();
}
BOOST_AUTO_TEST_CASE(stream_operator_via_lexical_cast_testing)
{
using namespace boost;
std::string s_int1 = lexical_cast<std::string>(type_id<int>());
BOOST_CHECK_EQUAL(s_int1, "int");
std::string s_int2 = lexical_cast<std::string>(template_id<int>());
BOOST_CHECK_EQUAL(s_int2, "int");
std::string s_double1 = lexical_cast<std::string>(type_id<double>());
BOOST_CHECK_EQUAL(s_double1, "double");
std::string s_double2 = lexical_cast<std::string>(template_id<double>());
BOOST_CHECK_EQUAL(s_double2, "double");
}
BOOST_AUTO_TEST_CASE(type_index_stripping_cvr_test)
{
using namespace boost;
BOOST_CHECK_EQUAL(type_id<int>(), type_id<const int>());
BOOST_CHECK_EQUAL(type_id<int>(), type_id<const volatile int>());
BOOST_CHECK_EQUAL(type_id<int>(), type_id<const volatile int&>());
BOOST_CHECK_EQUAL(type_id<int>(), type_id<int&>());
BOOST_CHECK_EQUAL(type_id<int>(), type_id<volatile int>());
BOOST_CHECK_EQUAL(type_id<int>(), type_id<volatile int&>());
BOOST_CHECK_EQUAL(type_id<double>(), type_id<const double>());
BOOST_CHECK_EQUAL(type_id<double>(), type_id<const volatile double>());
BOOST_CHECK_EQUAL(type_id<double>(), type_id<const volatile double&>());
BOOST_CHECK_EQUAL(type_id<double>(), type_id<double&>());
BOOST_CHECK_EQUAL(type_id<double>(), type_id<volatile double>());
BOOST_CHECK_EQUAL(type_id<double>(), type_id<volatile double&>());
}
BOOST_AUTO_TEST_CASE(template_index_stripping_cvr_test)
{
using namespace boost;
BOOST_CHECK_EQUAL(template_id<int>(), template_id<const int>());
BOOST_CHECK_EQUAL(template_id<int>(), template_id<const volatile int>());
BOOST_CHECK_EQUAL(template_id<int>(), template_id<const volatile int&>());
BOOST_CHECK_EQUAL(template_id<int>(), template_id<int&>());
BOOST_CHECK_EQUAL(template_id<int>(), template_id<volatile int>());
BOOST_CHECK_EQUAL(template_id<int>(), template_id<volatile int&>());
BOOST_CHECK_EQUAL(template_id<double>(), template_id<const double>());
BOOST_CHECK_EQUAL(template_id<double>(), template_id<const volatile double>());
BOOST_CHECK_EQUAL(template_id<double>(), template_id<const volatile double&>());
BOOST_CHECK_EQUAL(template_id<double>(), template_id<double&>());
BOOST_CHECK_EQUAL(template_id<double>(), template_id<volatile double>());
BOOST_CHECK_EQUAL(template_id<double>(), template_id<volatile double&>());
}
namespace my_namespace1 {
class my_class{};
}
namespace my_namespace2 {
class my_class{};
}
BOOST_AUTO_TEST_CASE(template_index_user_defined_class_test)
{
using namespace boost;
BOOST_CHECK_EQUAL(template_id<my_namespace1::my_class>(), template_id<my_namespace1::my_class>());
BOOST_CHECK_EQUAL(template_id<my_namespace2::my_class>(), template_id<my_namespace2::my_class>());
BOOST_CHECK_NE(template_id<my_namespace1::my_class>(), template_id<my_namespace2::my_class>());
BOOST_CHECK_NE(
template_id<my_namespace1::my_class>().name_demangled().find("my_namespace1::my_class"),
std::string::npos);
BOOST_CHECK_EQUAL(type_id<my_namespace1::my_class>(), type_id<my_namespace1::my_class>());
BOOST_CHECK_EQUAL(type_id<my_namespace2::my_class>(), type_id<my_namespace2::my_class>());
BOOST_CHECK_NE(type_id<my_namespace1::my_class>(), type_id<my_namespace2::my_class>());
BOOST_CHECK_NE(
type_id<my_namespace1::my_class>().name_demangled().find("my_namespace1::my_class"),
std::string::npos);
}