diff options
Diffstat (limited to 'src/boost/libs/type_index')
34 files changed, 2687 insertions, 0 deletions
diff --git a/src/boost/libs/type_index/CMakeLists.txt b/src/boost/libs/type_index/CMakeLists.txt new file mode 100644 index 000000000..e37950ac9 --- /dev/null +++ b/src/boost/libs/type_index/CMakeLists.txt @@ -0,0 +1,26 @@ +# Copyright 2019 Mike Dev +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt +# +# NOTE: CMake support for Boost.TypeIndex is currently experimental at best +# and the interface is likely to change in the future + +cmake_minimum_required(VERSION 3.5) +project(Boost.TypeIndex) + +add_library(boost_type_index INTERFACE) +add_library(Boost::type_index ALIAS boost_type_index) + +target_include_directories(boost_type_index INTERFACE include) + +target_link_libraries(boost_type_index + INTERFACE + Boost::config + Boost::container_hash + Boost::core + Boost::preprocessor + Boost::smart_ptr + Boost::static_assert + Boost::throw_exception + Boost::type_traits +) diff --git a/src/boost/libs/type_index/README.md b/src/boost/libs/type_index/README.md new file mode 100644 index 000000000..19db50381 --- /dev/null +++ b/src/boost/libs/type_index/README.md @@ -0,0 +1,18 @@ +# [Boost.TypeIndex](http://boost.org/libs/type_index) +Boost.TypeIndex is a part of the [Boost C++ Libraries](http://github.com/boostorg). It is a runtime/compile time copyable type info. + +### Test results + +@ | Build | Tests coverage | More info +----------------|-------------- | -------------- |----------- +Develop branch: | [![Build Status](https://travis-ci.org/apolukhin/type_index.svg?branch=develop)](https://travis-ci.org/apolukhin/type_index) [![Build status](https://ci.appveyor.com/api/projects/status/197a5imq10dqx6r8/branch/develop?svg=true)](https://ci.appveyor.com/project/apolukhin/type-index/branch/develop) | [![Coverage Status](https://coveralls.io/repos/apolukhin/type_index/badge.png?branch=develop)](https://coveralls.io/r/apolukhin/type_index?branch=develop) | [details...](http://www.boost.org/development/tests/develop/developer/type_index.html) +Master branch: | [![Build Status](https://travis-ci.org/apolukhin/type_index.svg?branch=master)](https://travis-ci.org/apolukhin/type_index) [![Build status](https://ci.appveyor.com/api/projects/status/197a5imq10dqx6r8/branch/master?svg=true)](https://ci.appveyor.com/project/apolukhin/type-index/branch/master) | [![Coverage Status](https://coveralls.io/repos/apolukhin/type_index/badge.png?branch=master)](https://coveralls.io/r/apolukhin/type_index?branch=master) | [details...](http://www.boost.org/development/tests/master/developer/type_index.html) + + +[Open Issues](https://svn.boost.org/trac/boost/query?status=!closed&component=type_index) + +[Latest developer documentation](http://boostorg.github.com/type_index/index.html) + +### License + +Distributed under the [Boost Software License, Version 1.0](http://boost.org/LICENSE_1_0.txt). diff --git a/src/boost/libs/type_index/examples/constexpr14_namespace_check.cpp b/src/boost/libs/type_index/examples/constexpr14_namespace_check.cpp new file mode 100644 index 000000000..09fc4a6d5 --- /dev/null +++ b/src/boost/libs/type_index/examples/constexpr14_namespace_check.cpp @@ -0,0 +1,97 @@ +// Copyright 2013-2020 Antony Polukhin + +// Distributed under the Boost Software License, Version 1.0. +// (See the accompanying file LICENSE_1_0.txt +// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.) + +#include <boost/config.hpp> + +template <class T> +void do_something(const T&) {} + + +#if !defined(BOOST_NO_CXX14_CONSTEXPR) && !defined(BOOST_NO_CXX11_CONSTEXPR) +// Implementation of this function is not essential for the example +template <std::size_t N> +constexpr bool starts_with(const char* name, const char (&ns)[N]) noexcept { + for (std::size_t i = 0; i < N - 1; ++i) + if (name[i] != ns[i]) + return false; + + return true; +} + +//[type_index_constexpr14_namespace_example +/*` + The following example shows that `boost::typeindex::ctti_type_index` is usable at compile time on + a C++14 compatible compilers. + + In this example we'll create and use a constexpr function that checks namespace of the provided type. +*/ + +#include <boost/type_index/ctti_type_index.hpp> + +// Helper function that returns true if `name` starts with `substr` +template <std::size_t N> +constexpr bool starts_with(const char* name, const char (&substr)[N]) noexcept; + + +// Function that returns true if `T` declared in namespace `ns` +template <class T, std::size_t N> +constexpr bool in_namespace(const char (&ns)[N]) noexcept { + const char* name = boost::typeindex::ctti_type_index::type_id<T>().raw_name(); + + // Some compilers add `class ` or `struct ` before the namespace, so we need to skip those words first + if (starts_with(name, "class ")) { + name += sizeof("class ") - 1; + } else if (starts_with(name, "struct ")) { + name += sizeof("struct ") - 1; + } + + return starts_with(name, ns) && starts_with(name + N - 1, "::"); +} + +/*` + Now when we have that wonderfull function, we can do static assertions and other compile-time validations: +*/ + +namespace my_project { + struct serializer { + template <class T> + void serialize(const T& value) { + static_assert( + in_namespace<T>("my_project::types") || in_namespace<T>("my_project::types_ext"), + "Only types from namespaces `my_project::types` and `my_project::types_ext` are allowed to be serialized using `my_project::serializer`" + ); + + // Actual implementation of the serialization goes below + // ... + do_something(value); + } + }; + + namespace types { + struct foo{}; + struct bar{}; + } +} // namespace my_project + +int main() { + my_project::serializer s; + my_project::types::foo f; + my_project::types::bar b; + + s.serialize(f); + s.serialize(b); + + // short sh = 0; + // s.serialize(sh); // Fails the static_assert! +} +//] [/type_index_constexpr14_namespace_example] + +#else // #if !defined(BOOST_NO_CXX14_CONSTEXPR) && !defined(BOOST_NO_CXX11_CONSTEXPR) + +int main() {} + +#endif + diff --git a/src/boost/libs/type_index/examples/constexpr14_sort_check.cpp b/src/boost/libs/type_index/examples/constexpr14_sort_check.cpp new file mode 100644 index 000000000..c89b7e3bd --- /dev/null +++ b/src/boost/libs/type_index/examples/constexpr14_sort_check.cpp @@ -0,0 +1,76 @@ +// Copyright 2013-2020 Antony Polukhin + +// Distributed under the Boost Software License, Version 1.0. +// (See the accompanying file LICENSE_1_0.txt +// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.) + +#include <boost/config.hpp> + +#if !defined(BOOST_NO_CXX14_CONSTEXPR) && !defined(BOOST_NO_CXX11_CONSTEXPR) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && (!defined(_MSC_VER) || (_MSC_VER > 1916)) + +//[type_index_constexpr14_sort_check_example +/*` + The following example shows that `boost::typeindex::ctti_type_index` is usable at compile time on + a C++14 compatible compilers to check order of template parameters. + + Consider the situation when we have a function that accepts std::tuple, boost::variant or some other class that uses variadic templates: +*/ + +template <class... T> class types{}; + +template <class... T> +void do_something(const types<T...>& t) noexcept; + +/*` + Such functions may be very usefull, however they may significantly increase the size of the resulting program. Each instantionation of such function with different templates order + consumes space in the resulting program: + + // Types are same, but different order leads to new instantionation of do_something function. + types<bool, double, int> + types<bool, int, double> + types<int, bool, double> + types<int, double, bool> + types<double, int, bool> + types<double, bool, int> + + One of the ways to reduce instantinations count is to force the types to have some order: +*/ + + +#include <boost/type_index/ctti_type_index.hpp> + +// Implementing type trait that returns true if the types are sorted lexographicaly +template <class... T> +constexpr bool is_asc_sorted(types<T...>) noexcept { + return true; +} + +template <class Lhs, class Rhs, class... TN> +constexpr bool is_asc_sorted(types<Lhs, Rhs, TN...>) noexcept { + using namespace boost::typeindex; + return ctti_type_index::type_id<Lhs>() <= ctti_type_index::type_id<Rhs>() + && is_asc_sorted(types<Rhs, TN...>()); +} + + +// Using the newly created `is_asc_sorted` trait: +template <class... T> +void do_something(const types<T...>& /*value*/) noexcept { + static_assert( + is_asc_sorted( types<T...>() ), + "T... for do_something(const types<T...>& t) must be sorted ascending" + ); +} + +int main() { + do_something( types<bool, double, int>() ); + // do_something( types<bool, int, double>() ); // Fails the static_assert! +} +//] [/type_index_constexpr14_sort_check_example] + +#else // #if !defined(BOOST_NO_CXX14_CONSTEXPR) && !defined(BOOST_NO_CXX11_CONSTEXPR) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && (!defined(_MSC_VER) || (_MSC_VER > 1916)) + +int main() {} + +#endif + diff --git a/src/boost/libs/type_index/examples/demangled_names.cpp b/src/boost/libs/type_index/examples/demangled_names.cpp new file mode 100644 index 000000000..c0589a91b --- /dev/null +++ b/src/boost/libs/type_index/examples/demangled_names.cpp @@ -0,0 +1,76 @@ +// Copyright 2013-2020 Antony Polukhin + +// Distributed under the Boost Software License, Version 1.0. +// (See the accompanying file LICENSE_1_0.txt +// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.) + + +//[type_index_names_example +/*` + The following example shows how short (mangled) and human readable type names could be obtained from a type. + Works with and without RTTI. +*/ + + +#include <boost/type_index.hpp> +#include <iostream> + +template <class T> +void foo(T) { + std::cout << "\n Short name: " << boost::typeindex::type_id<T>().raw_name(); + std::cout << "\n Readable name: " << boost::typeindex::type_id<T>().pretty_name(); +} + +struct user_defined_type{}; + +namespace ns1 { namespace ns2 { + struct user_defined_type{}; +}} // namespace ns1::ns2 + +namespace { + struct in_anon_type{}; +} // anonymous namespace + +int main() { + // Call to + foo(1); + // will output something like this: + // + // (RTTI on) (RTTI off) + // Short name: i Short name: int] + // Readable name: int Readable name: int + + user_defined_type t; + foo(t); + // Will output: + // + // (RTTI on) (RTTI off) + // Short name: 17user_defined_type user_defined_type] + // Readable name: user_defined_type user_defined_type + + ns1::ns2::user_defined_type t_in_ns; + foo(t_in_ns); + // Will output: + // + // (RTTI on) (RTTI off) + // Short name: N3ns13ns217user_defined_typeE ns1::ns2::user_defined_type] + // Readable name: ns1::ns2::user_defined_type ns1::ns2::user_defined_type + + in_anon_type anon_t; + foo(anon_t); + // Will output: + // + // (RTTI on) (RTTI off) + // Short name: N12_GLOBAL__N_112in_anon_typeE {anonymous}::in_anon_type] + // Readable name: (anonymous namespace)::in_anon_type {anonymous}::in_anon_type +} + +/*` + Short names are very compiler dependant: some compiler will output `.H`, others `i`. + + Readable names may also differ between compilers: `struct user_defined_type`, `user_defined_type`. + + [warning With RTTI off different classes with same names in anonymous namespace may collapse. See 'RTTI emulation limitations'. ] +*/ + +//] [/type_index_names_example] diff --git a/src/boost/libs/type_index/examples/exact_types_match.cpp b/src/boost/libs/type_index/examples/exact_types_match.cpp new file mode 100644 index 000000000..bf3a44b96 --- /dev/null +++ b/src/boost/libs/type_index/examples/exact_types_match.cpp @@ -0,0 +1,74 @@ +// Copyright 2013-2020 Antony Polukhin + +// Distributed under the Boost Software License, Version 1.0. +// (See the accompanying file LICENSE_1_0.txt +// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.) + +//[type_index_exact_type_match_example +/*` + 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 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> +#include <iostream> +#include <stdexcept> +#include <cstdlib> + +//<- +// Making `#include <cassert>` visible in docs, while actually using hand-made check +// instead of `assert`. This is required to verify correct behavior even if NDEBUG +// is defined and to avoid `unused local variable` warnings with defined NDEBUG. +#ifdef assert +# undef assert +#endif +#define assert(X) if (!(X)) std::exit(__LINE__) + /* !Comment block is not closed intentionaly! +//-> +#include <cassert> +//<- + !Closing comment block! */ +//-> + +class type_erased_unary_function { + void* function_ptr_; + boost::typeindex::type_index exact_param_t_; + +public: + template <class ParamT> + type_erased_unary_function(void(*ptr)(ParamT)) + : function_ptr_(reinterpret_cast<void*>(ptr)) // ptr - is a pointer to function returning `void` and accepting parameter of type `ParamT` + , exact_param_t_(boost::typeindex::type_id_with_cvr<ParamT>()) + {} + + template <class ParamT> + void call(ParamT v) { + if (exact_param_t_ != boost::typeindex::type_id_with_cvr<ParamT>()) { + throw std::runtime_error("Incorrect `ParamT`"); + } + + return (reinterpret_cast<void(*)(ParamT)>(function_ptr_))(v); + } +}; + +void foo(int){} + +int main() { + type_erased_unary_function func(&foo); + func.call(100); // OK, `100` has type `int` + + try { + int i = 100; + + // An attempt to convert stored function to a function accepting reference + func.call<int&>(i); // Will throw, because types `int&` and `int` mismatch + + assert(false); + } catch (const std::runtime_error& /*e*/) {} +} + +//] [/type_index_exact_type_match_example] diff --git a/src/boost/libs/type_index/examples/inheritance.cpp b/src/boost/libs/type_index/examples/inheritance.cpp new file mode 100644 index 000000000..199937895 --- /dev/null +++ b/src/boost/libs/type_index/examples/inheritance.cpp @@ -0,0 +1,47 @@ +// Copyright 2013-2020 Antony Polukhin + +// Distributed under the Boost Software License, Version 1.0. +// (See the accompanying file LICENSE_1_0.txt +// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.) + +//[type_index_derived_example +/*` + The following example shows that `type_info` is able to store the real type, successfully getting through + all the inheritances. + + Example works with and without RTTI." +*/ + +#include <boost/type_index.hpp> +#include <boost/type_index/runtime_cast/register_runtime_class.hpp> +#include <iostream> + +struct A { + BOOST_TYPE_INDEX_REGISTER_CLASS + virtual ~A(){} +}; +struct B: public A { BOOST_TYPE_INDEX_REGISTER_CLASS }; +struct C: public B { BOOST_TYPE_INDEX_REGISTER_CLASS }; +struct D: public C { BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(BOOST_TYPE_INDEX_NO_BASE_CLASS) }; + +void print_real_type(const A& a) { + std::cout << boost::typeindex::type_id_runtime(a).pretty_name() << '\n'; +} + +int main() { + C c; + const A& c_as_a = c; + print_real_type(c_as_a); // Outputs `struct C` + print_real_type(B()); // Outputs `struct B` + +/*` + It's also possible to use type_id_runtime with the BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS, which adds additional + information for runtime_cast to work. +*/ + D d; + const A& d_as_a = d; + print_real_type(d_as_a); // Outputs `struct D` + +} + +//] [/type_index_derived_example] diff --git a/src/boost/libs/type_index/examples/registry.cpp b/src/boost/libs/type_index/examples/registry.cpp new file mode 100644 index 000000000..28f216825 --- /dev/null +++ b/src/boost/libs/type_index/examples/registry.cpp @@ -0,0 +1,53 @@ +// Copyright 2013-2020 Antony Polukhin + +// Distributed under the Boost Software License, Version 1.0. +// (See the accompanying file LICENSE_1_0.txt +// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.) + +//[type_index_registry_example +/*` + The following example shows how an information about a type could be stored. + Example works with and without RTTI. +*/ + +#include <boost/type_index.hpp> +#include <boost/unordered/unordered_set.hpp> +//<- +// Making `#include <cassert>` visible in docs, while actually using `BOOST_TEST` +// instead of `assert`. This is required to verify correct behavior even if NDEBUG +// is defined and to avoid `unused local variable` warnings with defined NDEBUG. +#include <boost/core/lightweight_test.hpp> +#ifdef assert +# undef assert +#endif +#define assert(X) BOOST_TEST(X) + /* !Comment block is not closed intentionaly! +//-> +#include <cassert> +//<- + !Closing comment block! */ +//-> + +int main() { + boost::unordered_set<boost::typeindex::type_index> types; + + // Storing some `boost::type_info`s + types.insert(boost::typeindex::type_id<int>()); + types.insert(boost::typeindex::type_id<float>()); + + // `types` variable contains two `boost::type_index`es: + assert(types.size() == 2); + + // Const, volatile and reference will be striped from the type: + bool is_inserted = types.insert(boost::typeindex::type_id<const int>()).second; + assert(!is_inserted); + assert(types.erase(boost::typeindex::type_id<float&>()) == 1); + + // We have erased the `float` type, only `int` remains + assert(*types.begin() == boost::typeindex::type_id<int>()); +//<- + return boost::report_errors(); +//-> +} + +//] [/type_index_registry_example] diff --git a/src/boost/libs/type_index/examples/runtime_cast.cpp b/src/boost/libs/type_index/examples/runtime_cast.cpp new file mode 100644 index 000000000..43e7aa70f --- /dev/null +++ b/src/boost/libs/type_index/examples/runtime_cast.cpp @@ -0,0 +1,90 @@ +// +// Copyright (c) Chris Glover, 2016. +// +// +// 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) +// + +//[type_index_runtime_cast_example +/*` + The following example shows that `runtime_cast` is able to find a valid pointer + in various class hierarchies regardless of inheritance or type relation. + + Example works with and without RTTI." +*/ + +#include <boost/type_index/runtime_cast.hpp> +#include <iostream> + +struct A { + BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(BOOST_TYPE_INDEX_NO_BASE_CLASS) + virtual ~A() + {} +}; + +struct B { + BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(BOOST_TYPE_INDEX_NO_BASE_CLASS) + virtual ~B() + {} +}; + +struct C : A { + BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS((A)) +}; + +struct D : B { + BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS((B)) +}; + +struct E : C, D { + BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS((C)(D)) +}; + +int main() { + C c; + A* a = &c; + + if(C* cp = boost::typeindex::runtime_cast<C*>(a)) { + std::cout << "Yes, a points to a C: " + << a << "->" << cp << '\n'; + } + else { + std::cout << "Error: Expected a to point to a C" << '\n'; + } + + if(E* ce = boost::typeindex::runtime_cast<E*>(a)) { + std::cout << "Error: Expected a to not points to an E: " + << a << "->" << ce << '\n'; + } + else { + std::cout << "But, a does not point to an E" << '\n'; + } + + E e; + C* cp2 = &e; + if(D* dp = boost::typeindex::runtime_cast<D*>(cp2)) { + std::cout << "Yes, we can cross-cast from a C* to a D* when we actually have an E: " + << cp2 << "->" << dp << '\n'; + } + else { + std::cout << "Error: Expected cp to point to a D" << '\n'; + } + +/*` + Alternatively, we can use runtime_pointer_cast so we don't need to specity the target as a pointer. + This works for smart_ptr types too. +*/ + A* ap = &e; + if(B* bp = boost::typeindex::runtime_pointer_cast<B>(ap)) { + std::cout << "Yes, we can cross-cast and up-cast at the same time." + << ap << "->" << bp << '\n'; + } + else { + std::cout << "Error: Expected ap to point to a B" << '\n'; + } + + return 0; +} + +//] [/type_index_runtime_cast_example] diff --git a/src/boost/libs/type_index/examples/table_of_names.cpp b/src/boost/libs/type_index/examples/table_of_names.cpp new file mode 100644 index 000000000..d51487d78 --- /dev/null +++ b/src/boost/libs/type_index/examples/table_of_names.cpp @@ -0,0 +1,90 @@ +// Copyright 2013-2020 Antony Polukhin + +// Distributed under the Boost Software License, Version 1.0. +// (See the accompanying file LICENSE_1_0.txt +// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.) + + +//[type_index_names_table +/*` + The following example shows how different type names look when we explicitly use classes for RTTI and RTT off. + + This example requires RTTI. For a more portable example see 'Getting human readable and mangled type names': +*/ + + +#include <boost/type_index/stl_type_index.hpp> +#include <boost/type_index/ctti_type_index.hpp> +#include <iostream> + +template <class T> +void print(const char* name) { + boost::typeindex::stl_type_index sti = boost::typeindex::stl_type_index::type_id<T>(); + boost::typeindex::ctti_type_index cti = boost::typeindex::ctti_type_index::type_id<T>(); + std::cout << "\t[" /* start of the row */ + << "[" << name << "]" + << "[`" << sti.raw_name() << "`] " + << "[`" << sti.pretty_name() << "`] " + << "[`" << cti.raw_name() << "`] " + << "]\n" /* end of the row */ ; +} + +struct user_defined_type{}; + +namespace ns1 { namespace ns2 { + struct user_defined_type{}; +}} // namespace ns1::ns2 + +namespace { + struct in_anon_type{}; +} // anonymous namespace + +namespace ns3 { namespace { namespace ns4 { + struct in_anon_type{}; +}}} // namespace ns3::{anonymous}::ns4 + + +template <class T0, class T1> +class templ {}; + +template <> +class templ<int, int> {}; + +int main() { + std::cout << "[table:id Table of names\n"; + std::cout << "\t[[Type] [RTTI & raw_name] [RTTI & pretty_name] [noRTTI & raw_name]]\n"; + + print<user_defined_type>("User defined type"); + print<in_anon_type>("In anonymous namespace"); + print<ns3::ns4::in_anon_type>("In ns3::{anonymous}::ns4 namespace"); + print<templ<short, int> >("Template class"); + print<templ<int, int> >("Template class (full specialization)"); + print<templ< + templ<char, signed char>, + templ<int, user_defined_type> + > >("Template class with templae classes"); + + + std::cout << "]\n"; +} + +/*` + Code from the example will produce the following table: + + [table:id Table of names + [[Type] [RTTI & raw_name] [RTTI & pretty_name] [noRTTI & raw_name]] + [[User defined type][`17user_defined_type`] [`user_defined_type`] [`user_defined_type]`] ] + [[In anonymous namespace][`N12_GLOBAL__N_112in_anon_typeE`] [`(anonymous namespace)::in_anon_type`] [`{anonymous}::in_anon_type]`] ] + [[In ns3::{anonymous}::ns4 namespace][`N3ns312_GLOBAL__N_13ns412in_anon_typeE`] [`ns3::(anonymous namespace)::ns4::in_anon_type`] [`ns3::{anonymous}::ns4::in_anon_type]`] ] + [[Template class][`5templIsiE`] [`templ<short, int>`] [`templ<short int, int>]`] ] + [[Template class (full specialization)][`5templIiiE`] [`templ<int, int>`] [`templ<int, int>]`] ] + [[Template class with template classes][`5templIS_IcaES_Ii17user_defined_typeEE`] [`templ<templ<char, signed char>, templ<int, user_defined_type> >`] [`templ<templ<char, signed char>, templ<int, user_defined_type> >]`] ] + ] + + We have not show the "noRTTI & pretty_name" column in the table because it is almost equal + to "noRTTI & raw_name" column. + + [warning With RTTI off different classes with same names in anonymous namespace may collapse. See 'RTTI emulation limitations'. ] +*/ + +//] [/type_index_names_table] diff --git a/src/boost/libs/type_index/examples/user_defined_typeinfo.cpp b/src/boost/libs/type_index/examples/user_defined_typeinfo.cpp new file mode 100644 index 000000000..ba6e01e22 --- /dev/null +++ b/src/boost/libs/type_index/examples/user_defined_typeinfo.cpp @@ -0,0 +1,72 @@ +// Copyright 2013-2020 Antony Polukhin + +// Distributed under the Boost Software License, Version 1.0. +// (See the accompanying file LICENSE_1_0.txt +// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.) + + +//[type_index_my_type_index_worldwide_macro +/*` + There is an easy way to force `boost::typeindex::type_id` to use your own type_index class. + + All we need to do is just define `BOOST_TYPE_INDEX_USER_TYPEINDEX` to the full path to header file + of your type index class: +*/ + +// BOOST_TYPE_INDEX_USER_TYPEINDEX must be defined *BEFORE* first inclusion of <boost/type_index.hpp> +#define BOOST_TYPE_INDEX_USER_TYPEINDEX <boost/../libs/type_index/examples/user_defined_typeinfo.hpp> +#include <boost/type_index.hpp> +//] [/type_index_my_type_index_worldwide_macro] + +#include <boost/core/lightweight_test.hpp> +#ifdef assert +# undef assert +#endif +#define assert(X) BOOST_TEST(X) + + +using namespace my_namespace; + +int main() { +//[type_index_my_type_index_usage +/*` + Finally we can use the my_type_index class for getting type indexes: +*/ + + my_type_index + cl1 = my_type_index::type_id<my_class>(), + st1 = my_type_index::type_id<my_struct>(), + st2 = my_type_index::type_id<my_struct>(), + vec = my_type_index::type_id<my_classes>() + ; + + assert(cl1 != st1); + assert(st2 == st1); + assert(vec.pretty_name() == "my_classes"); + assert(cl1.pretty_name() == "my_class"); + +//] [/type_index_my_type_index_usage] + +//[type_index_my_type_index_type_id_runtime_test +/*` + Now the following example will compile and work. +*/ + my_struct str; + my_class& reference = str; + assert(my_type_index::type_id<my_struct>() == my_type_index::type_id_runtime(reference)); +//][/type_index_my_type_index_type_id_runtime_test] + +//[type_index_my_type_index_worldwide_usage +/*` + That's it! Now all TypeIndex global methods and typedefs will be using your class: +*/ + boost::typeindex::type_index worldwide = boost::typeindex::type_id<my_classes>(); + assert(worldwide.pretty_name() == "my_classes"); + assert(worldwide == my_type_index::type_id<my_classes>()); +//][/type_index_my_type_index_worldwide_usage] +//<- + return boost::report_errors(); +//-> +} + + diff --git a/src/boost/libs/type_index/examples/user_defined_typeinfo.hpp b/src/boost/libs/type_index/examples/user_defined_typeinfo.hpp new file mode 100644 index 000000000..1bc020e82 --- /dev/null +++ b/src/boost/libs/type_index/examples/user_defined_typeinfo.hpp @@ -0,0 +1,213 @@ +// Copyright 2013-2020 Antony Polukhin + +// Distributed under the Boost Software License, Version 1.0. +// (See the accompanying file LICENSE_1_0.txt +// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.) + +#ifndef USER_DEFINED_TYPEINFO_HPP +#define USER_DEFINED_TYPEINFO_HPP + +//[type_index_userdefined_usertypes +/*` + The following example shows how a user defined type_info can be created and used. + Example works with and without RTTI. + + Consider situation when user uses only those types in `typeid()`: +*/ + +#include <vector> +#include <string> + +namespace my_namespace { + +class my_class; +struct my_struct; + +typedef std::vector<my_class> my_classes; +typedef std::string my_string; + +} // namespace my_namespace + +//] [/type_index_userdefined_usertypes] + + +//[type_index_userdefined_enum +/*` + In that case user may wish to save space in binary and create it's own type system. + For that case `detail::typenum<>` meta function is added. Depending on the input type T + this function will return different numeric values. +*/ +#include <boost/type_index/type_index_facade.hpp> + +namespace my_namespace { namespace detail { + template <class T> struct typenum; + template <> struct typenum<void>{ enum {value = 0}; }; + template <> struct typenum<my_class>{ enum {value = 1}; }; + template <> struct typenum<my_struct>{ enum {value = 2}; }; + template <> struct typenum<my_classes>{ enum {value = 3}; }; + template <> struct typenum<my_string>{ enum {value = 4}; }; + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4510 4512 4610) // non-copyable non-constructable type +#endif + + // my_typeinfo structure is used to save type number + struct my_typeinfo { + const char* const type_; + }; + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + + const my_typeinfo infos[5] = { + {"void"}, {"my_class"}, {"my_struct"}, {"my_classes"}, {"my_string"} + }; + + template <class T> + inline const my_typeinfo& my_typeinfo_construct() { + return infos[typenum<T>::value]; + } +}} // my_namespace::detail + +//] [/type_index_userdefined_usertypes] + + +//[type_index_my_type_index +/*` + `my_type_index` is a user created type_index class. If in doubt during this phase, you can always + take a look at the `<boost/type_index/ctti_type_index.hpp>` or `<boost/type_index/stl_type_index.hpp>` + files. Documentation for `type_index_facade` could be also useful. +*/ + +/*` + Since we are not going to override `type_index_facade::hash_code()` we must additionally include + `<boost/container_hash/hash.hpp>`. +*/ +#include <boost/container_hash/hash.hpp> + +/*` + See implementation of `my_type_index`: +*/ +namespace my_namespace { + +class my_type_index: public boost::typeindex::type_index_facade<my_type_index, detail::my_typeinfo> { + const detail::my_typeinfo* data_; + +public: + typedef detail::my_typeinfo type_info_t; + + inline my_type_index() BOOST_NOEXCEPT + : data_(&detail::my_typeinfo_construct<void>()) + {} + + inline my_type_index(const type_info_t& data) BOOST_NOEXCEPT + : data_(&data) + {} + + inline const type_info_t& type_info() const BOOST_NOEXCEPT { + return *data_; + } + + inline const char* raw_name() const BOOST_NOEXCEPT { + return data_->type_; + } + + inline std::string pretty_name() const { + return data_->type_; + } + + template <class T> + inline static my_type_index type_id() BOOST_NOEXCEPT { + return detail::my_typeinfo_construct<T>(); + } + + template <class T> + inline static my_type_index type_id_with_cvr() BOOST_NOEXCEPT { + return detail::my_typeinfo_construct<T>(); + } + + template <class T> + inline static my_type_index type_id_runtime(const T& variable) BOOST_NOEXCEPT; +}; + +} // namespace my_namespace + +/*` + Note that we have used the boost::typeindex::type_index_facade class as base. + That class took care about all the helper function and operators (comparison, hashing, ostreaming and others). +*/ + +//] [/type_index_my_type_index] + +//[type_index_my_type_index_register_class +/*` + Usually to allow runtime type info we need to register class with some macro. + Let's see how a `MY_TYPEINDEX_REGISTER_CLASS` macro could be implemented for our `my_type_index` class: +*/ +namespace my_namespace { namespace detail { + + template <class T> + inline const my_typeinfo& my_typeinfo_construct_ref(const T*) { + return my_typeinfo_construct<T>(); + } + +#define MY_TYPEINDEX_REGISTER_CLASS \ + virtual const my_namespace::detail::my_typeinfo& type_id_runtime() const { \ + return my_namespace::detail::my_typeinfo_construct_ref(this); \ + } + +}} // namespace my_namespace::detail + +//] [/type_index_my_type_index_register_class] + +//[type_index_my_type_index_type_id_runtime_implmentation +/*` + Now when we have a MY_TYPEINDEX_REGISTER_CLASS, let's implement a `my_type_index::type_id_runtime` method: +*/ +namespace my_namespace { + template <class T> + my_type_index my_type_index::type_id_runtime(const T& variable) BOOST_NOEXCEPT { + // Classes that were marked with `MY_TYPEINDEX_REGISTER_CLASS` will have a + // `type_id_runtime()` method. + return variable.type_id_runtime(); + } +} +//] [/type_index_my_type_index_type_id_runtime_implmentation] + +//[type_index_my_type_index_type_id_runtime_classes +/*` + Consider the situation, when `my_class` and `my_struct` are polymorphic classes: +*/ + +namespace my_namespace { + +class my_class { +public: + MY_TYPEINDEX_REGISTER_CLASS + virtual ~my_class() {} +}; + +struct my_struct: public my_class { + MY_TYPEINDEX_REGISTER_CLASS +}; + +} // namespace my_namespace + +//] [/type_index_my_type_index_type_id_runtime_classes] + + +//[type_index_my_type_index_worldwide_typedefs +/*` + You'll also need to add some typedefs and macro to your "user_defined_typeinfo.hpp" header file: +*/ +#define BOOST_TYPE_INDEX_REGISTER_CLASS MY_TYPEINDEX_REGISTER_CLASS +namespace boost { namespace typeindex { + typedef my_namespace::my_type_index type_index; +}} +//] [/type_index_my_type_index_worldwide_typedefs] + + +#endif // USER_DEFINED_TYPEINFO_HPP + diff --git a/src/boost/libs/type_index/index.html b/src/boost/libs/type_index/index.html new file mode 100644 index 000000000..845e62cc4 --- /dev/null +++ b/src/boost/libs/type_index/index.html @@ -0,0 +1,35 @@ +<!DOCTYPE html> +<!-- + Copyright 2014 Antony Polukhin + antoshkka at gmail dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +--> +<html> +<head> +<meta charset="utf-8"> +<meta http-equiv="refresh" content="0; url=../../doc/html/boost_typeindex.html"> +<title>Boost.TypeIndex</title> +<style> + body { + background: #fff; + color: #000; + } + a { + color: #00f; + text-decoration: none; + } +</style> +</head> +<body> + <p> + Automatic redirection failed, please go to + <a href="../../doc/html/boost_typeindex.html">../../doc/html/boost_typeindex.html</a> + </p> + <p> + © 2014 Antony Polukhin + </p> +</body> +</html> diff --git a/src/boost/libs/type_index/meta/libraries.json b/src/boost/libs/type_index/meta/libraries.json new file mode 100644 index 000000000..5fff00aaf --- /dev/null +++ b/src/boost/libs/type_index/meta/libraries.json @@ -0,0 +1,14 @@ +{ + "key": "type_index", + "name": "Type Index", + "authors": [ + "Antony Polukhin" + ], + "maintainers": [ + "Antony Polukhin <antoshkka -at- gmail.com>" + ], + "description": "Runtime/Compile time copyable type info.", + "category": [ + "Emulation" + ] +} diff --git a/src/boost/libs/type_index/patched/README.md b/src/boost/libs/type_index/patched/README.md new file mode 100644 index 000000000..4dab0d690 --- /dev/null +++ b/src/boost/libs/type_index/patched/README.md @@ -0,0 +1,9 @@ +patches for Boost libraries to work without RTTI +========== + +Here are the patches that are TESTED and work well with RTTI disabled and enabled. +Patches add tests for some of the libraries to make sure that library compile and work without RTTI. + +Patches remove duplicate code, improve output, allow compilation with RTTI off... + +Libraries Boost.Graph, Boost.XPressive, Boost.PropertyMap and others may also benefit from TypeIndex library. diff --git a/src/boost/libs/type_index/patched/boost_detail_sp_typeinfo.patch b/src/boost/libs/type_index/patched/boost_detail_sp_typeinfo.patch new file mode 100644 index 000000000..b0649e0d3 --- /dev/null +++ b/src/boost/libs/type_index/patched/boost_detail_sp_typeinfo.patch @@ -0,0 +1,151 @@ +From b77c0af6af8bc4797defc3627878acc3cf7a6f39 Mon Sep 17 00:00:00 2001 +From: Antony Polukhin <antoshkka@gmail.com> +Date: Thu, 20 Feb 2014 17:57:24 +0400 +Subject: [PATCH] detail/sp_typeinfo.hpp now uses TypeIndex + +--- + include/boost/detail/sp_typeinfo.hpp | 123 +++-------------------------------- + 1 file changed, 8 insertions(+), 115 deletions(-) + +diff --git a/include/boost/detail/sp_typeinfo.hpp b/include/boost/detail/sp_typeinfo.hpp +index 43fae78..fbdf86d 100644 +--- a/include/boost/detail/sp_typeinfo.hpp ++++ b/include/boost/detail/sp_typeinfo.hpp +@@ -10,126 +10,19 @@ + // detail/sp_typeinfo.hpp + // + // Copyright 2007 Peter Dimov ++// Copyright 2014 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) + +-#include <boost/config.hpp> ++#include <boost/type_index.hpp> ++namespace boost { namespace detail { ++ ++typedef boost::typeind::type_info sp_typeinfo; ++ ++}} // namespace boost::detail + +-#if defined( BOOST_NO_TYPEID ) +- +-#include <boost/current_function.hpp> +-#include <functional> +- +-namespace boost +-{ +- +-namespace detail +-{ +- +-class sp_typeinfo +-{ +-private: +- +- sp_typeinfo( sp_typeinfo const& ); +- sp_typeinfo& operator=( sp_typeinfo const& ); +- +- char const * name_; +- +-public: +- +- explicit sp_typeinfo( char const * name ): name_( name ) +- { +- } +- +- bool operator==( sp_typeinfo const& rhs ) const +- { +- return this == &rhs; +- } +- +- bool operator!=( sp_typeinfo const& rhs ) const +- { +- return this != &rhs; +- } +- +- bool before( sp_typeinfo const& rhs ) const +- { +- return std::less< sp_typeinfo const* >()( this, &rhs ); +- } +- +- char const* name() const +- { +- return name_; +- } +-}; +- +-template<class T> struct sp_typeid_ +-{ +- static sp_typeinfo ti_; +- +- static char const * name() +- { +- return BOOST_CURRENT_FUNCTION; +- } +-}; +- +-#if defined(__SUNPRO_CC) +-// see #4199, the Sun Studio compiler gets confused about static initialization +-// constructor arguments. But an assignment works just fine. +-template<class T> sp_typeinfo sp_typeid_< T >::ti_ = sp_typeid_< T >::name(); +-#else +-template<class T> sp_typeinfo sp_typeid_< T >::ti_(sp_typeid_< T >::name()); +-#endif +- +-template<class T> struct sp_typeid_< T & >: sp_typeid_< T > +-{ +-}; +- +-template<class T> struct sp_typeid_< T const >: sp_typeid_< T > +-{ +-}; +- +-template<class T> struct sp_typeid_< T volatile >: sp_typeid_< T > +-{ +-}; +- +-template<class T> struct sp_typeid_< T const volatile >: sp_typeid_< T > +-{ +-}; +- +-} // namespace detail +- +-} // namespace boost +- +-#define BOOST_SP_TYPEID(T) (boost::detail::sp_typeid_<T>::ti_) +- +-#else +- +-#include <typeinfo> +- +-namespace boost +-{ +- +-namespace detail +-{ +- +-#if defined( BOOST_NO_STD_TYPEINFO ) +- +-typedef ::type_info sp_typeinfo; +- +-#else +- +-typedef std::type_info sp_typeinfo; +- +-#endif +- +-} // namespace detail +- +-} // namespace boost +- +-#define BOOST_SP_TYPEID(T) typeid(T) +- +-#endif ++#define BOOST_SP_TYPEID(T) (boost::typeind::type_id<T>().type_info()) + + #endif // #ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED +-- +1.8.5.3 + diff --git a/src/boost/libs/type_index/patched/boost_exception.patch b/src/boost/libs/type_index/patched/boost_exception.patch new file mode 100644 index 000000000..9b3643e05 --- /dev/null +++ b/src/boost/libs/type_index/patched/boost_exception.patch @@ -0,0 +1,156 @@ +From 8f57d59bfbc978673a2493a90b4f3e7e54ddbf18 Mon Sep 17 00:00:00 2001 +From: Antony Polukhin <antoshkka@gmail.com> +Date: Thu, 20 Feb 2014 18:30:11 +0400 +Subject: [PATCH] Boost.Exception now uses TypeIndex to reduce duplicate code + and simplify name demanglings + +--- + include/boost/exception/detail/type_info.hpp | 43 +++------------------- + include/boost/exception/diagnostic_information.hpp | 2 +- + include/boost/exception/exception.hpp | 3 +- + include/boost/exception/info.hpp | 2 +- + test/Jamfile.v2 | 2 + + 5 files changed, 12 insertions(+), 40 deletions(-) + +diff --git a/include/boost/exception/detail/type_info.hpp b/include/boost/exception/detail/type_info.hpp +index 6e5942d..a247b71 100644 +--- a/include/boost/exception/detail/type_info.hpp ++++ b/include/boost/exception/detail/type_info.hpp +@@ -12,13 +12,7 @@ + #pragma warning(push,1) + #endif + +-#include <boost/detail/sp_typeinfo.hpp> +-#include <boost/current_function.hpp> +-#include <boost/config.hpp> +-//#ifndef BOOST_NO_TYPEID +-//#include <boost/units/detail/utility.hpp> +-//#endif +-#include <string> ++#include <boost/type_index.hpp> + + namespace + boost +@@ -28,11 +22,7 @@ boost + std::string + tag_type_name() + { +-#ifdef BOOST_NO_TYPEID +- return BOOST_CURRENT_FUNCTION; +-#else +- return /*units::detail::demangle*/(typeid(T*).name()); +-#endif ++ return boost::typeind::type_id<T*>().pretty_name(); + } + + template <class T> +@@ -40,41 +30,20 @@ boost + std::string + type_name() + { +-#ifdef BOOST_NO_TYPEID +- return BOOST_CURRENT_FUNCTION; +-#else +- return /*units::detail::demangle*/(typeid(T).name()); +-#endif ++ return boost::typeind::type_id<T>().pretty_name(); + } + + namespace + exception_detail + { +- struct +- type_info_ +- { +- detail::sp_typeinfo const * type_; +- +- explicit +- type_info_( detail::sp_typeinfo const & type ): +- type_(&type) +- { +- } +- +- friend +- bool +- operator<( type_info_ const & a, type_info_ const & b ) +- { +- return 0!=(a.type_->before(*b.type_)); +- } +- }; ++ typedef boost::typeind::type_index type_info_; + } + } + +-#define BOOST_EXCEPTION_STATIC_TYPEID(T) ::boost::exception_detail::type_info_(BOOST_SP_TYPEID(T)) ++#define BOOST_EXCEPTION_STATIC_TYPEID(T) ::boost::typeind::type_id<T>() + + #ifndef BOOST_NO_RTTI +-#define BOOST_EXCEPTION_DYNAMIC_TYPEID(x) ::boost::exception_detail::type_info_(typeid(x)) ++#define BOOST_EXCEPTION_DYNAMIC_TYPEID(x) ::boost::typeind::type_id_runtime(x) + #endif + + #if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +diff --git a/include/boost/exception/diagnostic_information.hpp b/include/boost/exception/diagnostic_information.hpp +index 2f5cb88..0f8b5e8 100644 +--- a/include/boost/exception/diagnostic_information.hpp ++++ b/include/boost/exception/diagnostic_information.hpp +@@ -151,7 +151,7 @@ boost + #ifndef BOOST_NO_RTTI + if ( verbose ) + tmp << std::string("Dynamic exception type: ") << +- /*units::detail::demangle*/((be?(BOOST_EXCEPTION_DYNAMIC_TYPEID(*be)):(BOOST_EXCEPTION_DYNAMIC_TYPEID(*se))).type_->name()) << '\n'; ++ /*units::detail::demangle*/((be?(BOOST_EXCEPTION_DYNAMIC_TYPEID(*be)):(BOOST_EXCEPTION_DYNAMIC_TYPEID(*se)))) << '\n'; + #endif + if( with_what && se && verbose ) + tmp << "std::exception::what: " << wh << '\n'; +diff --git a/include/boost/exception/exception.hpp b/include/boost/exception/exception.hpp +index 9f20a04..53c341f 100644 +--- a/include/boost/exception/exception.hpp ++++ b/include/boost/exception/exception.hpp +@@ -12,6 +12,8 @@ + #pragma warning(push,1) + #endif + ++#include <boost/exception/detail/type_info.hpp> ++ + namespace + boost + { +@@ -151,7 +153,6 @@ boost + exception_detail + { + class error_info_base; +- struct type_info_; + + struct + error_info_container +diff --git a/include/boost/exception/info.hpp b/include/boost/exception/info.hpp +index edbf058..e0f4950 100644 +--- a/include/boost/exception/info.hpp ++++ b/include/boost/exception/info.hpp +@@ -96,7 +96,7 @@ boost + { + shared_ptr<error_info_base> const & p = i->second; + #ifndef BOOST_NO_RTTI +- BOOST_ASSERT( *BOOST_EXCEPTION_DYNAMIC_TYPEID(*p).type_==*ti.type_ ); ++ BOOST_ASSERT(BOOST_EXCEPTION_DYNAMIC_TYPEID(*p)==ti ); + #endif + return p; + } +diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 +index d2dfcd6..5bd076d 100644 +--- a/test/Jamfile.v2 ++++ b/test/Jamfile.v2 +@@ -35,7 +35,9 @@ run enable_error_info_test.cpp helper1.cpp ; + run throw_exception_test.cpp helper2.cpp ; + run errno_test.cpp ; + run error_info_test.cpp ; ++run error_info_test.cpp : : : <rtti>off : error_info_test_rtti ; + run diagnostic_information_test.cpp ; ++run diagnostic_information_test.cpp : : : <rtti>off : diagnostic_information_test_rtti ; + run refcount_ptr_test.cpp ; + run current_exception_cast_test.cpp ; + run no_exceptions_test.cpp : : : <exception-handling>off ; +-- +1.8.5.3 + diff --git a/src/boost/libs/type_index/patched/boost_smart_ptr.patch b/src/boost/libs/type_index/patched/boost_smart_ptr.patch new file mode 100644 index 000000000..5120199ce --- /dev/null +++ b/src/boost/libs/type_index/patched/boost_smart_ptr.patch @@ -0,0 +1,26 @@ +From 03194eefcb9c3314054855d28bd9a90d3188768d Mon Sep 17 00:00:00 2001 +From: Antony Polukhin <antoshkka@gmail.com> +Date: Thu, 20 Feb 2014 18:50:10 +0400 +Subject: [PATCH] Use TypeIndex features in Boost.SharedPtr to avoid type_info + related bugs + +--- + include/boost/smart_ptr/detail/sp_counted_impl.hpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/boost/smart_ptr/detail/sp_counted_impl.hpp b/include/boost/smart_ptr/detail/sp_counted_impl.hpp +index a7b43ae..5955036 100644 +--- a/include/boost/smart_ptr/detail/sp_counted_impl.hpp ++++ b/include/boost/smart_ptr/detail/sp_counted_impl.hpp +@@ -155,7 +155,7 @@ public: + + virtual void * get_deleter( detail::sp_typeinfo const & ti ) + { +- return ti == BOOST_SP_TYPEID(D)? &reinterpret_cast<char&>( del ): 0; ++ return ti == boost::typeind::type_id<D>()? &reinterpret_cast<char&>( del ): 0; + } + + virtual void * get_untyped_deleter() +-- +1.8.5.3 + diff --git a/src/boost/libs/type_index/test/Jamfile.v2 b/src/boost/libs/type_index/test/Jamfile.v2 new file mode 100644 index 000000000..22779cbce --- /dev/null +++ b/src/boost/libs/type_index/test/Jamfile.v2 @@ -0,0 +1,81 @@ +# Copyright 2012-2020 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 ; +import os ; + +# Variable that contains all the stuff required for linking together <rtti>on and <rtti>off +compat = <define>BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY ; + +# Making own `nortti` that is link compatible. +# We explicitly define BOOST_NO_RTTI because it sometimes can not be detected by build system. +nortti = <toolset>gcc:<cxxflags>"-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID" <toolset>clang:<cxxflags>"-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID" <toolset>intel:<cxxflags>"-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID" <toolset>darwin:<cxxflags>"-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID" <toolset>msvc:<cxxflags>"/GR-" ; + +norttidefines = <toolset>gcc:<cxxflags>"-DBOOST_NO_RTTI -DBOOST_NO_TYPEID" <toolset>clang:<cxxflags>"-DBOOST_NO_RTTI -DBOOST_NO_TYPEID" <toolset>intel:<cxxflags>"-DBOOST_NO_RTTI -DBOOST_NO_TYPEID" <toolset>darwin:<cxxflags>"-DBOOST_NO_RTTI -DBOOST_NO_TYPEID" <toolset>msvc:<cxxflags>"-DBOOST_NO_RTTI" ; + + +# Making libraries that CANNOT work between rtti-on/rtti-off modules +obj test_lib_nortti-obj : test_lib.cpp : <link>shared <rtti>off $(norttidefines) ; +obj test_lib_anonymous_nortti-obj : test_lib_anonymous.cpp : <link>shared <rtti>off $(norttidefines) ; +lib test_lib_nortti : test_lib_nortti-obj : <link>shared <rtti>off $(norttidefines) ; +lib test_lib_anonymous_nortti : test_lib_anonymous_nortti-obj : <link>shared <rtti>off $(norttidefines) ; + +obj test_lib_rtti-obj : test_lib.cpp : <link>shared ; +obj test_lib_anonymous_rtti-obj : test_lib_anonymous.cpp : <link>shared ; +lib test_lib_rtti : test_lib_rtti-obj : <link>shared ; +lib test_lib_anonymous_rtti : test_lib_anonymous_rtti-obj : <link>shared ; + +# Making libraries that can work between rtti-on/rtti-off modules +obj test_lib_nortti_compat-obj : test_lib.cpp : <link>shared $(nortti) $(compat) ; +obj test_lib_rtti_compat-obj : test_lib.cpp : <link>shared $(nortti) $(compat) ; +lib test_lib_nortti_compat : test_lib_nortti_compat-obj : <link>shared $(nortti) $(compat) ; +lib test_lib_rtti_compat : test_lib_rtti_compat-obj : <link>shared $(nortti) $(compat) ; + +exe testing_crossmodule_anonymous_no_rtti : testing_crossmodule_anonymous.cpp test_lib_anonymous_nortti : <rtti>off $(norttidefines) ; + +test-suite type_index + : + [ run type_index_test.cpp ] + [ run type_index_runtime_cast_test.cpp ] + [ run type_index_constexpr_test.cpp ] + [ run type_index_test.cpp : : : <rtti>off $(norttidefines) : type_index_test_no_rtti ] + [ run ctti_print_name.cpp : : : <test-info>always_show_run_output ] + [ run testing_crossmodule.cpp test_lib_rtti ] + [ run testing_crossmodule.cpp test_lib_nortti : : : <rtti>off $(norttidefines) : testing_crossmodule_no_rtti ] + [ run testing_crossmodule_anonymous.cpp test_lib_anonymous_rtti : : : <test-info>always_show_run_output ] + [ run compare_ctti_stl.cpp ] + [ run track_13621.cpp ] + + [ compile-fail type_index_test_ctti_copy_fail.cpp ] + [ compile-fail type_index_test_ctti_construct_fail.cpp ] + [ compile type_index_test_ctti_alignment.cpp ] + + # Mixing RTTI on and off + + # MSVC sometimes overrides the /GR-, without `detect_missmatch` this test may link. + # TODO: Disabled on MSVC. Enable again when there'll be an understanding of how to write this test correctly wor MSVC. + [ link-fail testing_crossmodule.cpp test_lib_rtti : $(nortti) <toolset>msvc:<build>no : link_fail_nortti_rtti ] + [ link-fail testing_crossmodule.cpp test_lib_nortti : <toolset>msvc:<build>no : link_fail_rtti_nortti ] + + [ run testing_crossmodule.cpp test_lib_rtti_compat : : : $(nortti) $(compat) : testing_crossmodule_nortti_rtti_compat ] + [ run testing_crossmodule.cpp test_lib_nortti_compat : : : $(compat) : testing_crossmodule_rtti_nortti_compat ] + ; + +# Assuring that examples compile and run. Adding sources from `examples` directory to the `type_index` test suite. +for local p in [ glob ../examples/*.cpp ] +{ + # RTTI on + type_index += [ run $(p) ] ; + + # RTTI off + local target_name = $(p[1]:B)_no_rtti ; + if $(target_name) != "table_of_names_no_rtti" + { + type_index += [ run $(p) : : : <rtti>off $(norttidefines) : $(target_name) ] ; + } +} + diff --git a/src/boost/libs/type_index/test/compare_ctti_stl.cpp b/src/boost/libs/type_index/test/compare_ctti_stl.cpp new file mode 100644 index 000000000..c7f2ec30d --- /dev/null +++ b/src/boost/libs/type_index/test/compare_ctti_stl.cpp @@ -0,0 +1,67 @@ +// Copyright Klemens Morgenstern, 2012-2015. +// Copyright 2019-2020 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) + +#include <boost/type_index/ctti_type_index.hpp> +#include <boost/type_index/stl_type_index.hpp> +#include <boost/core/lightweight_test.hpp> + + +namespace my_namespace1 { + class my_class{}; +} + + +namespace my_namespace2 { + class my_class{}; +} + +namespace my_namespace3 +{ +template<typename T, typename U> +struct my_template {}; + +} + +#if !defined( BOOST_NO_RTTI ) + +template<typename T> +void compare() +{ + typedef boost::typeindex::ctti_type_index ctti; + typedef boost::typeindex::stl_type_index stl; + BOOST_TEST_EQ( + ctti::type_id<int>().pretty_name(), + stl::type_id<int>().pretty_name() + ); +} + + +int main() +{ + compare<void>(); + compare<int>(); + compare<double*>(); + compare<const double&>(); + compare<my_namespace1::my_class>(); + + compare<my_namespace3::my_template< + my_namespace1::my_class, + my_namespace2::my_class> >(); + + + return boost::report_errors(); +} + +#else + +int main() +{ + return 0; +} + +#endif + diff --git a/src/boost/libs/type_index/test/ctti_print_name.cpp b/src/boost/libs/type_index/test/ctti_print_name.cpp new file mode 100644 index 000000000..c16c8b465 --- /dev/null +++ b/src/boost/libs/type_index/test/ctti_print_name.cpp @@ -0,0 +1,44 @@ +// +// Copyright 2012-2020 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) + +#include <iostream> + +// This cpp file: +// * tests BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING macro +// * outputs full ctti name so that TypeIndex library could be adjust to new compiler without requesting regression tester's help +#define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING (0,0,false,"") +#include <boost/type_index/ctti_type_index.hpp> + +namespace user_defined_namespace { + class user_defined_class {}; +} + +class empty +{ +}; + + +int main() +{ + using namespace boost::typeindex; + + std::cout << "int: " + << ctti_type_index::type_id<int>() << '\n'; + + std::cout << "double: " + << ctti_type_index::type_id<double>() << '\n'; + + std::cout << "user_defined_namespace::user_defined_class: " + << ctti_type_index::type_id<user_defined_namespace::user_defined_class>() << '\n'; + + + std::cout << "empty:" + << ctti_type_index::type_id<empty>() << '\n'; + + return 0; +} + diff --git a/src/boost/libs/type_index/test/test_lib.cpp b/src/boost/libs/type_index/test/test_lib.cpp new file mode 100644 index 000000000..174a7fecf --- /dev/null +++ b/src/boost/libs/type_index/test/test_lib.cpp @@ -0,0 +1,40 @@ +// +// Copyright 2012-2020 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) +// + +#define TEST_LIB_SOURCE +#include "test_lib.hpp" + +namespace user_defined_namespace { + class user_defined{}; +} + +namespace test_lib { + +boost::typeindex::type_index get_integer() { + return boost::typeindex::type_id<int>(); +} + +boost::typeindex::type_index get_user_defined_class() { + return boost::typeindex::type_id<user_defined_namespace::user_defined>(); +} + +boost::typeindex::type_index get_const_integer() { + return boost::typeindex::type_id_with_cvr<const int>(); +} + +boost::typeindex::type_index get_const_user_defined_class() { + return boost::typeindex::type_id_with_cvr<const user_defined_namespace::user_defined>(); +} + +#if !defined(BOOST_HAS_PRAGMA_DETECT_MISMATCH) || !defined(_CPPRTTI) +// Just do nothing +void accept_typeindex(const boost::typeindex::type_index&) {} +#endif + +} + diff --git a/src/boost/libs/type_index/test/test_lib.hpp b/src/boost/libs/type_index/test/test_lib.hpp new file mode 100644 index 000000000..7619008fe --- /dev/null +++ b/src/boost/libs/type_index/test/test_lib.hpp @@ -0,0 +1,42 @@ +// +// Copyright 2012-2020 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_TESTS_TEST_LIB_HPP +#define BOOST_TYPE_INDEX_TESTS_TEST_LIB_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +#include <boost/type_index.hpp> + +// This is ALWAYS a dynamic library +#if defined(TEST_LIB_SOURCE) +# define TEST_LIB_DECL BOOST_SYMBOL_EXPORT +# else +# define TEST_LIB_DECL BOOST_SYMBOL_IMPORT +# endif + +namespace test_lib { + +TEST_LIB_DECL boost::typeindex::type_index get_integer(); +TEST_LIB_DECL boost::typeindex::type_index get_user_defined_class(); + +TEST_LIB_DECL boost::typeindex::type_index get_const_integer(); +TEST_LIB_DECL boost::typeindex::type_index get_const_user_defined_class(); + +#if !defined(BOOST_HAS_PRAGMA_DETECT_MISMATCH) || !defined(_CPPRTTI) +// This is required for checking RTTI on/off linkage +TEST_LIB_DECL void accept_typeindex(const boost::typeindex::type_index&); +#endif + +} + +#endif // BOOST_TYPE_INDEX_TESTS_LIB1_HPP + diff --git a/src/boost/libs/type_index/test/test_lib_anonymous.cpp b/src/boost/libs/type_index/test/test_lib_anonymous.cpp new file mode 100644 index 000000000..53f4307d4 --- /dev/null +++ b/src/boost/libs/type_index/test/test_lib_anonymous.cpp @@ -0,0 +1,27 @@ +// +// Copyright 2012-2020 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) +// + +#define TEST_LIB_SOURCE +#include "test_lib_anonymous.hpp" + +namespace { + class user_defined{}; +} // anonymous namespace + +namespace test_lib { + +boost::typeindex::type_index get_anonymous_user_defined_class() { + return boost::typeindex::type_id<user_defined>(); +} + +boost::typeindex::type_index get_const_anonymous_user_defined_class() { + return boost::typeindex::type_id_with_cvr<const user_defined>(); +} + +} + diff --git a/src/boost/libs/type_index/test/test_lib_anonymous.hpp b/src/boost/libs/type_index/test/test_lib_anonymous.hpp new file mode 100644 index 000000000..15165eb1b --- /dev/null +++ b/src/boost/libs/type_index/test/test_lib_anonymous.hpp @@ -0,0 +1,34 @@ +// +// Copyright 2012-2020 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_TESTS_TEST_LIB_ANONYMOUS_HPP +#define BOOST_TYPE_INDEX_TESTS_TEST_LIB_ANONYMOUS_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +#include <boost/type_index.hpp> + +// This is ALWAYS a dynamic library +#if defined(TEST_LIB_SOURCE) +# define TEST_LIB_DECL BOOST_SYMBOL_EXPORT +# else +# define TEST_LIB_DECL BOOST_SYMBOL_IMPORT +# endif + +namespace test_lib { + +TEST_LIB_DECL boost::typeindex::type_index get_anonymous_user_defined_class(); +TEST_LIB_DECL boost::typeindex::type_index get_const_anonymous_user_defined_class(); + +} + +#endif // BOOST_TYPE_INDEX_TESTS_TEST_LIB_ANONYMOUS_HPP + diff --git a/src/boost/libs/type_index/test/testing_crossmodule.cpp b/src/boost/libs/type_index/test/testing_crossmodule.cpp new file mode 100644 index 000000000..fa9017d96 --- /dev/null +++ b/src/boost/libs/type_index/test/testing_crossmodule.cpp @@ -0,0 +1,57 @@ +// +// Copyright 2012-2020 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) + +#include <boost/type_index.hpp> +#include "test_lib.hpp" + +#include <boost/core/lightweight_test.hpp> + +namespace user_defined_namespace { + class user_defined{}; +} + +void comparing_types_between_modules() +{ + boost::typeindex::type_index t_const_int = boost::typeindex::type_id_with_cvr<const int>(); + boost::typeindex::type_index t_int = boost::typeindex::type_id<int>(); + + BOOST_TEST_EQ(t_int, test_lib::get_integer()); + BOOST_TEST_EQ(t_const_int, test_lib::get_const_integer()); + BOOST_TEST_NE(t_const_int, test_lib::get_integer()); + BOOST_TEST_NE(t_int, test_lib::get_const_integer()); + + + boost::typeindex::type_index t_const_userdef + = boost::typeindex::type_id_with_cvr<const user_defined_namespace::user_defined>(); + boost::typeindex::type_index t_userdef + = boost::typeindex::type_id<user_defined_namespace::user_defined>(); + + BOOST_TEST_EQ(t_userdef, test_lib::get_user_defined_class()); + BOOST_TEST_EQ(t_const_userdef, test_lib::get_const_user_defined_class()); + BOOST_TEST_NE(t_const_userdef, test_lib::get_user_defined_class()); + BOOST_TEST_NE(t_userdef, test_lib::get_const_user_defined_class()); + + + BOOST_TEST_NE(t_userdef, test_lib::get_integer()); + BOOST_TEST_NE(t_const_userdef, test_lib::get_integer()); + BOOST_TEST_NE(t_int, test_lib::get_user_defined_class()); + BOOST_TEST_NE(t_const_int, test_lib::get_const_user_defined_class()); + + // MSVC supports detect_missmatch pragma, but /GR- silently switch disable the link time check. + // /GR- undefies the _CPPRTTI macro. Using it to detect working detect_missmatch pragma. + #if !defined(BOOST_HAS_PRAGMA_DETECT_MISMATCH) || !defined(_CPPRTTI) + test_lib::accept_typeindex(t_int); + #endif +} + + +int main() { + comparing_types_between_modules(); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/type_index/test/testing_crossmodule_anonymous.cpp b/src/boost/libs/type_index/test/testing_crossmodule_anonymous.cpp new file mode 100644 index 000000000..f32a69596 --- /dev/null +++ b/src/boost/libs/type_index/test/testing_crossmodule_anonymous.cpp @@ -0,0 +1,48 @@ +// +// Copyright 2012-2020 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) + +#include <boost/core/lightweight_test.hpp> + +#include <boost/type_index.hpp> +#include "test_lib_anonymous.hpp" + +#include <iostream> + +#define BOOST_CHECK_NE(x, y) BOOST_CHECK(x != y) + +namespace { + class user_defined{}; +} + +void comparing_anonymous_types_between_modules() +{ + boost::typeindex::type_index t_const_userdef = boost::typeindex::type_id_with_cvr<const user_defined>(); + boost::typeindex::type_index t_userdef = boost::typeindex::type_id<user_defined>(); + + // Known to fail on Clang and old versions of GCC. + //BOOST_TEST_NE(t_userdef, test_lib::get_anonymous_user_defined_class()); + //BOOST_TEST_NE(t_const_userdef, test_lib::get_const_anonymous_user_defined_class()); + + std::cout + << "t_userdef == " << t_userdef + << ", test_lib::get_anonymous_user_defined_class() == " << test_lib::get_anonymous_user_defined_class() + << '\n'; + std::cout + << "t_const_userdef == " << t_const_userdef + << ", test_lib::get_const_anonymous_user_defined_class() == " << test_lib::get_const_anonymous_user_defined_class() + << '\n'; + + BOOST_TEST_NE(t_const_userdef, test_lib::get_anonymous_user_defined_class()); + BOOST_TEST_NE(t_userdef, test_lib::get_const_anonymous_user_defined_class()); +} + +int main() { + comparing_anonymous_types_between_modules(); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/type_index/test/track_13621.cpp b/src/boost/libs/type_index/test/track_13621.cpp new file mode 100644 index 000000000..31d4c53f6 --- /dev/null +++ b/src/boost/libs/type_index/test/track_13621.cpp @@ -0,0 +1,23 @@ +// +// Copyright 2018-2020 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) + +#include <boost/type_index/ctti_type_index.hpp> +#include <string> + +#include <boost/core/lightweight_test.hpp> + +class empty +{ +}; + +int main() +{ + std::string name = boost::typeindex::ctti_type_index::type_id<empty>().pretty_name(); + BOOST_TEST(name.find("empty") != std::string::npos); + return boost::report_errors(); +} + diff --git a/src/boost/libs/type_index/test/type_index_constexpr_test.cpp b/src/boost/libs/type_index/test/type_index_constexpr_test.cpp new file mode 100644 index 000000000..e9b84eaa6 --- /dev/null +++ b/src/boost/libs/type_index/test/type_index_constexpr_test.cpp @@ -0,0 +1,157 @@ +// +// Copyright 2015-2020 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) + +#include <boost/type_index/ctti_type_index.hpp> + +#include <algorithm> +#include <string> + +#include <boost/core/lightweight_test.hpp> + +const char* hello1 = "Hello word"; +const char* hello1_end = hello1 + sizeof("Hello word"); +const char* hello2 = "Hello word, pal!"; +const char* hello2_end = hello2 + sizeof("Hello word, pal!"); + +void strcmp_same() { + using boost::typeindex::detail::constexpr_strcmp; + + BOOST_TEST( + constexpr_strcmp(hello1, hello1) == 0 + ); + + BOOST_TEST( + constexpr_strcmp(hello2, hello2) == 0 + ); + + BOOST_TEST( + constexpr_strcmp(hello1, hello2) != 0 + ); + + BOOST_TEST( + constexpr_strcmp(hello2, hello1) != 0 + ); + + BOOST_TEST( + (constexpr_strcmp(hello2, hello1) < 0) + == + (std::strcmp(hello2, hello1) < 0) + ); + + BOOST_TEST( + (constexpr_strcmp(hello1, hello2) < 0) + == + (std::strcmp(hello1, hello2) < 0) + ); +} + +void search_same() { + using boost::typeindex::detail::constexpr_search; + BOOST_TEST( + constexpr_search(hello1, hello1_end, hello2, hello2_end) == std::search(hello1, hello1_end, hello2, hello2_end) + ); + + BOOST_TEST( + constexpr_search(hello2, hello2_end, hello1, hello1_end) == std::search(hello2, hello2_end, hello1, hello1_end) + ); + + const char* word = "word"; + const char* word_end = word + sizeof("word") - 1; + BOOST_TEST( + constexpr_search(hello1, hello1_end, word, word_end) == std::search(hello1, hello1_end, word, word_end) + ); + + BOOST_TEST( + constexpr_search(hello2, hello2_end, word, word_end) == std::search(hello2, hello2_end, word, word_end) + ); +} + +template <class T, std::size_t N> +BOOST_CXX14_CONSTEXPR bool in_namespace(const char (&ns)[N]) BOOST_NOEXCEPT { + BOOST_CXX14_CONSTEXPR const char* name = boost::typeindex::ctti_type_index::type_id<T>().raw_name(); + for (std::size_t i = 0; i < N - 1; ++i) + if (name[i] != ns[i]) + return false; + + return true; +} + +template <class T> +BOOST_CXX14_CONSTEXPR bool is_boost_namespace() BOOST_NOEXCEPT { + return in_namespace<T>("boost::") || in_namespace<T>("class boost::") || in_namespace<T>("struct boost::"); +} + +void constexpr_test() { + using namespace boost::typeindex; + + BOOST_CXX14_CONSTEXPR ctti_type_index t_int0 = ctti_type_index::type_id<int>(); + (void)t_int0; + + BOOST_CXX14_CONSTEXPR ctti_type_index t_short0 = ctti_type_index::type_id<short>(); + (void)t_short0; + + BOOST_CXX14_CONSTEXPR ctti_type_index t_int1 = ctti_type_index::type_id<int>(); + (void)t_int1; + + BOOST_CXX14_CONSTEXPR ctti_type_index t_short1 = ctti_type_index::type_id<short>(); + (void)t_short1; + +// Following tests are known to fail on _MSC_VER == 1916. +#if !defined(_MSC_VER) || _MSC_VER > 1916 + + BOOST_CXX14_CONSTEXPR bool same0 = (t_int0 == t_int1); + BOOST_TEST(same0); + + BOOST_CXX14_CONSTEXPR bool same1 = (t_short1 == t_short0); + BOOST_TEST(same1); + + BOOST_CXX14_CONSTEXPR bool same2 = (t_int1 == t_int1); + BOOST_TEST(same2); + + BOOST_CXX14_CONSTEXPR bool same3 = (t_short0 == t_short0); + BOOST_TEST(same3); + + BOOST_CXX14_CONSTEXPR bool same4 = !(t_short0 < t_short0 || t_short0 > t_short0); + BOOST_TEST(same4); + + BOOST_CXX14_CONSTEXPR bool same5 = (t_short0 <= t_short0 && t_short0 >= t_short0); + BOOST_TEST(same5); + + + BOOST_CXX14_CONSTEXPR bool not_same0 = (t_int0 != t_short1); + BOOST_TEST(not_same0); + + BOOST_CXX14_CONSTEXPR bool not_same1 = (t_int1 != t_short0); + BOOST_TEST(not_same1); + + BOOST_CXX14_CONSTEXPR bool not_same2 = (t_int1 < t_short0 || t_int1 > t_short0); + BOOST_TEST(not_same2); + + + BOOST_CXX14_CONSTEXPR const char* int_name = t_int0.name(); + BOOST_TEST(*int_name != '\0'); + + BOOST_CXX14_CONSTEXPR const char* short_name = t_short0.name(); + BOOST_TEST(*short_name != '\0'); + + BOOST_CXX14_CONSTEXPR bool in_namespace = is_boost_namespace<ctti_type_index>(); + BOOST_TEST(in_namespace); + + BOOST_CXX14_CONSTEXPR bool not_in_namespace = !is_boost_namespace<std::string>(); + BOOST_TEST(not_in_namespace); + +#endif // #if !defined(_MSC_VER) || _MSC_VER > 1916 +} + + +int main() { + strcmp_same(); + search_same(); + constexpr_test(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/type_index/test/type_index_runtime_cast_test.cpp b/src/boost/libs/type_index/test/type_index_runtime_cast_test.cpp new file mode 100644 index 000000000..1f5344ef5 --- /dev/null +++ b/src/boost/libs/type_index/test/type_index_runtime_cast_test.cpp @@ -0,0 +1,296 @@ +// +// Copyright Chris Glover, 2016. +// +// 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) + +// #include <boost/type_index/runtime_cast.hpp> +// #include <boost/type_index/runtime_reference_cast.hpp> + +#include <boost/type_index/runtime_cast.hpp> +#include <boost/type_index/runtime_cast/boost_shared_ptr_cast.hpp> +#include <boost/smart_ptr/make_shared.hpp> + +#include <boost/core/lightweight_test.hpp> + +#if !defined(BOOST_NO_CXX11_SMART_PTR) +# include <boost/type_index/runtime_cast/std_shared_ptr_cast.hpp> +#endif + +// Classes include a member variable "name" with the +// name of the class hard coded so we can be sure that +// the pointer offsets are all working, since we're doing +// a cast from void* at some point. + +#define IMPLEMENT_CLASS(type_name) \ + type_name() : name( #type_name ) {} \ + std::string name; + +struct base { + BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(BOOST_TYPE_INDEX_NO_BASE_CLASS) + IMPLEMENT_CLASS(base) +}; + +struct single_derived : base { + BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST((base)) + IMPLEMENT_CLASS(single_derived) +}; + +struct base1 { + BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(BOOST_TYPE_INDEX_NO_BASE_CLASS) + IMPLEMENT_CLASS(base1) +}; + +struct base2 { + BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(BOOST_TYPE_INDEX_NO_BASE_CLASS) + IMPLEMENT_CLASS(base2) +}; + +struct multiple_derived : base1, base2 { + BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST((base1)(base2)) + IMPLEMENT_CLASS(multiple_derived) +}; + +struct baseV1 : virtual base { + BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST((base)) + IMPLEMENT_CLASS(baseV1) +}; + +struct baseV2 : virtual base { + BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST((base)) + IMPLEMENT_CLASS(baseV2) +}; + +struct multiple_virtual_derived : baseV1, baseV2 { + BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST((baseV1)(baseV2)) + IMPLEMENT_CLASS(multiple_virtual_derived) +}; + +struct unrelated { + BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(BOOST_TYPE_INDEX_NO_BASE_CLASS) + IMPLEMENT_CLASS(unrelated) +}; + +struct unrelated_with_base : base { + BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST((base)) + IMPLEMENT_CLASS(unrelated_with_base) +}; + +struct unrelatedV1 : virtual base { + BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST((base)) + IMPLEMENT_CLASS(unrelatedV1) +}; + +struct level1_a : base { + BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST((base)) + IMPLEMENT_CLASS(level1_a) +}; + +struct level1_b : base { + BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST((base)) + IMPLEMENT_CLASS(level1_b) +}; + +struct level2 : level1_a, level1_b { + BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST((level1_a)(level1_b)) + IMPLEMENT_CLASS(level2) +}; + +struct reg_base { + BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(BOOST_TYPE_INDEX_NO_BASE_CLASS) +}; + +struct reg_derived : reg_base { + BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS((reg_base)) +}; + +void no_base() +{ + using namespace boost::typeindex; + base b; + base* b2 = runtime_pointer_cast<base>(&b); + BOOST_TEST_NE(b2, (base*)NULL); + BOOST_TEST_EQ(b2->name, "base"); + + BOOST_TEST_EQ(runtime_pointer_cast<unrelated>(&b), (unrelated*)NULL); + BOOST_TEST_EQ(runtime_pointer_cast<single_derived>(&b), (single_derived*)NULL); + BOOST_TEST_EQ(runtime_pointer_cast<unrelatedV1>(&b), (unrelatedV1*)NULL); + BOOST_TEST_EQ(runtime_pointer_cast<unrelated_with_base>(&b), (unrelated_with_base*)NULL); +} + +void single_base() +{ + using namespace boost::typeindex; + single_derived d; + base* b = &d; + single_derived* d2 = runtime_pointer_cast<single_derived>(b); + BOOST_TEST_NE(d2, (single_derived*)NULL); + BOOST_TEST_EQ(d2->name, "single_derived"); + + BOOST_TEST_EQ(runtime_pointer_cast<unrelated>(&d), (unrelated*)NULL); + BOOST_TEST_EQ(runtime_pointer_cast<unrelated>(b), (unrelated*)NULL); + BOOST_TEST_EQ(runtime_pointer_cast<unrelated_with_base>(b), (unrelated_with_base*)NULL); +} + +void multiple_base() +{ + using namespace boost::typeindex; + multiple_derived d; + base1* b1 = &d; + multiple_derived* d2 = runtime_pointer_cast<multiple_derived>(b1); + BOOST_TEST_NE(d2, (multiple_derived*)NULL); + BOOST_TEST_EQ(d2->name, "multiple_derived"); + + base2* b2 = runtime_pointer_cast<base2>(b1); + BOOST_TEST_NE(b2, (base2*)NULL); + BOOST_TEST_EQ(b2->name, "base2"); + + BOOST_TEST_EQ(runtime_pointer_cast<unrelated>(&d), (unrelated*)NULL); + BOOST_TEST_EQ(runtime_pointer_cast<unrelated>(b1), (unrelated*)NULL); + BOOST_TEST_EQ(runtime_pointer_cast<unrelated_with_base>(b1), (unrelated_with_base*)NULL); +} + +void virtual_base() +{ + using namespace boost::typeindex; + multiple_virtual_derived d; + base* b = &d; + multiple_virtual_derived* d2 = runtime_pointer_cast<multiple_virtual_derived>(b); + baseV1* bv1 = runtime_pointer_cast<baseV1>(b); + baseV2* bv2 = runtime_pointer_cast<baseV2>(b); + + BOOST_TEST_NE(d2, (multiple_virtual_derived*)NULL); + BOOST_TEST_EQ(d2->name, "multiple_virtual_derived"); + + BOOST_TEST_NE(bv1, (baseV1*)NULL); + BOOST_TEST_EQ(bv1->name, "baseV1"); + + BOOST_TEST_NE(bv2, (baseV2*)NULL); + BOOST_TEST_EQ(bv2->name, "baseV2"); + + BOOST_TEST_EQ(runtime_pointer_cast<unrelated>(b), (unrelated*)NULL); + BOOST_TEST_EQ(runtime_pointer_cast<unrelated>(&d), (unrelated*)NULL); + BOOST_TEST_EQ(runtime_pointer_cast<unrelated_with_base>(b), (unrelated_with_base*)NULL); +} + +void pointer_interface() +{ + using namespace boost::typeindex; + single_derived d; + base* b = &d; + single_derived* d2 = runtime_cast<single_derived*>(b); + BOOST_TEST_NE(d2, (single_derived*)NULL); + BOOST_TEST_EQ(d2->name, "single_derived"); + BOOST_TEST_EQ(runtime_pointer_cast<unrelated>(b), (unrelated*)NULL); +} + +void reference_interface() +{ + using namespace boost::typeindex; + single_derived d; + base& b = d; + single_derived& d2 = runtime_cast<single_derived&>(b); + BOOST_TEST_EQ(d2.name, "single_derived"); + + try { + unrelated& u = runtime_cast<unrelated&>(b); + (void)u; + BOOST_TEST(!"should throw bad_runtime_cast"); + } + catch(boost::typeindex::bad_runtime_cast&) { + } + catch(...) { + BOOST_TEST(!"should throw bad_runtime_cast"); + } +} + +void const_pointer_interface() +{ + using namespace boost::typeindex; + const single_derived d; + base const* b = &d; + single_derived const* d2 = runtime_cast<single_derived const*>(b); + BOOST_TEST_NE(d2, (single_derived*)NULL); + BOOST_TEST_EQ(d2->name, "single_derived"); + BOOST_TEST_EQ(runtime_pointer_cast<unrelated>(b), (unrelated*)NULL); +} + +void const_reference_interface() +{ + using namespace boost::typeindex; + const single_derived d; + base const& b = d; + single_derived const& d2 = runtime_cast<single_derived const&>(b); + BOOST_TEST_EQ(d2.name, "single_derived"); + + try { + unrelated const& u = runtime_cast<unrelated const&>(b); + (void)u; + BOOST_TEST(!"should throw bad_runtime_cast"); + } + catch(boost::typeindex::bad_runtime_cast&) { + } + catch(...) { + BOOST_TEST(!"should throw bad_runtime_cast"); + } +} + +void diamond_non_virtual() +{ + using namespace boost::typeindex; + level2 inst; + level1_a* l1a = &inst; + base* b1 = l1a; + level1_b* l1_b = runtime_cast<level1_b*>(b1); + BOOST_TEST_NE(l1_b, (level1_b*)NULL); + BOOST_TEST_EQ(l1_b->name, "level1_b"); +} + +void boost_shared_ptr() +{ + using namespace boost::typeindex; + boost::shared_ptr<single_derived> d = boost::make_shared<single_derived>(); + boost::shared_ptr<base> b = d; + boost::shared_ptr<single_derived> d2 = runtime_pointer_cast<single_derived>(b); + BOOST_TEST_NE(d2, boost::shared_ptr<single_derived>()); + BOOST_TEST_EQ(d2->name, "single_derived"); +} + +void std_shared_ptr() +{ +#if !defined(BOOST_NO_CXX11_SMART_PTR) + using namespace boost::typeindex; + std::shared_ptr<single_derived> d = std::make_shared<single_derived>(); + std::shared_ptr<base> b = d; + std::shared_ptr<single_derived> d2 = runtime_pointer_cast<single_derived>(b); + BOOST_TEST_NE(d2, std::shared_ptr<single_derived>()); + BOOST_TEST_EQ(d2->name, "single_derived"); +#endif +} + +void register_runtime_class() +{ + using namespace boost::typeindex; + reg_derived rd; + reg_base* rb = &rd; + reg_derived* prd = runtime_pointer_cast<reg_derived>(rb); + BOOST_TEST_NE(prd, (reg_derived*)NULL); + BOOST_TEST_EQ(type_id_runtime(*prd), type_id<reg_derived>()); +} + +int main() { + no_base(); + single_derived(); + multiple_base(); + virtual_base(); + pointer_interface(); + reference_interface(); + const_pointer_interface(); + const_reference_interface(); + diamond_non_virtual(); + boost_shared_ptr(); + std_shared_ptr(); + register_runtime_class(); + return boost::report_errors(); +} diff --git a/src/boost/libs/type_index/test/type_index_test.cpp b/src/boost/libs/type_index/test/type_index_test.cpp new file mode 100644 index 000000000..9a4c73c5a --- /dev/null +++ b/src/boost/libs/type_index/test/type_index_test.cpp @@ -0,0 +1,400 @@ +// +// Copyright 2012-2020 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) + +#include <boost/type_index.hpp> + +#include <boost/lexical_cast.hpp> + +#include <boost/core/lightweight_test.hpp> + +namespace my_namespace1 { + class my_class{}; +} + + +namespace my_namespace2 { + class my_class{}; +} + + +void names_matches_type_id() +{ + using namespace boost::typeindex; + BOOST_TEST_EQ(type_id<int>().pretty_name(), "int"); + BOOST_TEST_EQ(type_id<double>().pretty_name(), "double"); + + BOOST_TEST_EQ(type_id<int>().name(), type_id<int>().name()); + BOOST_TEST_NE(type_id<int>().name(), type_id<double>().name()); + BOOST_TEST_NE(type_id<double>().name(), type_id<int>().name()); + BOOST_TEST_EQ(type_id<double>().name(), type_id<double>().name()); +} + +void default_construction() +{ + using namespace boost::typeindex; + type_index ti1, ti2; + BOOST_TEST_EQ(ti1, ti2); + BOOST_TEST_EQ(type_id<void>(), ti1); + + BOOST_TEST_EQ(type_id<void>().name(), ti1.name()); + BOOST_TEST_NE(type_id<int>(), ti1); +} + + +void copy_construction() +{ + using namespace boost::typeindex; + type_index ti1, ti2 = type_id<int>(); + BOOST_TEST_NE(ti1, ti2); + ti1 = ti2; + BOOST_TEST_EQ(ti2, ti1); + + const type_index ti3(ti1); + BOOST_TEST_EQ(ti3, ti1); +} + +void comparators_type_id() +{ + using namespace boost::typeindex; + type_index t_int = type_id<int>(); + type_index t_double = type_id<double>(); + + BOOST_TEST_EQ(t_int, t_int); + BOOST_TEST_LE(t_int, t_int); + BOOST_TEST_GE(t_int, t_int); + BOOST_TEST_NE(t_int, t_double); + + BOOST_TEST_LE(t_double, t_double); + BOOST_TEST_GE(t_double, t_double); + BOOST_TEST_NE(t_double, t_int); + + BOOST_TEST(t_double < t_int || t_int < t_double); + BOOST_TEST(t_double > t_int || t_int > t_double); +} + +void hash_code_type_id() +{ + using namespace boost::typeindex; + 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_TEST_EQ(t_int1, t_int2); + BOOST_TEST_NE(t_int1, t_double2); + BOOST_TEST_LE(t_double1, t_double2); +} + + + +template <class T1, class T2> +static void test_with_modofiers() { + using namespace boost::typeindex; + + type_index t1 = type_id_with_cvr<T1>(); + type_index t2 = type_id_with_cvr<T2>(); + + BOOST_TEST_NE(t2, t1); + BOOST_TEST(t2 != t1.type_info()); + BOOST_TEST(t2.type_info() != t1); + + BOOST_TEST(t1 < t2 || t2 < t1); + BOOST_TEST(t1 > t2 || t2 > t1); + BOOST_TEST(t1.type_info() < t2 || t2.type_info() < t1); + BOOST_TEST(t1.type_info() > t2 || t2.type_info() > t1); + BOOST_TEST(t1 < t2.type_info() || t2 < t1.type_info()); + BOOST_TEST(t1 > t2.type_info() || t2 > t1.type_info()); + + // Chaecking that comparison operators overloads compile + BOOST_TEST(t1 <= t2 || t2 <= t1); + BOOST_TEST(t1 >= t2 || t2 >= t1); + BOOST_TEST(t1.type_info() <= t2 || t2.type_info() <= t1); + BOOST_TEST(t1.type_info() >= t2 || t2.type_info() >= t1); + BOOST_TEST(t1 <= t2.type_info() || t2 <= t1.type_info()); + BOOST_TEST(t1 >= t2.type_info() || t2 >= t1.type_info()); + + BOOST_TEST_EQ(t1, type_id_with_cvr<T1>()); + BOOST_TEST_EQ(t2, type_id_with_cvr<T2>()); + BOOST_TEST(t1 == type_id_with_cvr<T1>().type_info()); + BOOST_TEST(t2 == type_id_with_cvr<T2>().type_info()); + BOOST_TEST(t1.type_info() == type_id_with_cvr<T1>()); + BOOST_TEST(t2.type_info() == type_id_with_cvr<T2>()); + + BOOST_TEST_EQ(t1.hash_code(), type_id_with_cvr<T1>().hash_code()); + BOOST_TEST_EQ(t2.hash_code(), type_id_with_cvr<T2>().hash_code()); + + BOOST_TEST_NE(t1.hash_code(), type_id_with_cvr<T2>().hash_code()); + BOOST_TEST_NE(t2.hash_code(), type_id_with_cvr<T1>().hash_code()); +} + +void type_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&>(); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + test_with_modofiers<int&&, const 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&&, volatile int&&>(); + test_with_modofiers<int&&, const volatile int>(); + test_with_modofiers<int&&, const volatile int&>(); + test_with_modofiers<int&&, const volatile int&&>(); +#endif +} + +template <class T> +static void test_storing_nonstoring_modifiers_templ() { + using namespace boost::typeindex; + + type_index t1 = type_id_with_cvr<T>(); + type_index t2 = type_id<T>(); + + BOOST_TEST_EQ(t2, t1); + BOOST_TEST_EQ(t1, t2); + BOOST_TEST(t1 <= t2); + BOOST_TEST(t1 >= t2); + BOOST_TEST(t2 <= t1); + BOOST_TEST(t2 >= t1); + + BOOST_TEST_EQ(t2.pretty_name(), t1.pretty_name()); +} + +void type_id_storing_modifiers_vs_nonstoring() +{ + test_storing_nonstoring_modifiers_templ<int>(); + test_storing_nonstoring_modifiers_templ<my_namespace1::my_class>(); + test_storing_nonstoring_modifiers_templ<my_namespace2::my_class>(); + + boost::typeindex::type_index t1 = boost::typeindex::type_id_with_cvr<const int>(); + boost::typeindex::type_index t2 = boost::typeindex::type_id<int>(); + BOOST_TEST_NE(t2, t1); + BOOST_TEST(t1.pretty_name() == "const int" || t1.pretty_name() == "int const"); +} + +void type_index_stream_operator_via_lexical_cast_testing() +{ + using namespace boost::typeindex; + + std::string s_int2 = boost::lexical_cast<std::string>(type_id<int>()); + BOOST_TEST_EQ(s_int2, "int"); + + std::string s_double2 = boost::lexical_cast<std::string>(type_id<double>()); + BOOST_TEST_EQ(s_double2, "double"); +} + +void type_index_stripping_cvr_test() +{ + using namespace boost::typeindex; + + BOOST_TEST_EQ(type_id<int>(), type_id<const int>()); + BOOST_TEST_EQ(type_id<int>(), type_id<const volatile int>()); + BOOST_TEST_EQ(type_id<int>(), type_id<const volatile int&>()); + + BOOST_TEST_EQ(type_id<int>(), type_id<int&>()); + BOOST_TEST_EQ(type_id<int>(), type_id<volatile int>()); + BOOST_TEST_EQ(type_id<int>(), type_id<volatile int&>()); + + + BOOST_TEST_EQ(type_id<double>(), type_id<const double>()); + BOOST_TEST_EQ(type_id<double>(), type_id<const volatile double>()); + BOOST_TEST_EQ(type_id<double>(), type_id<const volatile double&>()); + + BOOST_TEST_EQ(type_id<double>(), type_id<double&>()); + BOOST_TEST_EQ(type_id<double>(), type_id<volatile double>()); + BOOST_TEST_EQ(type_id<double>(), type_id<volatile double&>()); +} + + +void type_index_user_defined_class_test() +{ + using namespace boost::typeindex; + + BOOST_TEST_EQ(type_id<my_namespace1::my_class>(), type_id<my_namespace1::my_class>()); + BOOST_TEST_EQ(type_id<my_namespace2::my_class>(), type_id<my_namespace2::my_class>()); + +#ifndef BOOST_NO_RTTI + BOOST_TEST(type_id<my_namespace1::my_class>() == typeid(my_namespace1::my_class)); + BOOST_TEST(type_id<my_namespace2::my_class>() == typeid(my_namespace2::my_class)); + BOOST_TEST(typeid(my_namespace1::my_class) == type_id<my_namespace1::my_class>()); + BOOST_TEST(typeid(my_namespace2::my_class) == type_id<my_namespace2::my_class>()); +#endif + + BOOST_TEST_NE(type_id<my_namespace1::my_class>(), type_id<my_namespace2::my_class>()); + BOOST_TEST_NE( + type_id<my_namespace1::my_class>().pretty_name().find("my_namespace1::my_class"), + std::string::npos); +} + + + + + +struct A { +public: + BOOST_TYPE_INDEX_REGISTER_CLASS + virtual ~A(){} +}; + +struct B: public A { + BOOST_TYPE_INDEX_REGISTER_CLASS +}; + +struct C: public B { + BOOST_TYPE_INDEX_REGISTER_CLASS +}; + +void comparators_type_id_runtime() +{ + C c1; + B b1; + A* pc1 = &c1; + A& rc1 = c1; + A* pb1 = &b1; + A& rb1 = b1; + +#ifndef BOOST_NO_RTTI + BOOST_TEST(typeid(rc1) == typeid(*pc1)); + BOOST_TEST(typeid(rb1) == typeid(*pb1)); + + BOOST_TEST(typeid(rc1) != typeid(*pb1)); + BOOST_TEST(typeid(rb1) != typeid(*pc1)); + + BOOST_TEST(typeid(&rc1) == typeid(pb1)); + BOOST_TEST(typeid(&rb1) == typeid(pc1)); +#else + BOOST_TEST(boost::typeindex::type_index(pc1->boost_type_index_type_id_runtime_()).raw_name()); +#endif + + BOOST_TEST_EQ(boost::typeindex::type_id_runtime(rc1), boost::typeindex::type_id_runtime(*pc1)); + BOOST_TEST_EQ(boost::typeindex::type_id<C>(), boost::typeindex::type_id_runtime(*pc1)); + BOOST_TEST_EQ(boost::typeindex::type_id_runtime(rb1), boost::typeindex::type_id_runtime(*pb1)); + BOOST_TEST_EQ(boost::typeindex::type_id<B>(), boost::typeindex::type_id_runtime(*pb1)); + + BOOST_TEST_NE(boost::typeindex::type_id_runtime(rc1), boost::typeindex::type_id_runtime(*pb1)); + BOOST_TEST_NE(boost::typeindex::type_id_runtime(rb1), boost::typeindex::type_id_runtime(*pc1)); + +#ifndef BOOST_NO_RTTI + BOOST_TEST_EQ(boost::typeindex::type_id_runtime(&rc1), boost::typeindex::type_id_runtime(pb1)); + BOOST_TEST_EQ(boost::typeindex::type_id_runtime(&rb1), boost::typeindex::type_id_runtime(pc1)); + + BOOST_TEST(boost::typeindex::type_id_runtime(rc1) == typeid(*pc1)); + BOOST_TEST(boost::typeindex::type_id_runtime(rb1) == typeid(*pb1)); + + BOOST_TEST(boost::typeindex::type_id_runtime(rc1) != typeid(*pb1)); + BOOST_TEST(boost::typeindex::type_id_runtime(rb1) != typeid(*pc1)); + BOOST_TEST(boost::typeindex::type_id_runtime(&rc1) == typeid(pb1)); + BOOST_TEST(boost::typeindex::type_id_runtime(&rb1) == typeid(pc1)); +#endif +} + + +#ifndef BOOST_NO_RTTI + +void comparators_type_id_vs_type_info() +{ + using namespace boost::typeindex; + type_index t_int = type_id<int>(); + + BOOST_TEST(t_int == typeid(int)); + BOOST_TEST(typeid(int) == t_int); + BOOST_TEST(t_int <= typeid(int)); + BOOST_TEST(typeid(int) <= t_int); + BOOST_TEST(t_int >= typeid(int)); + BOOST_TEST(typeid(int) >= t_int); + + type_index t_double = type_id<double>(); + + BOOST_TEST(t_double == typeid(double)); + BOOST_TEST(typeid(double) == t_double); + BOOST_TEST(t_double <= typeid(double)); + BOOST_TEST(typeid(double) <= t_double); + BOOST_TEST(t_double >= typeid(double)); + BOOST_TEST(typeid(double) >= t_double); + + if (t_double < t_int) { + BOOST_TEST(t_double < typeid(int)); + BOOST_TEST(typeid(double) < t_int); + BOOST_TEST(typeid(int) > t_double); + BOOST_TEST(t_int > typeid(double)); + + + BOOST_TEST(t_double <= typeid(int)); + BOOST_TEST(typeid(double) <= t_int); + BOOST_TEST(typeid(int) >= t_double); + BOOST_TEST(t_int >= typeid(double)); + } else { + BOOST_TEST(t_double > typeid(int)); + BOOST_TEST(typeid(double) > t_int); + BOOST_TEST(typeid(int) < t_double); + BOOST_TEST(t_int < typeid(double)); + + + BOOST_TEST(t_double >= typeid(int)); + BOOST_TEST(typeid(double) >= t_int); + BOOST_TEST(typeid(int) <= t_double); + BOOST_TEST(t_int <= typeid(double)); + } + +} + +#endif // BOOST_NO_RTTI + +int main() { + names_matches_type_id(); + default_construction(); + copy_construction(); + comparators_type_id(); + hash_code_type_id(); + + type_id_storing_modifiers(); + type_id_storing_modifiers_vs_nonstoring(); + type_index_stream_operator_via_lexical_cast_testing(); + type_index_stripping_cvr_test(); + type_index_user_defined_class_test(); + + comparators_type_id_runtime(); +#ifndef BOOST_NO_RTTI + comparators_type_id_vs_type_info(); +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/type_index/test/type_index_test_ctti_alignment.cpp b/src/boost/libs/type_index/test/type_index_test_ctti_alignment.cpp new file mode 100644 index 000000000..95b25d718 --- /dev/null +++ b/src/boost/libs/type_index/test/type_index_test_ctti_alignment.cpp @@ -0,0 +1,18 @@ +// +// Copyright 2012-2020 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) + +#include <boost/type_index/ctti_type_index.hpp> +#include <boost/type_traits/alignment_of.hpp> + +int main() { + BOOST_STATIC_ASSERT_MSG( + boost::alignment_of<boost::typeindex::detail::ctti_data>::value == boost::alignment_of<char>::value, + "Alignments of boost::typeindex::detail::ctti_data and char differ. " + "It is unsafe to reinterpret_cast between them." + ); +} + diff --git a/src/boost/libs/type_index/test/type_index_test_ctti_construct_fail.cpp b/src/boost/libs/type_index/test/type_index_test_ctti_construct_fail.cpp new file mode 100644 index 000000000..ce3c3a890 --- /dev/null +++ b/src/boost/libs/type_index/test/type_index_test_ctti_construct_fail.cpp @@ -0,0 +1,15 @@ +// +// Copyright 2012-2020 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) + +#include <boost/type_index/ctti_type_index.hpp> + +int main() { + using namespace boost::typeindex; + ctti_type_index::type_info_t t; + (void)t; +} + diff --git a/src/boost/libs/type_index/test/type_index_test_ctti_copy_fail.cpp b/src/boost/libs/type_index/test/type_index_test_ctti_copy_fail.cpp new file mode 100644 index 000000000..fad7fa487 --- /dev/null +++ b/src/boost/libs/type_index/test/type_index_test_ctti_copy_fail.cpp @@ -0,0 +1,15 @@ +// +// Copyright 2012-2020 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) + +#include <boost/type_index/ctti_type_index.hpp> + +int main() { + using namespace boost::typeindex; + ctti_type_index::type_info_t t = ctti_type_index::type_id<int>().type_info(); + (void)t; +} + |