Squashed 'third_party/boostorg/type_index/' content from commit c2caa34
Change-Id: I76e1c1099cbf17522d18a78a42581be067301ca4
git-subtree-dir: third_party/boostorg/type_index
git-subtree-split: c2caa340ab9d9d834c5ffafb3f267b3c46c8c821
diff --git a/examples/constexpr14_namespace_check.cpp b/examples/constexpr14_namespace_check.cpp
new file mode 100644
index 0000000..98a5e40
--- /dev/null
+++ b/examples/constexpr14_namespace_check.cpp
@@ -0,0 +1,97 @@
+// Copyright 2013-2017 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/examples/constexpr14_sort_check.cpp b/examples/constexpr14_sort_check.cpp
new file mode 100644
index 0000000..54a8435
--- /dev/null
+++ b/examples/constexpr14_sort_check.cpp
@@ -0,0 +1,76 @@
+// Copyright 2013-2017 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)
+
+//[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)
+
+int main() {}
+
+#endif
+
diff --git a/examples/demangled_names.cpp b/examples/demangled_names.cpp
new file mode 100644
index 0000000..d148b5d
--- /dev/null
+++ b/examples/demangled_names.cpp
@@ -0,0 +1,76 @@
+// Copyright 2013-2014 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/examples/exact_types_match.cpp b/examples/exact_types_match.cpp
new file mode 100644
index 0000000..498d662
--- /dev/null
+++ b/examples/exact_types_match.cpp
@@ -0,0 +1,74 @@
+// Copyright 2013-2015 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/examples/inheritance.cpp b/examples/inheritance.cpp
new file mode 100644
index 0000000..3da7527
--- /dev/null
+++ b/examples/inheritance.cpp
@@ -0,0 +1,47 @@
+// Copyright 2013-2014 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/examples/registry.cpp b/examples/registry.cpp
new file mode 100644
index 0000000..64a97ca
--- /dev/null
+++ b/examples/registry.cpp
@@ -0,0 +1,50 @@
+// Copyright 2013-2017 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_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>());
+}
+
+//] [/type_index_registry_example]
diff --git a/examples/runtime_cast.cpp b/examples/runtime_cast.cpp
new file mode 100644
index 0000000..43e7aa7
--- /dev/null
+++ b/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/examples/table_of_names.cpp b/examples/table_of_names.cpp
new file mode 100644
index 0000000..262e5f4
--- /dev/null
+++ b/examples/table_of_names.cpp
@@ -0,0 +1,90 @@
+// Copyright 2013-2014 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/examples/user_defined_typeinfo.cpp b/examples/user_defined_typeinfo.cpp
new file mode 100644
index 0000000..b4fd076
--- /dev/null
+++ b/examples/user_defined_typeinfo.cpp
@@ -0,0 +1,69 @@
+// Copyright 2013-2015 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]
+}
+
+
diff --git a/examples/user_defined_typeinfo.hpp b/examples/user_defined_typeinfo.hpp
new file mode 100644
index 0000000..946be17
--- /dev/null
+++ b/examples/user_defined_typeinfo.hpp
@@ -0,0 +1,213 @@
+// Copyright 2013-2018 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
+