├── .gitignore ├── meta └── libraries.json ├── modules ├── usage_test_mu1.cpp ├── usage_test_mu2.cpp ├── usage_sample.cpp └── boost_type_index.cppm ├── test ├── type_index_test_ctti_construct_fail.cpp ├── type_index_test_ctti_copy_fail.cpp ├── type_index_test_ctti_alignment.cpp ├── track_13621.cpp ├── test_lib_anonymous.cpp ├── test_lib_anonymous.hpp ├── test_lib.cpp ├── ctti_print_name.cpp ├── test_lib.hpp ├── compare_ctti_stl.cpp ├── testing_crossmodule_anonymous.cpp ├── cmake_subdir_test │ └── CMakeLists.txt ├── testing_crossmodule.cpp ├── appveyor.yml ├── Jamfile.v2 ├── type_index_constexpr_test.cpp ├── CMakeLists.txt ├── type_index_runtime_cast_test.cpp └── type_index_test.cpp ├── patched ├── README.md ├── boost_smart_ptr.patch ├── boost_detail_sp_typeinfo.patch └── boost_exception.patch ├── index.html ├── include └── boost │ ├── type_index │ ├── detail │ │ ├── config.hpp │ │ ├── ctti_register_class.hpp │ │ ├── stl_register_class.hpp │ │ └── compile_time_type_info.hpp │ ├── runtime_cast.hpp │ ├── runtime_cast │ │ ├── detail │ │ │ └── runtime_cast_impl.hpp │ │ ├── std_shared_ptr_cast.hpp │ │ ├── boost_shared_ptr_cast.hpp │ │ ├── reference_cast.hpp │ │ ├── pointer_cast.hpp │ │ └── register_runtime_class.hpp │ ├── ctti_type_index.hpp │ ├── stl_type_index.hpp │ └── type_index_facade.hpp │ └── type_index.hpp ├── CMakeLists.txt ├── examples ├── inheritance.cpp ├── registry.cpp ├── user_defined_typeinfo.cpp ├── runtime_cast.cpp ├── demangled_names.cpp ├── exact_types_match.cpp ├── constexpr14_sort_check.cpp ├── constexpr14_namespace_check.cpp ├── table_of_names.cpp └── user_defined_typeinfo.hpp ├── README.md ├── doc └── Jamfile.v2 ├── .gitattributes └── .github └── workflows └── ci.yml /.gitignore: -------------------------------------------------------------------------------- 1 | doc/autodoc.xml 2 | doc/html 3 | -------------------------------------------------------------------------------- /meta/libraries.json: -------------------------------------------------------------------------------- 1 | { 2 | "key": "type_index", 3 | "name": "Type Index", 4 | "authors": [ 5 | "Antony Polukhin" 6 | ], 7 | "maintainers": [ 8 | "Antony Polukhin " 9 | ], 10 | "description": "Runtime/Compile time copyable type info.", 11 | "category": [ 12 | "Emulation" 13 | ], 14 | "cxxstd": "11" 15 | } 16 | -------------------------------------------------------------------------------- /modules/usage_test_mu1.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016-2025 Antony Polukhin 2 | // 3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | #include 7 | 8 | import boost.type_index; 9 | 10 | void do_something(std::ostream& os) { 11 | os << boost::typeindex::type_id_with_cvr(); 12 | } 13 | 14 | -------------------------------------------------------------------------------- /test/type_index_test_ctti_construct_fail.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2012-2025 Antony Polukhin. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See 5 | // accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | 10 | int main() { 11 | using namespace boost::typeindex; 12 | ctti_type_index::type_info_t t; 13 | (void)t; 14 | } 15 | 16 | -------------------------------------------------------------------------------- /patched/README.md: -------------------------------------------------------------------------------- 1 | patches for Boost libraries to work without RTTI 2 | ========== 3 | 4 | Here are the patches that are TESTED and work well with RTTI disabled and enabled. 5 | Patches add tests for some of the libraries to make sure that library compile and work without RTTI. 6 | 7 | Patches remove duplicate code, improve output, allow compilation with RTTI off... 8 | 9 | Libraries Boost.Graph, Boost.XPressive, Boost.PropertyMap and others may also benefit from TypeIndex library. 10 | -------------------------------------------------------------------------------- /test/type_index_test_ctti_copy_fail.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2012-2025 Antony Polukhin. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See 5 | // accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | 10 | int main() { 11 | using namespace boost::typeindex; 12 | ctti_type_index::type_info_t t = ctti_type_index::type_id().type_info(); 13 | (void)t; 14 | } 15 | 16 | -------------------------------------------------------------------------------- /modules/usage_test_mu2.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016-2025 Antony Polukhin 2 | // 3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | #include 7 | #include 8 | 9 | void do_something(std::ostream& os); 10 | 11 | int main() { 12 | do_something(std::cout); 13 | std::cout << '\n'; 14 | std::cout << boost::typeindex::type_id_with_cvr(); // Outputs: const int 15 | } 16 | 17 | -------------------------------------------------------------------------------- /test/type_index_test_ctti_alignment.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2012-2025 Antony Polukhin. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See 5 | // accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | 10 | int main() { 11 | static_assert( 12 | alignof(boost::typeindex::detail::ctti_data) == alignof(char), 13 | "Alignments of boost::typeindex::detail::ctti_data and char differ. " 14 | "It is unsafe to reinterpret_cast between them." 15 | ); 16 | } 17 | 18 | -------------------------------------------------------------------------------- /modules/usage_sample.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016-2025 Antony Polukhin 2 | // 3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | // To compile manually use a command like the folowing: 7 | // clang++ -std=c++20 -fmodule-file=type_index.pcm type_index.pcm usage_sample.cpp 8 | 9 | //[type_index_module_example 10 | #include 11 | 12 | import boost.type_index; 13 | 14 | int main() { 15 | std::cout << boost::typeindex::type_id_with_cvr(); // Outputs: const int 16 | } 17 | //] 18 | 19 | -------------------------------------------------------------------------------- /test/track_13621.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2018-2025 Antony Polukhin. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See 5 | // accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | class empty 14 | { 15 | }; 16 | 17 | int main() 18 | { 19 | std::string name = boost::typeindex::ctti_type_index::type_id().pretty_name(); 20 | BOOST_TEST(name.find("empty") != std::string::npos); 21 | return boost::report_errors(); 22 | } 23 | 24 | -------------------------------------------------------------------------------- /test/test_lib_anonymous.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2012-2025 Antony Polukhin. 3 | // 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #define TEST_LIB_SOURCE 10 | #include "test_lib_anonymous.hpp" 11 | 12 | namespace { 13 | class user_defined{}; 14 | } // anonymous namespace 15 | 16 | namespace test_lib { 17 | 18 | boost::typeindex::type_index get_anonymous_user_defined_class() { 19 | return boost::typeindex::type_id(); 20 | } 21 | 22 | boost::typeindex::type_index get_const_anonymous_user_defined_class() { 23 | return boost::typeindex::type_id_with_cvr(); 24 | } 25 | 26 | } 27 | 28 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | 15 | 16 | Boost.TypeIndex 17 | 27 | 28 | 29 |

30 | Automatic redirection failed, please go to 31 | ../../doc/html/boost_typeindex.html 32 |

33 |

34 | © 2014-2024 Antony Polukhin 35 |

36 | 37 | 38 | -------------------------------------------------------------------------------- /include/boost/type_index/detail/config.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013-2025 Antony Polukhin. 3 | // 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_TYPE_INDEX_DETAIL_CONFIG_HPP 10 | #define BOOST_TYPE_INDEX_DETAIL_CONFIG_HPP 11 | 12 | #if !defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 13 | #include 14 | #ifdef BOOST_HAS_PRAGMA_ONCE 15 | # pragma once 16 | #endif 17 | #endif 18 | 19 | #ifdef BOOST_TYPE_INDEX_INTERFACE_UNIT 20 | # define BOOST_TYPE_INDEX_BEGIN_MODULE_EXPORT export { 21 | # define BOOST_TYPE_INDEX_END_MODULE_EXPORT } 22 | #else 23 | # define BOOST_TYPE_INDEX_BEGIN_MODULE_EXPORT 24 | # define BOOST_TYPE_INDEX_END_MODULE_EXPORT 25 | #endif 26 | 27 | #if defined(BOOST_USE_MODULES) && !defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 28 | import boost.type_index; 29 | #endif 30 | 31 | #endif // BOOST_TYPE_INDEX_DETAIL_CONFIG_HPP 32 | 33 | -------------------------------------------------------------------------------- /test/test_lib_anonymous.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2012-2025 Antony Polukhin. 3 | // 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_TYPE_INDEX_TESTS_TEST_LIB_ANONYMOUS_HPP 10 | #define BOOST_TYPE_INDEX_TESTS_TEST_LIB_ANONYMOUS_HPP 11 | 12 | // MS compatible compilers support #pragma once 13 | #if defined(_MSC_VER) 14 | # pragma once 15 | #endif 16 | 17 | #include 18 | 19 | // This is ALWAYS a dynamic library 20 | #if defined(TEST_LIB_SOURCE) 21 | # define TEST_LIB_DECL BOOST_SYMBOL_EXPORT 22 | # else 23 | # define TEST_LIB_DECL BOOST_SYMBOL_IMPORT 24 | # endif 25 | 26 | namespace test_lib { 27 | 28 | TEST_LIB_DECL boost::typeindex::type_index get_anonymous_user_defined_class(); 29 | TEST_LIB_DECL boost::typeindex::type_index get_const_anonymous_user_defined_class(); 30 | 31 | } 32 | 33 | #endif // BOOST_TYPE_INDEX_TESTS_TEST_LIB_ANONYMOUS_HPP 34 | 35 | -------------------------------------------------------------------------------- /patched/boost_smart_ptr.patch: -------------------------------------------------------------------------------- 1 | From 03194eefcb9c3314054855d28bd9a90d3188768d Mon Sep 17 00:00:00 2001 2 | From: Antony Polukhin 3 | Date: Thu, 20 Feb 2014 18:50:10 +0400 4 | Subject: [PATCH] Use TypeIndex features in Boost.SharedPtr to avoid type_info 5 | related bugs 6 | 7 | --- 8 | include/boost/smart_ptr/detail/sp_counted_impl.hpp | 2 +- 9 | 1 file changed, 1 insertion(+), 1 deletion(-) 10 | 11 | diff --git a/include/boost/smart_ptr/detail/sp_counted_impl.hpp b/include/boost/smart_ptr/detail/sp_counted_impl.hpp 12 | index a7b43ae..5955036 100644 13 | --- a/include/boost/smart_ptr/detail/sp_counted_impl.hpp 14 | +++ b/include/boost/smart_ptr/detail/sp_counted_impl.hpp 15 | @@ -155,7 +155,7 @@ public: 16 | 17 | virtual void * get_deleter( detail::sp_typeinfo const & ti ) 18 | { 19 | - return ti == BOOST_SP_TYPEID(D)? &reinterpret_cast( del ): 0; 20 | + return ti == boost::typeind::type_id()? &reinterpret_cast( del ): 0; 21 | } 22 | 23 | virtual void * get_untyped_deleter() 24 | -- 25 | 1.8.5.3 26 | 27 | -------------------------------------------------------------------------------- /include/boost/type_index/runtime_cast.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Chris Glover, 2016. 3 | // 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_TYPE_INDEX_RUNTIME_CAST_HPP 10 | #define BOOST_TYPE_INDEX_RUNTIME_CAST_HPP 11 | 12 | #include 13 | 14 | /// \file runtime_cast.hpp 15 | /// \brief Contains the basic utilities necessary to fully emulate 16 | /// dynamic_cast for language level constructs (raw pointers and references). 17 | /// 18 | /// boost::typeindex::runtime_cast is a drop in replacement for dynamic_cast 19 | /// that can be used in situations where traditional rtti is either unavailable 20 | /// or undesirable. 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #ifdef BOOST_HAS_PRAGMA_ONCE 27 | # pragma once 28 | #endif 29 | 30 | #endif // BOOST_TYPE_INDEX_RUNTIME_CAST_HPP 31 | -------------------------------------------------------------------------------- /test/test_lib.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2012-2025 Antony Polukhin. 3 | // 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #define TEST_LIB_SOURCE 10 | #include "test_lib.hpp" 11 | 12 | namespace user_defined_namespace { 13 | class user_defined{}; 14 | } 15 | 16 | namespace test_lib { 17 | 18 | boost::typeindex::type_index get_integer() { 19 | return boost::typeindex::type_id(); 20 | } 21 | 22 | boost::typeindex::type_index get_user_defined_class() { 23 | return boost::typeindex::type_id(); 24 | } 25 | 26 | boost::typeindex::type_index get_const_integer() { 27 | return boost::typeindex::type_id_with_cvr(); 28 | } 29 | 30 | boost::typeindex::type_index get_const_user_defined_class() { 31 | return boost::typeindex::type_id_with_cvr(); 32 | } 33 | 34 | #if !defined(BOOST_HAS_PRAGMA_DETECT_MISMATCH) || !defined(_CPPRTTI) 35 | // Just do nothing 36 | void accept_typeindex(const boost::typeindex::type_index&) {} 37 | #endif 38 | 39 | } 40 | 41 | -------------------------------------------------------------------------------- /test/ctti_print_name.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2012-2025 Antony Polukhin. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See 5 | // accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | 10 | // This cpp file: 11 | // * tests BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING macro 12 | // * outputs full ctti name so that TypeIndex library could be adjust to new compiler without requesting regression tester's help 13 | #define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING (0,0,false,"") 14 | #include 15 | 16 | namespace user_defined_namespace { 17 | class user_defined_class {}; 18 | } 19 | 20 | class empty 21 | { 22 | }; 23 | 24 | 25 | int main() 26 | { 27 | using namespace boost::typeindex; 28 | 29 | std::cout << "int: " 30 | << ctti_type_index::type_id() << '\n'; 31 | 32 | std::cout << "double: " 33 | << ctti_type_index::type_id() << '\n'; 34 | 35 | std::cout << "user_defined_namespace::user_defined_class: " 36 | << ctti_type_index::type_id() << '\n'; 37 | 38 | 39 | std::cout << "empty: " 40 | << ctti_type_index::type_id() << '\n'; 41 | 42 | return 0; 43 | } 44 | 45 | -------------------------------------------------------------------------------- /test/test_lib.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2012-2025 Antony Polukhin. 3 | // 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_TYPE_INDEX_TESTS_TEST_LIB_HPP 10 | #define BOOST_TYPE_INDEX_TESTS_TEST_LIB_HPP 11 | 12 | // MS compatible compilers support #pragma once 13 | #if defined(_MSC_VER) 14 | # pragma once 15 | #endif 16 | 17 | #include 18 | 19 | // This is ALWAYS a dynamic library 20 | #if defined(TEST_LIB_SOURCE) 21 | # define TEST_LIB_DECL BOOST_SYMBOL_EXPORT 22 | # else 23 | # define TEST_LIB_DECL BOOST_SYMBOL_IMPORT 24 | # endif 25 | 26 | namespace test_lib { 27 | 28 | TEST_LIB_DECL boost::typeindex::type_index get_integer(); 29 | TEST_LIB_DECL boost::typeindex::type_index get_user_defined_class(); 30 | 31 | TEST_LIB_DECL boost::typeindex::type_index get_const_integer(); 32 | TEST_LIB_DECL boost::typeindex::type_index get_const_user_defined_class(); 33 | 34 | #if !defined(BOOST_HAS_PRAGMA_DETECT_MISMATCH) || !defined(_CPPRTTI) 35 | // This is required for checking RTTI on/off linkage 36 | TEST_LIB_DECL void accept_typeindex(const boost::typeindex::type_index&); 37 | #endif 38 | 39 | } 40 | 41 | #endif // BOOST_TYPE_INDEX_TESTS_LIB1_HPP 42 | 43 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Generated by `boostdep --cmake type_index` 2 | # Copyright 2020, 2021 Peter Dimov 3 | # Distributed under the Boost Software License, Version 1.0. 4 | # https://www.boost.org/LICENSE_1_0.txt 5 | 6 | cmake_minimum_required(VERSION 3.5...3.31) 7 | 8 | project(boost_type_index VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX) 9 | 10 | if (BOOST_USE_MODULES) 11 | add_library(boost_type_index) 12 | target_sources(boost_type_index PUBLIC 13 | FILE_SET modules_public TYPE CXX_MODULES FILES modules/boost_type_index.cppm 14 | ) 15 | 16 | target_compile_features(boost_type_index PUBLIC cxx_std_20) 17 | target_compile_definitions(boost_type_index PUBLIC BOOST_USE_MODULES) 18 | if (CMAKE_CXX_COMPILER_IMPORT_STD) 19 | target_compile_definitions(boost_type_index PRIVATE BOOST_TYPE_INDEX_USE_STD_MODULE) 20 | message(STATUS "Using `import std;`") 21 | else() 22 | message(STATUS "`import std;` is not awailable") 23 | endif() 24 | set(__scope PUBLIC) 25 | else() 26 | add_library(boost_type_index INTERFACE) 27 | set(__scope INTERFACE) 28 | endif() 29 | 30 | target_include_directories(boost_type_index ${__scope} include) 31 | add_library(Boost::type_index ALIAS boost_type_index) 32 | 33 | target_link_libraries(boost_type_index 34 | ${__scope} 35 | Boost::config 36 | Boost::container_hash 37 | Boost::throw_exception 38 | ) 39 | 40 | if(BUILD_TESTING) 41 | add_subdirectory(test) 42 | endif() 43 | -------------------------------------------------------------------------------- /test/compare_ctti_stl.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Klemens Morgenstern, 2012-2015. 2 | // Copyright 2019-2025 Antony Polukhin. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See 5 | // accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | namespace my_namespace1 { 14 | class my_class{}; 15 | } 16 | 17 | 18 | namespace my_namespace2 { 19 | class my_class{}; 20 | } 21 | 22 | namespace my_namespace3 23 | { 24 | template 25 | struct my_template {}; 26 | 27 | } 28 | 29 | #if !defined( BOOST_NO_RTTI ) 30 | 31 | template 32 | void compare() 33 | { 34 | using ctti = boost::typeindex::ctti_type_index; 35 | using stl = boost::typeindex::stl_type_index; 36 | BOOST_TEST_EQ( 37 | ctti::type_id().pretty_name(), 38 | stl::type_id().pretty_name() 39 | ); 40 | } 41 | 42 | 43 | int main() 44 | { 45 | compare(); 46 | compare(); 47 | compare(); 48 | 49 | #ifndef _MSC_VER // may add `class` to the type name 50 | compare(); 51 | 52 | compare >(); 55 | #endif 56 | 57 | return boost::report_errors(); 58 | } 59 | 60 | #else 61 | 62 | int main() 63 | { 64 | return 0; 65 | } 66 | 67 | #endif 68 | 69 | -------------------------------------------------------------------------------- /examples/inheritance.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2013-2025 Antony Polukhin 2 | 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See the accompanying file LICENSE_1_0.txt 5 | // or a copy at .) 6 | 7 | //[type_index_derived_example 8 | /*` 9 | The following example shows that `type_info` is able to store the real type, successfully getting through 10 | all the inheritances. 11 | 12 | Example works with and without RTTI." 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | struct A { 20 | BOOST_TYPE_INDEX_REGISTER_CLASS 21 | virtual ~A(){} 22 | }; 23 | struct B: public A { BOOST_TYPE_INDEX_REGISTER_CLASS }; 24 | struct C: public B { BOOST_TYPE_INDEX_REGISTER_CLASS }; 25 | struct D: public C { BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS() }; 26 | 27 | void print_real_type(const A& a) { 28 | std::cout << boost::typeindex::type_id_runtime(a).pretty_name() << '\n'; 29 | } 30 | 31 | int main() { 32 | C c; 33 | const A& c_as_a = c; 34 | print_real_type(c_as_a); // Outputs `struct C` 35 | print_real_type(B()); // Outputs `struct B` 36 | 37 | /*` 38 | It's also possible to use type_id_runtime with the BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS, which adds additional 39 | information for runtime_cast to work. 40 | */ 41 | D d; 42 | const A& d_as_a = d; 43 | print_real_type(d_as_a); // Outputs `struct D` 44 | 45 | } 46 | 47 | //] [/type_index_derived_example] 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [Boost.TypeIndex](https://boost.org/libs/type_index) 2 | Boost.TypeIndex is a part of the [Boost C++ Libraries](https://github.com/boostorg). It is a runtime/compile time copyable type info. 3 | 4 | ### Test results 5 | 6 | @ | Build | Tests coverage | More info 7 | ----------------|-------------- | -------------- |----------- 8 | Develop branch: | [![CI](https://github.com/boostorg/type_index/actions/workflows/ci.yml/badge.svg?branch=develop)](https://github.com/boostorg/type_index/actions/workflows/ci.yml) [![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...](https://regression.boost.io/develop/developer/type_index.html) 9 | Master branch: | [![CI](https://github.com/boostorg/type_index/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/boostorg/type_index/actions/workflows/ci.yml) [![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...](https://regression.boost.io/master/developer/type_index.html) 10 | 11 | 12 | [Latest developer documentation](https://www.boost.org/doc/libs/develop/doc/html/boost_typeindex.html) 13 | 14 | ### License 15 | 16 | Distributed under the [Boost Software License, Version 1.0](https://boost.org/LICENSE_1_0.txt). 17 | -------------------------------------------------------------------------------- /test/testing_crossmodule_anonymous.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2012-2025 Antony Polukhin. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See 5 | // accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | 10 | #include 11 | #include "test_lib_anonymous.hpp" 12 | 13 | #include 14 | 15 | #define BOOST_CHECK_NE(x, y) BOOST_CHECK(x != y) 16 | 17 | namespace { 18 | class user_defined{}; 19 | } 20 | 21 | void comparing_anonymous_types_between_modules() 22 | { 23 | boost::typeindex::type_index t_const_userdef = boost::typeindex::type_id_with_cvr(); 24 | boost::typeindex::type_index t_userdef = boost::typeindex::type_id(); 25 | 26 | // Known to fail on Clang and old versions of GCC. 27 | //BOOST_TEST_NE(t_userdef, test_lib::get_anonymous_user_defined_class()); 28 | //BOOST_TEST_NE(t_const_userdef, test_lib::get_const_anonymous_user_defined_class()); 29 | 30 | std::cout 31 | << "t_userdef == " << t_userdef 32 | << ", test_lib::get_anonymous_user_defined_class() == " << test_lib::get_anonymous_user_defined_class() 33 | << '\n'; 34 | std::cout 35 | << "t_const_userdef == " << t_const_userdef 36 | << ", test_lib::get_const_anonymous_user_defined_class() == " << test_lib::get_const_anonymous_user_defined_class() 37 | << '\n'; 38 | 39 | BOOST_TEST_NE(t_const_userdef, test_lib::get_anonymous_user_defined_class()); 40 | BOOST_TEST_NE(t_userdef, test_lib::get_const_anonymous_user_defined_class()); 41 | } 42 | 43 | int main() { 44 | comparing_anonymous_types_between_modules(); 45 | 46 | return boost::report_errors(); 47 | } 48 | 49 | -------------------------------------------------------------------------------- /doc/Jamfile.v2: -------------------------------------------------------------------------------- 1 | # Copyright 2011-2025 Antony Polukhin. 2 | # Use, modification, and distribution are 3 | # subject to the Boost Software License, Version 1.0. (See accompanying 4 | # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | using quickbook ; 7 | import boostbook : boostbook ; 8 | import doxygen ; 9 | 10 | doxygen autodoc 11 | : 12 | [ glob ../include/boost/type_index.hpp ] 13 | [ glob ../include/boost/type_index/*.hpp ] 14 | [ glob ../include/boost/type_index/runtime_cast/*.hpp ] 15 | : 16 | EXTRACT_ALL=NO 17 | HIDE_UNDOC_MEMBERS=YES 18 | EXTRACT_PRIVATE=NO 19 | ENABLE_PREPROCESSING=YES 20 | EXPAND_ONLY_PREDEF=YES 21 | MACRO_EXPANSION=YES 22 | "PREDEFINED=\"stl_type_info=std::type_info\" \\ 23 | \"BOOST_TYPE_INDEX_DOXYGEN_INVOKED\" \\ 24 | \"BOOST_CXX14_CONSTEXPR=constexpr\" \\ 25 | \"detail::stl_type_info=std::type_info\"" 26 | "boost.doxygen.reftitle=Boost.TypeIndex Header Reference" 27 | ; 28 | 29 | xml type_index : type_index.qbk : autodoc ; 30 | boostbook standalone 31 | : 32 | type_index 33 | : 34 | boost.root=http://www.boost.org/doc/libs/1_90_0 35 | # boost.root=../../../.. 36 | pdf:boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html 37 | ; 38 | 39 | ############################################################################### 40 | alias boostdoc 41 | : type_index 42 | : 43 | : autodoc 44 | : ; 45 | explicit boostdoc ; 46 | alias boostrelease ; 47 | explicit boostrelease ; 48 | -------------------------------------------------------------------------------- /include/boost/type_index/detail/ctti_register_class.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013-2025 Antony Polukhin. 3 | // 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_TYPE_INDEX_CTTI_REGISTER_CLASS_HPP 10 | #define BOOST_TYPE_INDEX_CTTI_REGISTER_CLASS_HPP 11 | 12 | /// \file ctti_register_class.hpp 13 | /// \brief Contains BOOST_TYPE_INDEX_REGISTER_CLASS macro implementation that uses boost::typeindex::ctti_type_index. 14 | /// Not intended for inclusion from user's code. 15 | 16 | #include 17 | 18 | #ifdef BOOST_HAS_PRAGMA_ONCE 19 | # pragma once 20 | #endif 21 | 22 | #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 23 | 24 | namespace boost { namespace typeindex { namespace detail { 25 | 26 | BOOST_TYPE_INDEX_BEGIN_MODULE_EXPORT 27 | 28 | template 29 | inline const ctti_data& ctti_construct_typeid_ref(const T*) noexcept { 30 | return boost::typeindex::ctti_construct(); 31 | } 32 | 33 | BOOST_TYPE_INDEX_END_MODULE_EXPORT 34 | 35 | }}} // namespace boost::typeindex::detail 36 | 37 | #endif // #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 38 | 39 | /// @cond 40 | #define BOOST_TYPE_INDEX_REGISTER_CLASS \ 41 | virtual const boost::typeindex::detail::ctti_data& boost_type_index_type_id_runtime_() const noexcept { \ 42 | return boost::typeindex::detail::ctti_construct_typeid_ref(this); \ 43 | } \ 44 | /**/ 45 | /// @endcond 46 | 47 | #endif // BOOST_TYPE_INDEX_CTTI_REGISTER_CLASS_HPP 48 | 49 | -------------------------------------------------------------------------------- /include/boost/type_index/detail/stl_register_class.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013-2025 Antony Polukhin. 3 | // 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_TYPE_INDEX_STL_REGISTER_CLASS_HPP 10 | #define BOOST_TYPE_INDEX_STL_REGISTER_CLASS_HPP 11 | 12 | /// \file stl_register_class.hpp 13 | /// \brief Contains BOOST_TYPE_INDEX_REGISTER_CLASS macro implementation that uses boost::typeindex::stl_type_index. 14 | /// Not intended for inclusion from user's code. 15 | 16 | #include 17 | 18 | #ifdef BOOST_HAS_PRAGMA_ONCE 19 | # pragma once 20 | #endif 21 | 22 | #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 23 | 24 | namespace boost { namespace typeindex { namespace detail { 25 | 26 | BOOST_TYPE_INDEX_BEGIN_MODULE_EXPORT 27 | 28 | template 29 | inline const stl_type_index::type_info_t& stl_construct_typeid_ref(const T*) noexcept { 30 | return typeid(T); 31 | } 32 | 33 | BOOST_TYPE_INDEX_END_MODULE_EXPORT 34 | 35 | }}} // namespace boost::typeindex::detail 36 | 37 | #endif // #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 38 | 39 | /// @cond 40 | #define BOOST_TYPE_INDEX_REGISTER_CLASS \ 41 | virtual const boost::typeindex::stl_type_index::type_info_t& boost_type_index_type_id_runtime_() const noexcept { \ 42 | return boost::typeindex::detail::stl_construct_typeid_ref(this); \ 43 | } \ 44 | /**/ 45 | /// @endcond 46 | 47 | #endif // BOOST_TYPE_INDEX_STL_REGISTER_CLASS_HPP 48 | 49 | -------------------------------------------------------------------------------- /modules/boost_type_index.cppm: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016-2025 Antony Polukhin 2 | // 3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | // To compile manually use a command like the folowing: 7 | // clang++ -I ../include -std=c++20 --precompile -x c++-module boost_type_index.cppm 8 | 9 | module; 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #if __has_include() 16 | # include 17 | #endif 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #ifndef BOOST_TYPE_INDEX_USE_STD_MODULE 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #endif 34 | 35 | #define BOOST_TYPE_INDEX_INTERFACE_UNIT 36 | 37 | export module boost.type_index; 38 | 39 | #ifdef BOOST_TYPE_INDEX_USE_STD_MODULE 40 | // Should not be in the global module fragment 41 | // https://eel.is/c++draft/module#global.frag-1 42 | import std; 43 | #endif 44 | 45 | #ifdef __clang__ 46 | # pragma clang diagnostic ignored "-Winclude-angled-in-module-purview" 47 | #endif 48 | 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | 60 | -------------------------------------------------------------------------------- /examples/registry.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2013-2025 Antony Polukhin 2 | 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See the accompanying file LICENSE_1_0.txt 5 | // or a copy at .) 6 | 7 | //[type_index_registry_example 8 | /*` 9 | The following example shows how an information about a type could be stored. 10 | Example works with and without RTTI. 11 | */ 12 | 13 | #include 14 | #include 15 | //<- 16 | // Making `#include ` visible in docs, while actually using `BOOST_TEST` 17 | // instead of `assert`. This is required to verify correct behavior even if NDEBUG 18 | // is defined and to avoid `unused local variable` warnings with defined NDEBUG. 19 | // 20 | // boost-no-inspect 21 | #include 22 | #ifdef assert 23 | # undef assert 24 | #endif 25 | #define assert(X) BOOST_TEST(X) 26 | /* !Comment block is not closed intentionaly! 27 | //-> 28 | #include 29 | //<- 30 | !Closing comment block! */ 31 | //-> 32 | 33 | int main() { 34 | boost::unordered_set types; 35 | 36 | // Storing some `boost::type_info`s 37 | types.insert(boost::typeindex::type_id()); 38 | types.insert(boost::typeindex::type_id()); 39 | 40 | // `types` variable contains two `boost::type_index`es: 41 | assert(types.size() == 2); 42 | 43 | // Const, volatile and reference will be striped from the type: 44 | bool is_inserted = types.insert(boost::typeindex::type_id()).second; 45 | assert(!is_inserted); 46 | assert(types.erase(boost::typeindex::type_id()) == 1); 47 | 48 | // We have erased the `float` type, only `int` remains 49 | assert(*types.begin() == boost::typeindex::type_id()); 50 | //<- 51 | return boost::report_errors(); 52 | //-> 53 | } 54 | 55 | //] [/type_index_registry_example] 56 | -------------------------------------------------------------------------------- /test/cmake_subdir_test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016-2025 Antony Polukhin 2 | # Distributed under the Boost Software License, Version 1.0. 3 | # See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt 4 | 5 | cmake_minimum_required(VERSION 3.5...4.0) 6 | 7 | project(type_index_subdir_test LANGUAGES CXX) 8 | 9 | foreach(dep IN ITEMS 10 | assert 11 | config 12 | core 13 | container_hash 14 | describe 15 | mp11 16 | smart_ptr 17 | throw_exception 18 | unordered 19 | predef) 20 | add_subdirectory(../../../${dep} boostorg/${dep}) 21 | endforeach() 22 | add_subdirectory(../../ boostorg/type_index) 23 | 24 | enable_testing() 25 | 26 | if (BOOST_USE_MODULES) 27 | add_executable(boost_type_index_module_usage ../../modules/usage_sample.cpp) 28 | target_link_libraries(boost_type_index_module_usage PRIVATE Boost::type_index) 29 | add_test(NAME boost_type_index_module_usage COMMAND boost_type_index_module_usage) 30 | 31 | # Make sure that mixing includes and imports is fine for different TU 32 | add_executable(boost_type_index_module_usage_mu ../../modules/usage_test_mu1.cpp ../../modules/usage_test_mu2.cpp) 33 | target_link_libraries(boost_type_index_module_usage_mu PRIVATE Boost::type_index) 34 | add_test(NAME boost_type_index_module_usage_mu COMMAND boost_type_index_module_usage_mu) 35 | endif() 36 | 37 | list(APPEND RUN_TESTS_SOURCES 38 | compare_ctti_stl.cpp 39 | ctti_print_name.cpp 40 | track_13621.cpp 41 | type_index_runtime_cast_test.cpp 42 | type_index_test.cpp 43 | ) 44 | 45 | foreach (testsourcefile ${RUN_TESTS_SOURCES}) 46 | get_filename_component(testname ${testsourcefile} NAME_WLE) 47 | add_executable(${PROJECT_NAME}_${testname} ../${testsourcefile}) 48 | target_link_libraries(${PROJECT_NAME}_${testname} Boost::type_index Boost::smart_ptr) 49 | add_test(NAME ${PROJECT_NAME}_${testname} COMMAND ${PROJECT_NAME}_${testname}) 50 | endforeach() 51 | -------------------------------------------------------------------------------- /include/boost/type_index/runtime_cast/detail/runtime_cast_impl.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Chris Glover, 2016. 3 | // 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_TYPE_INDEX_RUNTIME_CAST_DETAIL_RUNTIME_CAST_IMPL_HPP 10 | #define BOOST_TYPE_INDEX_RUNTIME_CAST_DETAIL_RUNTIME_CAST_IMPL_HPP 11 | 12 | /// \file runtime_cast_impl.hpp 13 | /// \brief Contains the overload of boost::typeindex::runtime_cast for 14 | /// pointer types. 15 | /// 16 | /// boost::typeindex::runtime_cast can be used to emulate dynamic_cast 17 | /// functionality on platorms that don't provide it or should the user 18 | /// desire opt in functionality instead of enabling it system wide. 19 | 20 | #include 21 | 22 | #if !defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 23 | #include 24 | #endif 25 | 26 | #ifdef BOOST_HAS_PRAGMA_ONCE 27 | # pragma once 28 | #endif 29 | 30 | namespace boost { namespace typeindex { 31 | 32 | namespace detail { 33 | 34 | template 35 | T* runtime_cast_impl(U* u, std::integral_constant) noexcept { 36 | return u; 37 | } 38 | 39 | template 40 | T const* runtime_cast_impl(U const* u, std::integral_constant) noexcept { 41 | return u; 42 | } 43 | 44 | template 45 | T* runtime_cast_impl(U* u, std::integral_constant) noexcept { 46 | return const_cast(static_cast( 47 | u->boost_type_index_find_instance_(boost::typeindex::type_id()) 48 | )); 49 | } 50 | 51 | template 52 | T const* runtime_cast_impl(U const* u, std::integral_constant) noexcept { 53 | return static_cast(u->boost_type_index_find_instance_(boost::typeindex::type_id())); 54 | } 55 | 56 | } // namespace detail 57 | 58 | }} // namespace boost::typeindex 59 | 60 | #endif // BOOST_TYPE_INDEX_RUNTIME_CAST_DETAIL_RUNTIME_CAST_IMPL_HPP 61 | -------------------------------------------------------------------------------- /test/testing_crossmodule.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2012-2025 Antony Polukhin. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See 5 | // accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | #include "test_lib.hpp" 10 | 11 | #include 12 | 13 | namespace user_defined_namespace { 14 | class user_defined{}; 15 | } 16 | 17 | void comparing_types_between_modules() 18 | { 19 | boost::typeindex::type_index t_const_int = boost::typeindex::type_id_with_cvr(); 20 | boost::typeindex::type_index t_int = boost::typeindex::type_id(); 21 | 22 | BOOST_TEST_EQ(t_int, test_lib::get_integer()); 23 | BOOST_TEST_EQ(t_const_int, test_lib::get_const_integer()); 24 | BOOST_TEST_NE(t_const_int, test_lib::get_integer()); 25 | BOOST_TEST_NE(t_int, test_lib::get_const_integer()); 26 | 27 | 28 | boost::typeindex::type_index t_const_userdef 29 | = boost::typeindex::type_id_with_cvr(); 30 | boost::typeindex::type_index t_userdef 31 | = boost::typeindex::type_id(); 32 | 33 | BOOST_TEST_EQ(t_userdef, test_lib::get_user_defined_class()); 34 | BOOST_TEST_EQ(t_const_userdef, test_lib::get_const_user_defined_class()); 35 | BOOST_TEST_NE(t_const_userdef, test_lib::get_user_defined_class()); 36 | BOOST_TEST_NE(t_userdef, test_lib::get_const_user_defined_class()); 37 | 38 | 39 | BOOST_TEST_NE(t_userdef, test_lib::get_integer()); 40 | BOOST_TEST_NE(t_const_userdef, test_lib::get_integer()); 41 | BOOST_TEST_NE(t_int, test_lib::get_user_defined_class()); 42 | BOOST_TEST_NE(t_const_int, test_lib::get_const_user_defined_class()); 43 | 44 | // MSVC supports detect_missmatch pragma, but /GR- silently switch disable the link time check. 45 | // /GR- undefies the _CPPRTTI macro. Using it to detect working detect_missmatch pragma. 46 | #if !defined(BOOST_HAS_PRAGMA_DETECT_MISMATCH) || !defined(_CPPRTTI) 47 | test_lib::accept_typeindex(t_int); 48 | #endif 49 | } 50 | 51 | 52 | int main() { 53 | comparing_types_between_modules(); 54 | 55 | return boost::report_errors(); 56 | } 57 | 58 | -------------------------------------------------------------------------------- /include/boost/type_index/runtime_cast/std_shared_ptr_cast.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Chris Glover, 2016. 3 | // 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_TYPE_INDEX_RUNTIME_CAST_STD_SHARED_PTR_CAST_HPP 10 | #define BOOST_TYPE_INDEX_RUNTIME_CAST_STD_SHARED_PTR_CAST_HPP 11 | 12 | /// \file std_shared_ptr_cast.hpp 13 | /// \brief Contains the overload of boost::typeindex::runtime_pointer_cast for 14 | /// std::shared_ptr types. 15 | 16 | #include 17 | 18 | #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 19 | 20 | #include 21 | 22 | #if !defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 23 | #include 24 | #endif 25 | 26 | #ifdef BOOST_HAS_PRAGMA_ONCE 27 | # pragma once 28 | #endif 29 | 30 | namespace boost { namespace typeindex { 31 | 32 | BOOST_TYPE_INDEX_BEGIN_MODULE_EXPORT 33 | 34 | /// \brief Creates a new instance of std::shared_ptr whose stored pointer is obtained from u's 35 | /// stored pointer using a runtime_cast. 36 | /// 37 | /// The new shared_ptr will share ownership with u, except that it is empty if the runtime_cast 38 | /// performed by runtime_pointer_cast returns a null pointer. 39 | /// \tparam T The desired target type to return a pointer of. 40 | /// \tparam U A complete class type of the source instance pointed to from u. 41 | /// \return If there exists a valid conversion from U* to T*, returns a std::shared_ptr 42 | /// that points to an address suitably offset from u. 43 | /// If no such conversion exists, returns std::shared_ptr(); 44 | template 45 | std::shared_ptr runtime_pointer_cast(std::shared_ptr const& u) { 46 | T* value = detail::runtime_cast_impl(u.get(), std::is_base_of()); 47 | if(value) 48 | return std::shared_ptr(u, value); 49 | return std::shared_ptr(); 50 | } 51 | 52 | BOOST_TYPE_INDEX_END_MODULE_EXPORT 53 | 54 | }} // namespace boost::typeindex 55 | 56 | #endif // #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 57 | 58 | #endif // BOOST_TYPE_INDEX_RUNTIME_CAST_STD_SHARED_PTR_CAST_HPP 59 | -------------------------------------------------------------------------------- /include/boost/type_index/runtime_cast/boost_shared_ptr_cast.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Chris Glover, 2016. 3 | // 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_TYPE_INDEX_RUNTIME_CAST_BOOST_SHARED_PTR_CAST_HPP 10 | #define BOOST_TYPE_INDEX_RUNTIME_CAST_BOOST_SHARED_PTR_CAST_HPP 11 | 12 | /// \file boost_shared_ptr_cast.hpp 13 | /// \brief Contains the overload of boost::typeindex::runtime_pointer_cast for 14 | /// boost::shared_ptr types. 15 | 16 | #include 17 | 18 | #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 19 | 20 | #include 21 | 22 | #if !defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 23 | #include 24 | #endif 25 | 26 | #ifdef BOOST_HAS_PRAGMA_ONCE 27 | # pragma once 28 | #endif 29 | 30 | namespace boost { namespace typeindex { 31 | 32 | BOOST_TYPE_INDEX_BEGIN_MODULE_EXPORT 33 | 34 | /// \brief Creates a new instance of smart pointer whose stored pointer is obtained from u's 35 | /// stored pointer using a runtime_cast. 36 | /// 37 | /// The new shared_ptr will share ownership with u, except that it is empty if the runtime_cast 38 | /// performed by runtime_pointer_cast returns a null pointer. 39 | /// \tparam T The desired target type to return a pointer of. 40 | /// \tparam U A complete class type of the source instance pointed to from u. 41 | /// \return If there exists a valid conversion from U* to T*, returns a boost::shared_ptr 42 | /// that points to an address suitably offset from u. 43 | /// If no such conversion exists, returns boost::shared_ptr(); 44 | template class SmartPointer> 45 | auto runtime_pointer_cast(SmartPointer const& u) -> decltype(u.use_count(), SmartPointer()) { 46 | T* value = detail::runtime_cast_impl(u.get(), std::is_base_of()); 47 | if(value) 48 | return SmartPointer(u, value); 49 | return SmartPointer(); 50 | } 51 | 52 | BOOST_TYPE_INDEX_END_MODULE_EXPORT 53 | 54 | }} // namespace boost::typeindex 55 | 56 | #endif // #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 57 | 58 | #endif // BOOST_TYPE_INDEX_RUNTIME_CAST_BOOST_SHARED_PTR_CAST_HPP 59 | -------------------------------------------------------------------------------- /examples/user_defined_typeinfo.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2013-2025 Antony Polukhin 2 | 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See the accompanying file LICENSE_1_0.txt 5 | // or a copy at .) 6 | 7 | 8 | //[type_index_my_type_index_worldwide_macro 9 | /*` 10 | There is an easy way to force `boost::typeindex::type_id` to use your own type_index class. 11 | 12 | All we need to do is just define `BOOST_TYPE_INDEX_USER_TYPEINDEX` to the full path to header file 13 | of your type index class: 14 | */ 15 | 16 | // BOOST_TYPE_INDEX_USER_TYPEINDEX must be defined *BEFORE* first inclusion of 17 | #define BOOST_TYPE_INDEX_USER_TYPEINDEX 18 | #include 19 | //] [/type_index_my_type_index_worldwide_macro] 20 | 21 | // boost-no-inspect 22 | #include 23 | #ifdef assert 24 | # undef assert 25 | #endif 26 | #define assert(X) BOOST_TEST(X) 27 | 28 | 29 | using namespace my_namespace; 30 | 31 | int main() { 32 | //[type_index_my_type_index_usage 33 | /*` 34 | Finally we can use the my_type_index class for getting type indexes: 35 | */ 36 | 37 | my_type_index 38 | cl1 = my_type_index::type_id(), 39 | st1 = my_type_index::type_id(), 40 | st2 = my_type_index::type_id(), 41 | vec = my_type_index::type_id() 42 | ; 43 | 44 | assert(cl1 != st1); 45 | assert(st2 == st1); 46 | assert(vec.pretty_name() == "my_classes"); 47 | assert(cl1.pretty_name() == "my_class"); 48 | 49 | //] [/type_index_my_type_index_usage] 50 | 51 | //[type_index_my_type_index_type_id_runtime_test 52 | /*` 53 | Now the following example will compile and work. 54 | */ 55 | my_struct str; 56 | my_class& reference = str; 57 | assert(my_type_index::type_id() == my_type_index::type_id_runtime(reference)); 58 | //][/type_index_my_type_index_type_id_runtime_test] 59 | 60 | //[type_index_my_type_index_worldwide_usage 61 | /*` 62 | That's it! Now all TypeIndex global methods and typedefs will be using your class: 63 | */ 64 | boost::typeindex::type_index worldwide = boost::typeindex::type_id(); 65 | assert(worldwide.pretty_name() == "my_classes"); 66 | assert(worldwide == my_type_index::type_id()); 67 | //][/type_index_my_type_index_worldwide_usage] 68 | //<- 69 | return boost::report_errors(); 70 | //-> 71 | } 72 | 73 | 74 | -------------------------------------------------------------------------------- /examples/runtime_cast.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Chris Glover, 2016. 3 | // 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | //[type_index_runtime_cast_example 10 | /*` 11 | The following example shows that `runtime_cast` is able to find a valid pointer 12 | in various class hierarchies regardless of inheritance or type relation. 13 | 14 | Example works with and without RTTI." 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | struct A { 21 | BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS() 22 | virtual ~A() 23 | {} 24 | }; 25 | 26 | struct B { 27 | BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS() 28 | virtual ~B() 29 | {} 30 | }; 31 | 32 | struct C : A { 33 | BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(A) 34 | }; 35 | 36 | struct D : B { 37 | BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(B) 38 | }; 39 | 40 | struct E : C, D { 41 | BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(C, D) 42 | }; 43 | 44 | int main() { 45 | C c; 46 | A* a = &c; 47 | 48 | if(C* cp = boost::typeindex::runtime_cast(a)) { 49 | std::cout << "Yes, a points to a C: " 50 | << a << "->" << cp << '\n'; 51 | } 52 | else { 53 | std::cout << "Error: Expected a to point to a C" << '\n'; 54 | } 55 | 56 | if(E* ce = boost::typeindex::runtime_cast(a)) { 57 | std::cout << "Error: Expected a to not points to an E: " 58 | << a << "->" << ce << '\n'; 59 | } 60 | else { 61 | std::cout << "But, a does not point to an E" << '\n'; 62 | } 63 | 64 | E e; 65 | C* cp2 = &e; 66 | if(D* dp = boost::typeindex::runtime_cast(cp2)) { 67 | std::cout << "Yes, we can cross-cast from a C* to a D* when we actually have an E: " 68 | << cp2 << "->" << dp << '\n'; 69 | } 70 | else { 71 | std::cout << "Error: Expected cp to point to a D" << '\n'; 72 | } 73 | 74 | /*` 75 | Alternatively, we can use runtime_pointer_cast so we don't need to specity the target as a pointer. 76 | This works for smart_ptr types too. 77 | */ 78 | A* ap = &e; 79 | if(B* bp = boost::typeindex::runtime_pointer_cast(ap)) { 80 | std::cout << "Yes, we can cross-cast and up-cast at the same time." 81 | << ap << "->" << bp << '\n'; 82 | } 83 | else { 84 | std::cout << "Error: Expected ap to point to a B" << '\n'; 85 | } 86 | 87 | return 0; 88 | } 89 | 90 | //] [/type_index_runtime_cast_example] 91 | -------------------------------------------------------------------------------- /examples/demangled_names.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2013-2025 Antony Polukhin 2 | 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See the accompanying file LICENSE_1_0.txt 5 | // or a copy at .) 6 | 7 | 8 | //[type_index_names_example 9 | /*` 10 | The following example shows how short (mangled) and human readable type names could be obtained from a type. 11 | Works with and without RTTI. 12 | */ 13 | 14 | 15 | #include 16 | #include 17 | 18 | template 19 | void foo(T) { 20 | std::cout << "\n Short name: " << boost::typeindex::type_id().raw_name(); 21 | std::cout << "\n Readable name: " << boost::typeindex::type_id().pretty_name(); 22 | } 23 | 24 | struct user_defined_type{}; 25 | 26 | namespace ns1 { namespace ns2 { 27 | struct user_defined_type{}; 28 | }} // namespace ns1::ns2 29 | 30 | namespace { 31 | struct in_anon_type{}; 32 | } // anonymous namespace 33 | 34 | int main() { 35 | // Call to 36 | foo(1); 37 | // will output something like this: 38 | // 39 | // (RTTI on) (RTTI off) 40 | // Short name: i Short name: int] 41 | // Readable name: int Readable name: int 42 | 43 | user_defined_type t; 44 | foo(t); 45 | // Will output: 46 | // 47 | // (RTTI on) (RTTI off) 48 | // Short name: 17user_defined_type user_defined_type] 49 | // Readable name: user_defined_type user_defined_type 50 | 51 | ns1::ns2::user_defined_type t_in_ns; 52 | foo(t_in_ns); 53 | // Will output: 54 | // 55 | // (RTTI on) (RTTI off) 56 | // Short name: N3ns13ns217user_defined_typeE ns1::ns2::user_defined_type] 57 | // Readable name: ns1::ns2::user_defined_type ns1::ns2::user_defined_type 58 | 59 | in_anon_type anon_t; 60 | foo(anon_t); 61 | // Will output: 62 | // 63 | // (RTTI on) (RTTI off) 64 | // Short name: N12_GLOBAL__N_112in_anon_typeE {anonymous}::in_anon_type] 65 | // Readable name: (anonymous namespace)::in_anon_type {anonymous}::in_anon_type 66 | } 67 | 68 | /*` 69 | Short names are very compiler dependant: some compiler will output `.H`, others `i`. 70 | 71 | Readable names may also differ between compilers: `struct user_defined_type`, `user_defined_type`. 72 | 73 | [warning With RTTI off different classes with same names in anonymous namespace may collapse. See 'RTTI emulation limitations'. ] 74 | */ 75 | 76 | //] [/type_index_names_example] 77 | -------------------------------------------------------------------------------- /examples/exact_types_match.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2013-2025 Antony Polukhin 2 | 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See the accompanying file LICENSE_1_0.txt 5 | // or a copy at .) 6 | 7 | //[type_index_exact_type_match_example 8 | /*` 9 | The following example shows that `type_index` (and `type_info`) is able to store the exact type, 10 | without stripping const, volatile and references. Example works with and without RTTI. 11 | 12 | In this example we'll create a class that stores a pointer to function and remembers the exact type of the 13 | parameter the function accepts. When the call to the bound function is made, he actual input parameter 14 | type is checked against the stored parameter type and an exception is thrown in case of mismatch. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | //<- 23 | // Making `#include ` visible in docs, while actually using hand-made check 24 | // instead of `assert`. This is required to verify correct behavior even if NDEBUG 25 | // is defined and to avoid `unused local variable` warnings with defined NDEBUG. 26 | // 27 | // boost-no-inspect 28 | #ifdef assert 29 | # undef assert 30 | #endif 31 | #define assert(X) if (!(X)) std::exit(__LINE__) 32 | /* !Comment block is not closed intentionaly! 33 | //-> 34 | #include 35 | //<- 36 | !Closing comment block! */ 37 | //-> 38 | 39 | class type_erased_unary_function { 40 | void* function_ptr_; 41 | boost::typeindex::type_index exact_param_t_; 42 | 43 | public: 44 | template 45 | type_erased_unary_function(void(*ptr)(ParamT)) 46 | : function_ptr_(reinterpret_cast(ptr)) // ptr - is a pointer to function returning `void` and accepting parameter of type `ParamT` 47 | , exact_param_t_(boost::typeindex::type_id_with_cvr()) 48 | {} 49 | 50 | template 51 | void call(ParamT v) { 52 | if (exact_param_t_ != boost::typeindex::type_id_with_cvr()) { 53 | throw std::runtime_error("Incorrect `ParamT`"); 54 | } 55 | 56 | return (reinterpret_cast(function_ptr_))(v); 57 | } 58 | }; 59 | 60 | void foo(int){} 61 | 62 | int main() { 63 | type_erased_unary_function func(&foo); 64 | func.call(100); // OK, `100` has type `int` 65 | 66 | try { 67 | int i = 100; 68 | 69 | // An attempt to convert stored function to a function accepting reference 70 | func.call(i); // Will throw, because types `int&` and `int` mismatch 71 | 72 | assert(false); 73 | } catch (const std::runtime_error& /*e*/) {} 74 | } 75 | 76 | //] [/type_index_exact_type_match_example] 77 | -------------------------------------------------------------------------------- /examples/constexpr14_sort_check.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2013-2025 Antony Polukhin 2 | 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See the accompanying file LICENSE_1_0.txt 5 | // or a copy at .) 6 | 7 | #include 8 | 9 | #if !defined(BOOST_NO_CXX14_CONSTEXPR) && !defined(BOOST_NO_CXX11_CONSTEXPR) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && (!defined(_MSC_VER) || (_MSC_VER > 1916)) 10 | 11 | //[type_index_constexpr14_sort_check_example 12 | /*` 13 | The following example shows that `boost::typeindex::ctti_type_index` is usable at compile time on 14 | a C++14 compatible compilers to check order of template parameters. 15 | 16 | Consider the situation when we have a function that accepts std::tuple, boost::variant or some other class that uses variadic templates: 17 | */ 18 | 19 | template class types{}; 20 | 21 | template 22 | void do_something(const types& t) noexcept; 23 | 24 | /*` 25 | 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 26 | consumes space in the resulting program: 27 | 28 | // Types are same, but different order leads to new instantionation of do_something function. 29 | types 30 | types 31 | types 32 | types 33 | types 34 | types 35 | 36 | One of the ways to reduce instantinations count is to force the types to have some order: 37 | */ 38 | 39 | 40 | #include 41 | 42 | // Implementing type trait that returns true if the types are sorted lexographicaly 43 | template 44 | constexpr bool is_asc_sorted(types) noexcept { 45 | return true; 46 | } 47 | 48 | template 49 | constexpr bool is_asc_sorted(types) noexcept { 50 | using namespace boost::typeindex; 51 | return ctti_type_index::type_id() <= ctti_type_index::type_id() 52 | && is_asc_sorted(types()); 53 | } 54 | 55 | 56 | // Using the newly created `is_asc_sorted` trait: 57 | template 58 | void do_something(const types& /*value*/) noexcept { 59 | static_assert( 60 | is_asc_sorted( types() ), 61 | "T... for do_something(const types& t) must be sorted ascending" 62 | ); 63 | } 64 | 65 | int main() { 66 | do_something( types() ); 67 | // do_something( types() ); // Fails the static_assert! 68 | } 69 | //] [/type_index_constexpr14_sort_check_example] 70 | 71 | #else // #if !defined(BOOST_NO_CXX14_CONSTEXPR) && !defined(BOOST_NO_CXX11_CONSTEXPR) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && (!defined(_MSC_VER) || (_MSC_VER > 1916)) 72 | 73 | int main() {} 74 | 75 | #endif 76 | 77 | -------------------------------------------------------------------------------- /include/boost/type_index/runtime_cast/reference_cast.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Chris Glover, 2016. 3 | // 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_TYPE_INDEX_RUNTIME_CAST_REFERENCE_CAST_HPP 10 | #define BOOST_TYPE_INDEX_RUNTIME_CAST_REFERENCE_CAST_HPP 11 | 12 | /// \file reference_cast.hpp 13 | /// \brief Contains the overload of boost::typeindex::runtime_cast for 14 | /// reference types. 15 | 16 | #include 17 | 18 | #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 19 | 20 | #include 21 | 22 | #if !defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 23 | #include 24 | #include 25 | 26 | #include 27 | #endif 28 | 29 | #ifdef BOOST_HAS_PRAGMA_ONCE 30 | # pragma once 31 | #endif 32 | 33 | namespace boost { namespace typeindex { 34 | 35 | BOOST_TYPE_INDEX_BEGIN_MODULE_EXPORT 36 | 37 | /// \brief Indicates that runtime_cast was unable to perform the desired cast operation 38 | /// because the source instance was not also an instance of the target type. 39 | struct BOOST_SYMBOL_VISIBLE bad_runtime_cast : std::exception 40 | {}; 41 | 42 | /// \brief Safely converts references to classes up, down, and sideways along the inheritance hierarchy. 43 | /// \tparam T The desired target type. Like dynamic_cast, must be a pointer to complete class type. 44 | /// \tparam U A complete class type of the source instance, u. 45 | /// \return If there exists a valid conversion from U& to T, returns a T that references an address 46 | /// suitably offset from u. If no such conversion exists, throws boost::typeindex::bad_runtime_cast. 47 | template 48 | typename std::add_lvalue_reference::type runtime_cast(U& u) { 49 | using impl_type = typename std::remove_reference::type; 50 | impl_type* value = detail::runtime_cast_impl( 51 | std::addressof(u), std::is_base_of()); 52 | if(!value) 53 | BOOST_THROW_EXCEPTION(bad_runtime_cast()); 54 | return *value; 55 | } 56 | 57 | /// \brief Safely converts references to classes up, down, and sideways along the inheritance hierarchy. 58 | /// \tparam T The desired target type. Like dynamic_cast, must be a pointer to complete class type. 59 | /// \tparam U A complete class type of the source instance, u. 60 | /// \return If there exists a valid conversion from U const& to T const, returns a T const that references an address 61 | /// suitably offset from u. If no such conversion exists, throws boost::typeindex::bad_runtime_cast. 62 | template 63 | typename std::add_lvalue_reference::type runtime_cast(U const& u) { 64 | using impl_type = typename std::remove_reference::type; 65 | impl_type* value = detail::runtime_cast_impl( 66 | std::addressof(u), std::is_base_of()); 67 | if(!value) 68 | BOOST_THROW_EXCEPTION(bad_runtime_cast()); 69 | return *value; 70 | } 71 | 72 | BOOST_TYPE_INDEX_END_MODULE_EXPORT 73 | 74 | }} // namespace boost::typeindex 75 | 76 | #endif // #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 77 | 78 | #endif // BOOST_TYPE_INDEX_RUNTIME_CAST_REFERENCE_CAST_HPP 79 | -------------------------------------------------------------------------------- /test/appveyor.yml: -------------------------------------------------------------------------------- 1 | # Use, modification, and distribution are 2 | # subject to the Boost Software License, Version 1.0. (See accompanying 3 | # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 4 | # 5 | # Copyright 2016-2025 Antony Polukhin. 6 | 7 | # 8 | # See https://svn.boost.org/trac/boost/wiki/TravisCoverals for description of this file 9 | # and how it can be used with Boost libraries. 10 | # 11 | # File revision #6 12 | 13 | init: 14 | # boost-local/libs/ folder to put this library into. This may be useful, if you're for example running Travis 15 | # from `Boost.DLL` repo while Boost already has `dll` and with to replace `dll` with content of`Boost.DLL`. 16 | # 17 | # Otherwise just leave the default value - set BOOST_LIBS_FOLDER=%APPVEYOR_PROJECT_NAME% 18 | - set BOOST_LIBS_FOLDER=%APPVEYOR_PROJECT_NAME% 19 | 20 | ############################################################################################################### 21 | # From this point and below code is same for all the Boost libs 22 | ############################################################################################################### 23 | 24 | version: 1.64.{build}-{branch} 25 | 26 | # branches to build 27 | branches: 28 | except: 29 | - gh-pages 30 | 31 | skip_tags: true 32 | 33 | environment: 34 | matrix: 35 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 36 | TOOLSET: msvc-14.1,clang-win 37 | CXXSTD: 14,17 38 | ADDRMD: 32,64 39 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 40 | ADDPATH: C:\cygwin\bin; 41 | TOOLSET: gcc 42 | CXXSTD: 03,11,14,1z 43 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 44 | ADDPATH: C:\cygwin64\bin; 45 | TOOLSET: gcc 46 | CXXSTD: 03,11,14,1z 47 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 48 | ADDPATH: C:\mingw\bin; 49 | TOOLSET: gcc 50 | CXXSTD: 03,11,14,1z 51 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 52 | ADDPATH: C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin; 53 | TOOLSET: gcc 54 | CXXSTD: 03,11,14,1z 55 | 56 | before_build: 57 | - set BOOST_BRANCH=develop 58 | - if "%APPVEYOR_REPO_BRANCH%" == "master" set BOOST_BRANCH=master 59 | - echo "Testing %APPVEYOR_PROJECT_NAME%" 60 | # Cloning Boost libraries (fast nondeep cloning) 61 | - set BOOST=C:/boost-local 62 | - git clone -b %BOOST_BRANCH% --depth 10 https://github.com/boostorg/boost.git %BOOST% 63 | - cd %BOOST% 64 | - git submodule update --init --depth 10 tools/build tools/boostdep 65 | 66 | - rm -rf %BOOST%/libs/%BOOST_LIBS_FOLDER% 67 | - mv -f %APPVEYOR_BUILD_FOLDER% %BOOST%/libs/%BOOST_LIBS_FOLDER% 68 | - python tools/boostdep/depinst/depinst.py --include examples --git_args "--depth 10 --jobs 2" %BOOST_LIBS_FOLDER% 69 | 70 | build_script: 71 | - cmd /c bootstrap 72 | - b2.exe headers 73 | - cd %BOOST%/libs/%BOOST_LIBS_FOLDER%/test 74 | 75 | after_build: 76 | before_test: 77 | test_script: 78 | - PATH=%ADDPATH%%PATH% 79 | - if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD% 80 | - if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD% 81 | - echo "Running command ..\..\..\b2 -j3 toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release" 82 | - ..\..\..\b2.exe -j3 toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release cxxflags="-DBOOST_TRAVISCI_BUILD" 83 | 84 | after_test: 85 | on_success: 86 | on_failure: 87 | on_finish: 88 | -------------------------------------------------------------------------------- /examples/constexpr14_namespace_check.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2013-2025 Antony Polukhin 2 | 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See the accompanying file LICENSE_1_0.txt 5 | // or a copy at .) 6 | 7 | #include 8 | 9 | #include 10 | 11 | template 12 | void do_something(const T&) {} 13 | 14 | 15 | #if !defined(BOOST_NO_CXX14_CONSTEXPR) && !defined(BOOST_NO_CXX11_CONSTEXPR) 16 | // Implementation of this function is not essential for the example 17 | template 18 | constexpr bool starts_with(const char* name, const char (&ns)[N]) noexcept { 19 | for (std::size_t i = 0; i < N - 1; ++i) 20 | if (name[i] != ns[i]) 21 | return false; 22 | 23 | return true; 24 | } 25 | 26 | //[type_index_constexpr14_namespace_example 27 | /*` 28 | The following example shows that `boost::typeindex::ctti_type_index` is usable at compile time on 29 | a C++14 compatible compilers. 30 | 31 | In this example we'll create and use a constexpr function that checks namespace of the provided type. 32 | */ 33 | 34 | #include 35 | 36 | // Helper function that returns true if `name` starts with `substr` 37 | template 38 | constexpr bool starts_with(const char* name, const char (&substr)[N]) noexcept; 39 | 40 | 41 | // Function that returns true if `T` declared in namespace `ns` 42 | template 43 | constexpr bool in_namespace(const char (&ns)[N]) noexcept { 44 | const char* name = boost::typeindex::ctti_type_index::type_id().raw_name(); 45 | 46 | // Some compilers add `class ` or `struct ` before the namespace, so we need to skip those words first 47 | if (starts_with(name, "class ")) { 48 | name += sizeof("class ") - 1; 49 | } else if (starts_with(name, "struct ")) { 50 | name += sizeof("struct ") - 1; 51 | } 52 | 53 | return starts_with(name, ns) && starts_with(name + N - 1, "::"); 54 | } 55 | 56 | /*` 57 | Now when we have that wonderfull function, we can do static assertions and other compile-time validations: 58 | */ 59 | 60 | namespace my_project { 61 | struct serializer { 62 | template 63 | void serialize(const T& value) { 64 | static_assert( 65 | in_namespace("my_project::types") || in_namespace("my_project::types_ext"), 66 | "Only types from namespaces `my_project::types` and `my_project::types_ext` are allowed to be serialized using `my_project::serializer`" 67 | ); 68 | 69 | // Actual implementation of the serialization goes below 70 | // ... 71 | do_something(value); 72 | } 73 | }; 74 | 75 | namespace types { 76 | struct foo{}; 77 | struct bar{}; 78 | } 79 | } // namespace my_project 80 | 81 | int main() { 82 | my_project::serializer s; 83 | my_project::types::foo f; 84 | my_project::types::bar b; 85 | 86 | s.serialize(f); 87 | s.serialize(b); 88 | 89 | // short sh = 0; 90 | // s.serialize(sh); // Fails the static_assert! 91 | } 92 | //] [/type_index_constexpr14_namespace_example] 93 | 94 | #else // #if !defined(BOOST_NO_CXX14_CONSTEXPR) && !defined(BOOST_NO_CXX11_CONSTEXPR) 95 | 96 | int main() {} 97 | 98 | #endif 99 | 100 | -------------------------------------------------------------------------------- /examples/table_of_names.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2013-2025 Antony Polukhin 2 | 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See the accompanying file LICENSE_1_0.txt 5 | // or a copy at .) 6 | 7 | 8 | //[type_index_names_table 9 | /*` 10 | The following example shows how different type names look when we explicitly use classes for RTTI and RTT off. 11 | 12 | This example requires RTTI. For a more portable example see 'Getting human readable and mangled type names': 13 | */ 14 | 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | template 21 | void print(const char* name) { 22 | boost::typeindex::stl_type_index sti = boost::typeindex::stl_type_index::type_id(); 23 | boost::typeindex::ctti_type_index cti = boost::typeindex::ctti_type_index::type_id(); 24 | std::cout << "\t[" /* start of the row */ 25 | << "[" << name << "]" 26 | << "[`" << sti.raw_name() << "`] " 27 | << "[`" << sti.pretty_name() << "`] " 28 | << "[`" << cti.raw_name() << "`] " 29 | << "]\n" /* end of the row */ ; 30 | } 31 | 32 | struct user_defined_type{}; 33 | 34 | namespace ns1 { namespace ns2 { 35 | struct user_defined_type{}; 36 | }} // namespace ns1::ns2 37 | 38 | namespace { 39 | struct in_anon_type{}; 40 | } // anonymous namespace 41 | 42 | namespace ns3 { namespace { namespace ns4 { 43 | struct in_anon_type{}; 44 | }}} // namespace ns3::{anonymous}::ns4 45 | 46 | 47 | template 48 | class templ {}; 49 | 50 | template <> 51 | class templ {}; 52 | 53 | int main() { 54 | std::cout << "[table:id Table of names\n"; 55 | std::cout << "\t[[Type] [RTTI & raw_name] [RTTI & pretty_name] [noRTTI & raw_name]]\n"; 56 | 57 | print("User defined type"); 58 | print("In anonymous namespace"); 59 | print("In ns3::{anonymous}::ns4 namespace"); 60 | print >("Template class"); 61 | print >("Template class (full specialization)"); 62 | print, 64 | templ 65 | > >("Template class with templae classes"); 66 | 67 | 68 | std::cout << "]\n"; 69 | } 70 | 71 | /*` 72 | Code from the example will produce the following table: 73 | 74 | [table:id Table of names 75 | [[Type] [RTTI & raw_name] [RTTI & pretty_name] [noRTTI & raw_name]] 76 | [[User defined type][`17user_defined_type`] [`user_defined_type`] [`user_defined_type]`] ] 77 | [[In anonymous namespace][`N12_GLOBAL__N_112in_anon_typeE`] [`(anonymous namespace)::in_anon_type`] [`{anonymous}::in_anon_type]`] ] 78 | [[In ns3::{anonymous}::ns4 namespace][`N3ns312_GLOBAL__N_13ns412in_anon_typeE`] [`ns3::(anonymous namespace)::ns4::in_anon_type`] [`ns3::{anonymous}::ns4::in_anon_type]`] ] 79 | [[Template class][`5templIsiE`] [`templ`] [`templ]`] ] 80 | [[Template class (full specialization)][`5templIiiE`] [`templ`] [`templ]`] ] 81 | [[Template class with template classes][`5templIS_IcaES_Ii17user_defined_typeEE`] [`templ, templ >`] [`templ, templ >]`] ] 82 | ] 83 | 84 | We have not show the "noRTTI & pretty_name" column in the table because it is almost equal 85 | to "noRTTI & raw_name" column. 86 | 87 | [warning With RTTI off different classes with same names in anonymous namespace may collapse. See 'RTTI emulation limitations'. ] 88 | */ 89 | 90 | //] [/type_index_names_table] 91 | -------------------------------------------------------------------------------- /include/boost/type_index/runtime_cast/pointer_cast.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Chris Glover, 2016. 3 | // 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_TYPE_INDEX_RUNTIME_CAST_POINTER_CAST_HPP 10 | #define BOOST_TYPE_INDEX_RUNTIME_CAST_POINTER_CAST_HPP 11 | 12 | /// \file pointer_class.hpp 13 | /// \brief Contains the function overloads of boost::typeindex::runtime_cast for 14 | /// pointer types. 15 | 16 | #include 17 | 18 | #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 19 | 20 | #include 21 | #include 22 | 23 | #ifdef BOOST_HAS_PRAGMA_ONCE 24 | # pragma once 25 | #endif 26 | 27 | namespace boost { namespace typeindex { 28 | 29 | BOOST_TYPE_INDEX_BEGIN_MODULE_EXPORT 30 | 31 | /// \brief Safely converts pointers to classes up, down, and sideways along the inheritance hierarchy. 32 | /// \tparam T The desired target type. Like dynamic_cast, must be a pointer to complete class type. 33 | /// \tparam U A complete class type of the source instance, u. 34 | /// \return If there exists a valid conversion from U* to T, returns a T that points to 35 | /// an address suitably offset from u. If no such conversion exists, returns nullptr. 36 | template 37 | T runtime_cast(U* u) noexcept { 38 | using impl_type = typename std::remove_pointer::type; 39 | return detail::runtime_cast_impl(u, std::is_base_of()); 40 | } 41 | 42 | /// \brief Safely converts pointers to classes up, down, and sideways along the inheritance hierarchy. 43 | /// \tparam T The desired target type. Like dynamic_cast, must be a pointer to complete class type. 44 | /// \tparam U A complete class type of the source instance, u. 45 | /// \return If there exists a valid conversion from U* to T, returns a T that points to 46 | /// an address suitably offset from u. If no such conversion exists, returns nullptr. 47 | template 48 | T runtime_cast(U const* u) noexcept { 49 | using impl_type = typename std::remove_pointer::type; 50 | return detail::runtime_cast_impl(u, std::is_base_of()); 51 | } 52 | 53 | /// \brief Safely converts pointers to classes up, down, and sideways along the inheritance 54 | /// hierarchy. 55 | /// \tparam T The desired target type to return a pointer to. 56 | /// \tparam U A complete class type of the source instance, u. 57 | /// \return If there exists a valid conversion from U const* to T*, returns a T* 58 | /// that points to an address suitably offset from u. 59 | /// If no such conversion exists, returns nullptr. 60 | template 61 | T* runtime_pointer_cast(U* u) noexcept { 62 | return detail::runtime_cast_impl(u, std::is_base_of()); 63 | } 64 | 65 | /// \brief Safely converts pointers to classes up, down, and sideways along the inheritance 66 | /// hierarchy. 67 | /// \tparam T The desired target type to return a pointer to. 68 | /// \tparam U A complete class type of the source instance, u. 69 | /// \return If there exists a valid conversion from U const* to T const*, returns a T const* 70 | /// that points to an address suitably offset from u. 71 | /// If no such conversion exists, returns nullptr. 72 | template 73 | T const* runtime_pointer_cast(U const* u) noexcept { 74 | return detail::runtime_cast_impl(u, std::is_base_of()); 75 | } 76 | 77 | BOOST_TYPE_INDEX_END_MODULE_EXPORT 78 | 79 | }} // namespace boost::typeindex 80 | 81 | #endif // #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 82 | 83 | #endif // BOOST_TYPE_INDEX_RUNTIME_CAST_POINTER_CAST_HPP 84 | -------------------------------------------------------------------------------- /patched/boost_detail_sp_typeinfo.patch: -------------------------------------------------------------------------------- 1 | From b77c0af6af8bc4797defc3627878acc3cf7a6f39 Mon Sep 17 00:00:00 2001 2 | From: Antony Polukhin 3 | Date: Thu, 20 Feb 2014 17:57:24 +0400 4 | Subject: [PATCH] detail/sp_typeinfo.hpp now uses TypeIndex 5 | 6 | --- 7 | include/boost/detail/sp_typeinfo.hpp | 123 +++-------------------------------- 8 | 1 file changed, 8 insertions(+), 115 deletions(-) 9 | 10 | diff --git a/include/boost/detail/sp_typeinfo.hpp b/include/boost/detail/sp_typeinfo.hpp 11 | index 43fae78..fbdf86d 100644 12 | --- a/include/boost/detail/sp_typeinfo.hpp 13 | +++ b/include/boost/detail/sp_typeinfo.hpp 14 | @@ -10,126 +10,19 @@ 15 | // detail/sp_typeinfo.hpp 16 | // 17 | // Copyright 2007 Peter Dimov 18 | +// Copyright 2014 Antony Polukhin 19 | // 20 | // Distributed under the Boost Software License, Version 1.0. 21 | // See accompanying file LICENSE_1_0.txt or copy at 22 | // http://www.boost.org/LICENSE_1_0.txt) 23 | 24 | -#include 25 | +#include 26 | +namespace boost { namespace detail { 27 | + 28 | +typedef boost::typeind::type_info sp_typeinfo; 29 | + 30 | +}} // namespace boost::detail 31 | 32 | -#if defined( BOOST_NO_TYPEID ) 33 | - 34 | -#include 35 | -#include 36 | - 37 | -namespace boost 38 | -{ 39 | - 40 | -namespace detail 41 | -{ 42 | - 43 | -class sp_typeinfo 44 | -{ 45 | -private: 46 | - 47 | - sp_typeinfo( sp_typeinfo const& ); 48 | - sp_typeinfo& operator=( sp_typeinfo const& ); 49 | - 50 | - char const * name_; 51 | - 52 | -public: 53 | - 54 | - explicit sp_typeinfo( char const * name ): name_( name ) 55 | - { 56 | - } 57 | - 58 | - bool operator==( sp_typeinfo const& rhs ) const 59 | - { 60 | - return this == &rhs; 61 | - } 62 | - 63 | - bool operator!=( sp_typeinfo const& rhs ) const 64 | - { 65 | - return this != &rhs; 66 | - } 67 | - 68 | - bool before( sp_typeinfo const& rhs ) const 69 | - { 70 | - return std::less< sp_typeinfo const* >()( this, &rhs ); 71 | - } 72 | - 73 | - char const* name() const 74 | - { 75 | - return name_; 76 | - } 77 | -}; 78 | - 79 | -template struct sp_typeid_ 80 | -{ 81 | - static sp_typeinfo ti_; 82 | - 83 | - static char const * name() 84 | - { 85 | - return BOOST_CURRENT_FUNCTION; 86 | - } 87 | -}; 88 | - 89 | -#if defined(__SUNPRO_CC) 90 | -// see #4199, the Sun Studio compiler gets confused about static initialization 91 | -// constructor arguments. But an assignment works just fine. 92 | -template sp_typeinfo sp_typeid_< T >::ti_ = sp_typeid_< T >::name(); 93 | -#else 94 | -template sp_typeinfo sp_typeid_< T >::ti_(sp_typeid_< T >::name()); 95 | -#endif 96 | - 97 | -template struct sp_typeid_< T & >: sp_typeid_< T > 98 | -{ 99 | -}; 100 | - 101 | -template struct sp_typeid_< T const >: sp_typeid_< T > 102 | -{ 103 | -}; 104 | - 105 | -template struct sp_typeid_< T volatile >: sp_typeid_< T > 106 | -{ 107 | -}; 108 | - 109 | -template struct sp_typeid_< T const volatile >: sp_typeid_< T > 110 | -{ 111 | -}; 112 | - 113 | -} // namespace detail 114 | - 115 | -} // namespace boost 116 | - 117 | -#define BOOST_SP_TYPEID(T) (boost::detail::sp_typeid_::ti_) 118 | - 119 | -#else 120 | - 121 | -#include 122 | - 123 | -namespace boost 124 | -{ 125 | - 126 | -namespace detail 127 | -{ 128 | - 129 | -#if defined( BOOST_NO_STD_TYPEINFO ) 130 | - 131 | -typedef ::type_info sp_typeinfo; 132 | - 133 | -#else 134 | - 135 | -typedef std::type_info sp_typeinfo; 136 | - 137 | -#endif 138 | - 139 | -} // namespace detail 140 | - 141 | -} // namespace boost 142 | - 143 | -#define BOOST_SP_TYPEID(T) typeid(T) 144 | - 145 | -#endif 146 | +#define BOOST_SP_TYPEID(T) (boost::typeind::type_id().type_info()) 147 | 148 | #endif // #ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED 149 | -- 150 | 1.8.5.3 151 | 152 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto !eol svneol=native#text/plain 2 | *.gitattributes text svneol=native#text/plain 3 | 4 | # Scriptish formats 5 | *.bat text svneol=native#text/plain 6 | *.bsh text svneol=native#text/x-beanshell 7 | *.cgi text svneol=native#text/plain 8 | *.cmd text svneol=native#text/plain 9 | *.js text svneol=native#text/javascript 10 | *.php text svneol=native#text/x-php 11 | *.pl text svneol=native#text/x-perl 12 | *.pm text svneol=native#text/x-perl 13 | *.py text svneol=native#text/x-python 14 | *.sh eol=lf svneol=LF#text/x-sh 15 | configure eol=lf svneol=LF#text/x-sh 16 | 17 | # Image formats 18 | *.bmp binary svneol=unset#image/bmp 19 | *.gif binary svneol=unset#image/gif 20 | *.ico binary svneol=unset#image/ico 21 | *.jpeg binary svneol=unset#image/jpeg 22 | *.jpg binary svneol=unset#image/jpeg 23 | *.png binary svneol=unset#image/png 24 | *.tif binary svneol=unset#image/tiff 25 | *.tiff binary svneol=unset#image/tiff 26 | *.svg text svneol=native#image/svg%2Bxml 27 | 28 | # Data formats 29 | *.pdf binary svneol=unset#application/pdf 30 | *.avi binary svneol=unset#video/avi 31 | *.doc binary svneol=unset#application/msword 32 | *.dsp text svneol=crlf#text/plain 33 | *.dsw text svneol=crlf#text/plain 34 | *.eps binary svneol=unset#application/postscript 35 | *.gz binary svneol=unset#application/gzip 36 | *.mov binary svneol=unset#video/quicktime 37 | *.mp3 binary svneol=unset#audio/mpeg 38 | *.ppt binary svneol=unset#application/vnd.ms-powerpoint 39 | *.ps binary svneol=unset#application/postscript 40 | *.psd binary svneol=unset#application/photoshop 41 | *.rdf binary svneol=unset#text/rdf 42 | *.rss text svneol=unset#text/xml 43 | *.rtf binary svneol=unset#text/rtf 44 | *.sln text svneol=native#text/plain 45 | *.swf binary svneol=unset#application/x-shockwave-flash 46 | *.tgz binary svneol=unset#application/gzip 47 | *.vcproj text svneol=native#text/xml 48 | *.vcxproj text svneol=native#text/xml 49 | *.vsprops text svneol=native#text/xml 50 | *.wav binary svneol=unset#audio/wav 51 | *.xls binary svneol=unset#application/vnd.ms-excel 52 | *.zip binary svneol=unset#application/zip 53 | 54 | # Text formats 55 | .htaccess text svneol=native#text/plain 56 | *.bbk text svneol=native#text/xml 57 | *.cmake text svneol=native#text/plain 58 | *.css text svneol=native#text/css 59 | *.dtd text svneol=native#text/xml 60 | *.htm text svneol=native#text/html 61 | *.html text svneol=native#text/html 62 | *.ini text svneol=native#text/plain 63 | *.log text svneol=native#text/plain 64 | *.mak text svneol=native#text/plain 65 | *.qbk text svneol=native#text/plain 66 | *.rst text svneol=native#text/plain 67 | *.sql text svneol=native#text/x-sql 68 | *.txt text svneol=native#text/plain 69 | *.xhtml text svneol=native#text/xhtml%2Bxml 70 | *.xml text svneol=native#text/xml 71 | *.xsd text svneol=native#text/xml 72 | *.xsl text svneol=native#text/xml 73 | *.xslt text svneol=native#text/xml 74 | *.xul text svneol=native#text/xul 75 | *.yml text svneol=native#text/plain 76 | boost-no-inspect text svneol=native#text/plain 77 | CHANGES text svneol=native#text/plain 78 | COPYING text svneol=native#text/plain 79 | INSTALL text svneol=native#text/plain 80 | Jamfile text svneol=native#text/plain 81 | Jamroot text svneol=native#text/plain 82 | Jamfile.v2 text svneol=native#text/plain 83 | Jamrules text svneol=native#text/plain 84 | Makefile* text svneol=native#text/plain 85 | README text svneol=native#text/plain 86 | TODO text svneol=native#text/plain 87 | 88 | # Code formats 89 | *.c text svneol=native#text/plain 90 | *.cpp text svneol=native#text/plain 91 | *.h text svneol=native#text/plain 92 | *.hpp text svneol=native#text/plain 93 | *.ipp text svneol=native#text/plain 94 | *.tpp text svneol=native#text/plain 95 | *.jam text svneol=native#text/plain 96 | *.java text svneol=native#text/plain 97 | -------------------------------------------------------------------------------- /test/Jamfile.v2: -------------------------------------------------------------------------------- 1 | # Copyright 2012-2025 Antony Polukhin 2 | # 3 | # Distributed under the Boost Software License, Version 1.0. (See accompanying 4 | # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | # 6 | 7 | require-b2 5.0.1 ; 8 | import-search /boost/config/checks ; 9 | import-search /boost/config/checks ; 10 | import config : requires ; 11 | import testing ; 12 | import feature ; 13 | import os ; 14 | 15 | project 16 | : source-location . 17 | : requirements 18 | /boost/type_index//boost_type_index 19 | [ requires cxx11_rvalue_references ] 20 | ; 21 | 22 | # Variable that contains all the stuff required for linking together on and off 23 | compat = BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY ; 24 | 25 | # Making own `nortti` that is link compatible. 26 | # We explicitly define BOOST_NO_RTTI because it sometimes can not be detected by build system. 27 | nortti = gcc:"-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID" clang:"-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID" intel:"-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID" darwin:"-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID" msvc:"/GR-" ; 28 | 29 | norttidefines = gcc:"-DBOOST_NO_RTTI -DBOOST_NO_TYPEID" clang:"-DBOOST_NO_RTTI -DBOOST_NO_TYPEID" intel:"-DBOOST_NO_RTTI -DBOOST_NO_TYPEID" darwin:"-DBOOST_NO_RTTI -DBOOST_NO_TYPEID" msvc:"-DBOOST_NO_RTTI" ; 30 | 31 | 32 | # Making libraries that CANNOT work between rtti-on/rtti-off modules 33 | obj test_lib_nortti-obj : test_lib.cpp : shared off $(norttidefines) ; 34 | obj test_lib_anonymous_nortti-obj : test_lib_anonymous.cpp : shared off $(norttidefines) ; 35 | lib test_lib_nortti : test_lib_nortti-obj : shared off $(norttidefines) ; 36 | lib test_lib_anonymous_nortti : test_lib_anonymous_nortti-obj : shared off $(norttidefines) ; 37 | 38 | obj test_lib_rtti-obj : test_lib.cpp : shared ; 39 | obj test_lib_anonymous_rtti-obj : test_lib_anonymous.cpp : shared ; 40 | lib test_lib_rtti : test_lib_rtti-obj : shared ; 41 | lib test_lib_anonymous_rtti : test_lib_anonymous_rtti-obj : shared ; 42 | 43 | # Making libraries that can work between rtti-on/rtti-off modules 44 | obj test_lib_nortti_compat-obj : test_lib.cpp : shared $(nortti) $(compat) ; 45 | obj test_lib_rtti_compat-obj : test_lib.cpp : shared $(nortti) $(compat) ; 46 | lib test_lib_nortti_compat : test_lib_nortti_compat-obj : shared $(nortti) $(compat) ; 47 | lib test_lib_rtti_compat : test_lib_rtti_compat-obj : shared $(nortti) $(compat) ; 48 | 49 | exe testing_crossmodule_anonymous_no_rtti : testing_crossmodule_anonymous.cpp test_lib_anonymous_nortti : off $(norttidefines) ; 50 | 51 | test-suite type_index 52 | : 53 | [ run type_index_test.cpp ] 54 | [ run type_index_runtime_cast_test.cpp /boost/smart_ptr//boost_smart_ptr ] 55 | [ run type_index_constexpr_test.cpp ] 56 | [ run type_index_test.cpp : : : off $(norttidefines) : type_index_test_no_rtti ] 57 | [ run ctti_print_name.cpp : : : always_show_run_output ] 58 | [ run testing_crossmodule.cpp test_lib_rtti ] 59 | [ run testing_crossmodule.cpp test_lib_nortti : : : off $(norttidefines) : testing_crossmodule_no_rtti ] 60 | [ run testing_crossmodule_anonymous.cpp test_lib_anonymous_rtti : : : always_show_run_output ] 61 | [ run compare_ctti_stl.cpp ] 62 | [ run track_13621.cpp ] 63 | 64 | [ compile-fail type_index_test_ctti_copy_fail.cpp ] 65 | [ compile-fail type_index_test_ctti_construct_fail.cpp ] 66 | [ compile type_index_test_ctti_alignment.cpp ] 67 | 68 | # Mixing RTTI on and off 69 | 70 | # MSVC sometimes overrides the /GR-, without `detect_missmatch` this test may link. 71 | # TODO: Disabled on MSVC. Enable again when there'll be an understanding of how to write this test correctly for MSVC. 72 | [ link-fail testing_crossmodule.cpp test_lib_rtti : $(nortti) msvc:no : link_fail_nortti_rtti ] 73 | [ link-fail testing_crossmodule.cpp test_lib_nortti : msvc:no : link_fail_rtti_nortti ] 74 | 75 | [ run testing_crossmodule.cpp test_lib_rtti_compat : : : $(nortti) $(compat) : testing_crossmodule_nortti_rtti_compat ] 76 | [ run testing_crossmodule.cpp test_lib_nortti_compat : : : $(compat) : testing_crossmodule_rtti_nortti_compat ] 77 | ; 78 | 79 | # Assuring that examples compile and run. Adding sources from `examples` directory to the `type_index` test suite. 80 | for local p in [ glob ../examples/*.cpp ] 81 | { 82 | # RTTI on 83 | type_index += [ run $(p) /boost/unordered//boost_unordered : : : ../examples ] ; 84 | 85 | # RTTI off 86 | local target_name = $(p[1]:B)_no_rtti ; 87 | if $(target_name) != "table_of_names_no_rtti" 88 | { 89 | type_index += [ run $(p) /boost/unordered//boost_unordered : : : ../examples off $(norttidefines) : $(target_name) ] ; 90 | } 91 | } 92 | 93 | -------------------------------------------------------------------------------- /test/type_index_constexpr_test.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2015-2025 Antony Polukhin. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See 5 | // accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | const char* hello1 = "Hello word"; 16 | const char* hello1_end = hello1 + sizeof("Hello word"); 17 | const char* hello2 = "Hello word, pal!"; 18 | const char* hello2_end = hello2 + sizeof("Hello word, pal!"); 19 | 20 | void strcmp_same() { 21 | using boost::typeindex::detail::constexpr_strcmp; 22 | 23 | BOOST_TEST( 24 | constexpr_strcmp(hello1, hello1) == 0 25 | ); 26 | 27 | BOOST_TEST( 28 | constexpr_strcmp(hello2, hello2) == 0 29 | ); 30 | 31 | BOOST_TEST( 32 | constexpr_strcmp(hello1, hello2) != 0 33 | ); 34 | 35 | BOOST_TEST( 36 | constexpr_strcmp(hello2, hello1) != 0 37 | ); 38 | 39 | BOOST_TEST( 40 | (constexpr_strcmp(hello2, hello1) < 0) 41 | == 42 | (std::strcmp(hello2, hello1) < 0) 43 | ); 44 | 45 | BOOST_TEST( 46 | (constexpr_strcmp(hello1, hello2) < 0) 47 | == 48 | (std::strcmp(hello1, hello2) < 0) 49 | ); 50 | } 51 | 52 | void search_same() { 53 | using boost::typeindex::detail::constexpr_search; 54 | BOOST_TEST( 55 | constexpr_search(hello1, hello1_end, hello2, hello2_end) == std::search(hello1, hello1_end, hello2, hello2_end) 56 | ); 57 | 58 | BOOST_TEST( 59 | constexpr_search(hello2, hello2_end, hello1, hello1_end) == std::search(hello2, hello2_end, hello1, hello1_end) 60 | ); 61 | 62 | const char* word = "word"; 63 | const char* word_end = word + sizeof("word") - 1; 64 | BOOST_TEST( 65 | constexpr_search(hello1, hello1_end, word, word_end) == std::search(hello1, hello1_end, word, word_end) 66 | ); 67 | 68 | BOOST_TEST( 69 | constexpr_search(hello2, hello2_end, word, word_end) == std::search(hello2, hello2_end, word, word_end) 70 | ); 71 | } 72 | 73 | template 74 | BOOST_CXX14_CONSTEXPR bool in_namespace(const char (&ns)[N]) BOOST_NOEXCEPT { 75 | BOOST_CXX14_CONSTEXPR const char* name = boost::typeindex::ctti_type_index::type_id().raw_name(); 76 | for (std::size_t i = 0; i < N - 1; ++i) 77 | if (name[i] != ns[i]) 78 | return false; 79 | 80 | return true; 81 | } 82 | 83 | template 84 | BOOST_CXX14_CONSTEXPR bool is_boost_namespace() BOOST_NOEXCEPT { 85 | return in_namespace("boost::") || in_namespace("class boost::") || in_namespace("struct boost::"); 86 | } 87 | 88 | void constexpr_test() { 89 | using namespace boost::typeindex; 90 | 91 | BOOST_CXX14_CONSTEXPR ctti_type_index t_int0 = ctti_type_index::type_id(); 92 | (void)t_int0; 93 | 94 | BOOST_CXX14_CONSTEXPR ctti_type_index t_short0 = ctti_type_index::type_id(); 95 | (void)t_short0; 96 | 97 | BOOST_CXX14_CONSTEXPR ctti_type_index t_int1 = ctti_type_index::type_id(); 98 | (void)t_int1; 99 | 100 | BOOST_CXX14_CONSTEXPR ctti_type_index t_short1 = ctti_type_index::type_id(); 101 | (void)t_short1; 102 | 103 | // Following tests are known to fail on _MSC_VER == 1916. 104 | #if !defined(_MSC_VER) || _MSC_VER > 1916 105 | 106 | BOOST_CXX14_CONSTEXPR bool same0 = (t_int0 == t_int1); 107 | BOOST_TEST(same0); 108 | 109 | BOOST_CXX14_CONSTEXPR bool same1 = (t_short1 == t_short0); 110 | BOOST_TEST(same1); 111 | 112 | BOOST_CXX14_CONSTEXPR bool same2 = (t_int1 == t_int1); 113 | BOOST_TEST(same2); 114 | 115 | BOOST_CXX14_CONSTEXPR bool same3 = (t_short0 == t_short0); 116 | BOOST_TEST(same3); 117 | 118 | BOOST_CXX14_CONSTEXPR bool same4 = !(t_short0 < t_short0 || t_short0 > t_short0); 119 | BOOST_TEST(same4); 120 | 121 | BOOST_CXX14_CONSTEXPR bool same5 = (t_short0 <= t_short0 && t_short0 >= t_short0); 122 | BOOST_TEST(same5); 123 | 124 | 125 | BOOST_CXX14_CONSTEXPR bool not_same0 = (t_int0 != t_short1); 126 | BOOST_TEST(not_same0); 127 | 128 | BOOST_CXX14_CONSTEXPR bool not_same1 = (t_int1 != t_short0); 129 | BOOST_TEST(not_same1); 130 | 131 | BOOST_CXX14_CONSTEXPR bool not_same2 = (t_int1 < t_short0 || t_int1 > t_short0); 132 | BOOST_TEST(not_same2); 133 | 134 | 135 | BOOST_CXX14_CONSTEXPR const char* int_name = t_int0.name(); 136 | BOOST_TEST(*int_name != '\0'); 137 | 138 | BOOST_CXX14_CONSTEXPR const char* short_name = t_short0.name(); 139 | BOOST_TEST(*short_name != '\0'); 140 | 141 | BOOST_CXX14_CONSTEXPR bool in_namespace = is_boost_namespace(); 142 | BOOST_TEST(in_namespace); 143 | 144 | BOOST_CXX14_CONSTEXPR bool not_in_namespace = !is_boost_namespace(); 145 | BOOST_TEST(not_in_namespace); 146 | 147 | #endif // #if !defined(_MSC_VER) || _MSC_VER > 1916 148 | } 149 | 150 | 151 | int main() { 152 | strcmp_same(); 153 | search_same(); 154 | constexpr_test(); 155 | return boost::report_errors(); 156 | } 157 | 158 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016-2025 Antony Polukhin 2 | # Distributed under the Boost Software License, Version 1.0. 3 | # See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt 4 | 5 | include(BoostTest OPTIONAL RESULT_VARIABLE HAVE_BOOST_TEST) 6 | 7 | if(NOT HAVE_BOOST_TEST) 8 | return() 9 | endif() 10 | 11 | if(MSVC) 12 | set(BOOST_TYPEINDEX_DETAIL_NO_RTTI "/GR-") 13 | set(BOOST_TYPEINDEX_DETAIL_RTTI "/GR") 14 | else() 15 | set(BOOST_TYPEINDEX_DETAIL_NO_RTTI "-fno-rtti") 16 | set(BOOST_TYPEINDEX_DETAIL_RTTI "-frtti") 17 | endif() 18 | 19 | # Making libraries that CANNOT work between rtti-on/rtti-off modules 20 | add_library(boost_type_index_test_lib_nortti SHARED test_lib.cpp) 21 | target_compile_options(boost_type_index_test_lib_nortti PRIVATE ${BOOST_TYPEINDEX_DETAIL_NO_RTTI}) 22 | target_link_libraries(boost_type_index_test_lib_nortti PRIVATE Boost::type_index) 23 | 24 | add_library(boost_type_index_test_lib_anonymous_nortti SHARED test_lib_anonymous.cpp) 25 | target_compile_options(boost_type_index_test_lib_anonymous_nortti PRIVATE ${BOOST_TYPEINDEX_DETAIL_NO_RTTI}) 26 | target_link_libraries(boost_type_index_test_lib_anonymous_nortti PRIVATE Boost::type_index) 27 | 28 | add_library(boost_type_index_test_lib_rtti SHARED test_lib.cpp) 29 | target_compile_options(boost_type_index_test_lib_rtti PRIVATE ${BOOST_TYPEINDEX_DETAIL_RTTI}) 30 | target_link_libraries(boost_type_index_test_lib_rtti PRIVATE Boost::type_index) 31 | 32 | add_library(boost_type_index_test_lib_anonymous_rtti SHARED test_lib_anonymous.cpp) 33 | target_compile_options(boost_type_index_test_lib_anonymous_rtti PRIVATE ${BOOST_TYPEINDEX_DETAIL_RTTI}) 34 | target_link_libraries(boost_type_index_test_lib_anonymous_rtti PRIVATE Boost::type_index) 35 | 36 | # Making libraries that can work between rtti-on/rtti-off modules 37 | add_library(boost_type_index_test_lib_nortti_compat SHARED test_lib.cpp) 38 | target_compile_options(boost_type_index_test_lib_nortti_compat PRIVATE ${BOOST_TYPEINDEX_DETAIL_NO_RTTI}) 39 | target_compile_definitions(boost_type_index_test_lib_nortti_compat PUBLIC BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY=1) 40 | target_link_libraries(boost_type_index_test_lib_nortti_compat PRIVATE Boost::type_index) 41 | 42 | add_library(boost_type_index_test_lib_rtti_compat SHARED test_lib.cpp) 43 | target_compile_options(boost_type_index_test_lib_rtti_compat PRIVATE ${BOOST_TYPEINDEX_DETAIL_RTTI}) 44 | target_compile_definitions(boost_type_index_test_lib_rtti_compat PUBLIC BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY=1) 45 | target_link_libraries(boost_type_index_test_lib_rtti_compat PRIVATE Boost::type_index) 46 | 47 | set(BOOST_TEST_LINK_LIBRARIES Boost::type_index Boost::core) 48 | 49 | boost_test(TYPE run SOURCES type_index_test.cpp) 50 | boost_test(TYPE run SOURCES type_index_runtime_cast_test.cpp LINK_LIBRARIES Boost::smart_ptr) 51 | boost_test(TYPE run SOURCES type_index_constexpr_test.cpp) 52 | boost_test(TYPE run SOURCES type_index_test.cpp COMPILE_OPTIONS ${BOOST_TYPEINDEX_DETAIL_NO_RTTI} NAME type_index_test_no_rtti) 53 | boost_test(TYPE run SOURCES ctti_print_name.cpp) 54 | 55 | boost_test(TYPE run SOURCES testing_crossmodule.cpp 56 | LINK_LIBRARIES boost_type_index_test_lib_rtti 57 | ) 58 | boost_test(TYPE run SOURCES testing_crossmodule.cpp 59 | LINK_LIBRARIES boost_type_index_test_lib_nortti 60 | COMPILE_OPTIONS ${BOOST_TYPEINDEX_DETAIL_NO_RTTI} 61 | NAME testing_crossmodule_no_rtti 62 | ) 63 | boost_test(TYPE run SOURCES testing_crossmodule_anonymous.cpp 64 | LINK_LIBRARIES boost_type_index_test_lib_anonymous_rtti 65 | ) 66 | 67 | boost_test(TYPE run SOURCES compare_ctti_stl.cpp) 68 | boost_test(TYPE run SOURCES track_13621.cpp) 69 | 70 | boost_test(TYPE compile-fail SOURCES type_index_test_ctti_copy_fail.cpp) 71 | boost_test(TYPE compile-fail SOURCES type_index_test_ctti_construct_fail.cpp) 72 | boost_test(TYPE compile SOURCES type_index_test_ctti_alignment.cpp) 73 | 74 | # Mixing RTTI on and off 75 | if(NOT MSVC) # MSVC sometimes overrides the /GR- and the tests link 76 | boost_test(TYPE link-fail SOURCES testing_crossmodule.cpp 77 | LINK_LIBRARIES boost_type_index_test_lib_rtti 78 | COMPILE_OPTIONS ${BOOST_TYPEINDEX_DETAIL_NO_RTTI} 79 | NAME link_fail_nortti_rtti) 80 | boost_test(TYPE link-fail SOURCES testing_crossmodule.cpp 81 | LINK_LIBRARIES boost_type_index_test_lib_nortti 82 | NAME link_fail_rtti_nortti) 83 | 84 | boost_test(TYPE run SOURCES testing_crossmodule.cpp 85 | LINK_LIBRARIES boost_type_index_test_lib_rtti_compat 86 | COMPILE_OPTIONS ${BOOST_TYPEINDEX_DETAIL_NO_RTTI} 87 | COMPILE_DEFINITIONS BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY=1 88 | NAME testing_crossmodule_nortti_rtti_compat 89 | ) 90 | boost_test(TYPE run SOURCES testing_crossmodule.cpp 91 | LINK_LIBRARIES boost_type_index_test_lib_nortti_compat 92 | COMPILE_DEFINITIONS BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY=1 93 | NAME testing_crossmodule_rtti_nortti_compat 94 | ) 95 | endif() 96 | 97 | file(GLOB EXAMPLE_FILES "../examples/*.cpp") 98 | foreach (testsourcefile ${EXAMPLE_FILES}) 99 | boost_test(TYPE run SOURCES ${testsourcefile} INCLUDE_DIRECTORIES ../examples LINK_LIBRARIES Boost::unordered) 100 | 101 | get_filename_component(testname ${testsourcefile} NAME_WE) 102 | if(NOT testname STREQUAL "table_of_names") 103 | boost_test(TYPE run SOURCES ${testsourcefile} NAME ${testname}_no_rtti COMPILE_OPTIONS ${BOOST_TYPEINDEX_DETAIL_NO_RTTI} INCLUDE_DIRECTORIES ../examples LINK_LIBRARIES Boost::unordered) 104 | endif() 105 | endforeach() 106 | -------------------------------------------------------------------------------- /patched/boost_exception.patch: -------------------------------------------------------------------------------- 1 | From 8f57d59bfbc978673a2493a90b4f3e7e54ddbf18 Mon Sep 17 00:00:00 2001 2 | From: Antony Polukhin 3 | Date: Thu, 20 Feb 2014 18:30:11 +0400 4 | Subject: [PATCH] Boost.Exception now uses TypeIndex to reduce duplicate code 5 | and simplify name demanglings 6 | 7 | --- 8 | include/boost/exception/detail/type_info.hpp | 43 +++------------------- 9 | include/boost/exception/diagnostic_information.hpp | 2 +- 10 | include/boost/exception/exception.hpp | 3 +- 11 | include/boost/exception/info.hpp | 2 +- 12 | test/Jamfile.v2 | 2 + 13 | 5 files changed, 12 insertions(+), 40 deletions(-) 14 | 15 | diff --git a/include/boost/exception/detail/type_info.hpp b/include/boost/exception/detail/type_info.hpp 16 | index 6e5942d..a247b71 100644 17 | --- a/include/boost/exception/detail/type_info.hpp 18 | +++ b/include/boost/exception/detail/type_info.hpp 19 | @@ -12,13 +12,7 @@ 20 | #pragma warning(push,1) 21 | #endif 22 | 23 | -#include 24 | -#include 25 | -#include 26 | -//#ifndef BOOST_NO_TYPEID 27 | -//#include 28 | -//#endif 29 | -#include 30 | +#include 31 | 32 | namespace 33 | boost 34 | @@ -28,11 +22,7 @@ boost 35 | std::string 36 | tag_type_name() 37 | { 38 | -#ifdef BOOST_NO_TYPEID 39 | - return BOOST_CURRENT_FUNCTION; 40 | -#else 41 | - return /*units::detail::demangle*/(typeid(T*).name()); 42 | -#endif 43 | + return boost::typeind::type_id().pretty_name(); 44 | } 45 | 46 | template 47 | @@ -40,41 +30,20 @@ boost 48 | std::string 49 | type_name() 50 | { 51 | -#ifdef BOOST_NO_TYPEID 52 | - return BOOST_CURRENT_FUNCTION; 53 | -#else 54 | - return /*units::detail::demangle*/(typeid(T).name()); 55 | -#endif 56 | + return boost::typeind::type_id().pretty_name(); 57 | } 58 | 59 | namespace 60 | exception_detail 61 | { 62 | - struct 63 | - type_info_ 64 | - { 65 | - detail::sp_typeinfo const * type_; 66 | - 67 | - explicit 68 | - type_info_( detail::sp_typeinfo const & type ): 69 | - type_(&type) 70 | - { 71 | - } 72 | - 73 | - friend 74 | - bool 75 | - operator<( type_info_ const & a, type_info_ const & b ) 76 | - { 77 | - return 0!=(a.type_->before(*b.type_)); 78 | - } 79 | - }; 80 | + typedef boost::typeind::type_index type_info_; 81 | } 82 | } 83 | 84 | -#define BOOST_EXCEPTION_STATIC_TYPEID(T) ::boost::exception_detail::type_info_(BOOST_SP_TYPEID(T)) 85 | +#define BOOST_EXCEPTION_STATIC_TYPEID(T) ::boost::typeind::type_id() 86 | 87 | #ifndef BOOST_NO_RTTI 88 | -#define BOOST_EXCEPTION_DYNAMIC_TYPEID(x) ::boost::exception_detail::type_info_(typeid(x)) 89 | +#define BOOST_EXCEPTION_DYNAMIC_TYPEID(x) ::boost::typeind::type_id_runtime(x) 90 | #endif 91 | 92 | #if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) 93 | diff --git a/include/boost/exception/diagnostic_information.hpp b/include/boost/exception/diagnostic_information.hpp 94 | index 2f5cb88..0f8b5e8 100644 95 | --- a/include/boost/exception/diagnostic_information.hpp 96 | +++ b/include/boost/exception/diagnostic_information.hpp 97 | @@ -151,7 +151,7 @@ boost 98 | #ifndef BOOST_NO_RTTI 99 | if ( verbose ) 100 | tmp << std::string("Dynamic exception type: ") << 101 | - /*units::detail::demangle*/((be?(BOOST_EXCEPTION_DYNAMIC_TYPEID(*be)):(BOOST_EXCEPTION_DYNAMIC_TYPEID(*se))).type_->name()) << '\n'; 102 | + /*units::detail::demangle*/((be?(BOOST_EXCEPTION_DYNAMIC_TYPEID(*be)):(BOOST_EXCEPTION_DYNAMIC_TYPEID(*se)))) << '\n'; 103 | #endif 104 | if( with_what && se && verbose ) 105 | tmp << "std::exception::what: " << wh << '\n'; 106 | diff --git a/include/boost/exception/exception.hpp b/include/boost/exception/exception.hpp 107 | index 9f20a04..53c341f 100644 108 | --- a/include/boost/exception/exception.hpp 109 | +++ b/include/boost/exception/exception.hpp 110 | @@ -12,6 +12,8 @@ 111 | #pragma warning(push,1) 112 | #endif 113 | 114 | +#include 115 | + 116 | namespace 117 | boost 118 | { 119 | @@ -151,7 +153,6 @@ boost 120 | exception_detail 121 | { 122 | class error_info_base; 123 | - struct type_info_; 124 | 125 | struct 126 | error_info_container 127 | diff --git a/include/boost/exception/info.hpp b/include/boost/exception/info.hpp 128 | index edbf058..e0f4950 100644 129 | --- a/include/boost/exception/info.hpp 130 | +++ b/include/boost/exception/info.hpp 131 | @@ -96,7 +96,7 @@ boost 132 | { 133 | shared_ptr const & p = i->second; 134 | #ifndef BOOST_NO_RTTI 135 | - BOOST_ASSERT( *BOOST_EXCEPTION_DYNAMIC_TYPEID(*p).type_==*ti.type_ ); 136 | + BOOST_ASSERT(BOOST_EXCEPTION_DYNAMIC_TYPEID(*p)==ti ); 137 | #endif 138 | return p; 139 | } 140 | diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 141 | index d2dfcd6..5bd076d 100644 142 | --- a/test/Jamfile.v2 143 | +++ b/test/Jamfile.v2 144 | @@ -35,7 +35,9 @@ run enable_error_info_test.cpp helper1.cpp ; 145 | run throw_exception_test.cpp helper2.cpp ; 146 | run errno_test.cpp ; 147 | run error_info_test.cpp ; 148 | +run error_info_test.cpp : : : off : error_info_test_rtti ; 149 | run diagnostic_information_test.cpp ; 150 | +run diagnostic_information_test.cpp : : : off : diagnostic_information_test_rtti ; 151 | run refcount_ptr_test.cpp ; 152 | run current_exception_cast_test.cpp ; 153 | run no_exceptions_test.cpp : : : off ; 154 | -- 155 | 1.8.5.3 156 | 157 | -------------------------------------------------------------------------------- /include/boost/type_index/runtime_cast/register_runtime_class.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Chris Glover, 2016. 3 | // 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_TYPE_INDEX_RUNTIME_CAST_REGISTER_RUNTIME_CLASS_HPP 10 | #define BOOST_TYPE_INDEX_RUNTIME_CAST_REGISTER_RUNTIME_CLASS_HPP 11 | 12 | /// \file register_runtime_class.hpp 13 | /// \brief Contains the macros BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST and 14 | /// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS 15 | 16 | #include 17 | 18 | #include 19 | 20 | #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 21 | 22 | #ifdef BOOST_HAS_PRAGMA_ONCE 23 | # pragma once 24 | #endif 25 | 26 | namespace boost { namespace typeindex { namespace detail { 27 | 28 | BOOST_TYPE_INDEX_BEGIN_MODULE_EXPORT 29 | 30 | template 31 | inline type_index runtime_class_construct_type_id(T const*) { 32 | return boost::typeindex::type_id(); 33 | } 34 | 35 | template 36 | constexpr const void* find_instance(boost::typeindex::type_index const&, const Self*) noexcept { 37 | return nullptr; 38 | } 39 | 40 | template 41 | const void* find_instance(boost::typeindex::type_index const& idx, const Self* self) noexcept { 42 | if (const void* ptr = self->Base::boost_type_index_find_instance_(idx)) { 43 | return ptr; 44 | } 45 | 46 | return boost::typeindex::detail::find_instance(idx, self); 47 | } 48 | 49 | BOOST_TYPE_INDEX_END_MODULE_EXPORT 50 | 51 | }}} // namespace boost::typeindex::detail 52 | 53 | #endif // #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 54 | 55 | 56 | /// \def BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS 57 | /// \brief Macro used to make a class compatible with boost::typeindex::runtime_cast 58 | /// 59 | /// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS generates a virtual function 60 | /// in the current class that, when combined with the supplied base class information, allows 61 | /// boost::typeindex::runtime_cast to accurately convert between dynamic types of instances of 62 | /// the current class. 63 | /// 64 | /// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS also adds support for boost::typeindex::type_id_runtime 65 | /// by including BOOST_TYPE_INDEX_REGISTER_CLASS. It is typical that these features are used together, 66 | /// but in the event that BOOST_TYPE_INDEX_REGISTER_CLASS is undesirable in the current class, 67 | /// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST is provided. 68 | /// 69 | /// \b Example: 70 | /// \code 71 | /// struct base1 { 72 | /// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS() 73 | /// virtual ~base1(); 74 | /// }; 75 | /// 76 | /// struct base2 { 77 | /// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS() 78 | /// virtual ~base2(); 79 | /// }; 80 | /// 81 | /// struct derived1 : base1 { 82 | /// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(base1) 83 | /// }; 84 | /// 85 | /// struct derived2 : base1, base2 { 86 | /// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(base1, base2) 87 | /// }; 88 | /// 89 | /// ... 90 | /// 91 | /// base1* pb1 = get_object(); 92 | /// if(derived2* pb2 = boost::typeindex::runtime_cast(pb1)) { 93 | /// assert(boost::typeindex::type_id_runtime(*pb1)) == boost::typeindex::type_id()); 94 | /// } 95 | /// \endcode 96 | /// 97 | /// \param base_class_seq A Boost.Preprocessor sequence of the current class' direct bases, or 98 | /// BOOST_TYPE_INDEX_NO_BASE_CLASS if this class has no direct base classes. 99 | #define BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(...) \ 100 | BOOST_TYPE_INDEX_REGISTER_CLASS \ 101 | BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(__VA_ARGS__) 102 | 103 | /// \def BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST 104 | /// \brief Macro used to make a class compatible with boost::typeindex::runtime_cast without including 105 | /// support for boost::typeindex::type_id_runtime. 106 | /// 107 | /// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST is provided as an alternative to BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS 108 | /// in the event that support for boost::typeindex::type_id_runtime is undesirable. 109 | /// 110 | /// \b Example: 111 | /// \code 112 | /// struct base1 { 113 | /// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST() 114 | /// virtual ~base1(); 115 | /// }; 116 | /// 117 | /// struct base2 { 118 | /// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST() 119 | /// virtual ~base2(); 120 | /// }; 121 | /// 122 | /// struct derived1 : base1 { 123 | /// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(base1) 124 | /// }; 125 | /// 126 | /// struct derived2 : base1, base2 { 127 | /// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(base1, base2) 128 | /// }; 129 | /// 130 | /// ... 131 | /// 132 | /// base1* pb1 = get_object(); 133 | /// if(derived2* pb2 = boost::typeindex::runtime_cast(pb1)) 134 | /// { /* can't call boost::typeindex::type_id_runtime(*pb1) here */ } 135 | /// \endcode 136 | /// 137 | /// \param base_class_seq A Boost.Preprocessor sequence of the current class' direct bases, or 138 | /// BOOST_TYPE_INDEX_NO_BASE_CLASS if this class has no direct base classes. 139 | #define BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(...) \ 140 | virtual void const* boost_type_index_find_instance_(boost::typeindex::type_index const& idx) const noexcept { \ 141 | if(idx == boost::typeindex::detail::runtime_class_construct_type_id(this)) \ 142 | return this; \ 143 | return boost::typeindex::detail::find_instance<__VA_ARGS__>(idx, this); \ 144 | } 145 | 146 | /// \def BOOST_TYPE_INDEX_NO_BASE_CLASS 147 | /// \brief Instructs BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS and BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST 148 | /// that this class has no base classes. 149 | /// \deprecated Just remove and use BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS() or BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST() 150 | #define BOOST_TYPE_INDEX_NO_BASE_CLASS /**/ 151 | 152 | #endif // BOOST_TYPE_INDEX_RUNTIME_CAST_REGISTER_RUNTIME_CLASS_HPP 153 | -------------------------------------------------------------------------------- /examples/user_defined_typeinfo.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2013-2025 Antony Polukhin 2 | 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See the accompanying file LICENSE_1_0.txt 5 | // or a copy at .) 6 | 7 | #ifndef USER_DEFINED_TYPEINFO_HPP 8 | #define USER_DEFINED_TYPEINFO_HPP 9 | 10 | //[type_index_userdefined_usertypes 11 | /*` 12 | The following example shows how a user defined type_info can be created and used. 13 | Example works with and without RTTI. 14 | 15 | Consider situation when user uses only those types in `typeid()`: 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | namespace my_namespace { 22 | 23 | class my_class; 24 | struct my_struct; 25 | 26 | using my_classes = std::vector; 27 | using my_string = std::string; 28 | 29 | } // namespace my_namespace 30 | 31 | //] [/type_index_userdefined_usertypes] 32 | 33 | 34 | //[type_index_userdefined_enum 35 | /*` 36 | In that case user may wish to save space in binary and create it's own type system. 37 | For that case `detail::typenum<>` meta function is added. Depending on the input type T 38 | this function will return different numeric values. 39 | */ 40 | #include 41 | 42 | namespace my_namespace { namespace detail { 43 | template struct typenum; 44 | template <> struct typenum{ enum {value = 0}; }; 45 | template <> struct typenum{ enum {value = 1}; }; 46 | template <> struct typenum{ enum {value = 2}; }; 47 | template <> struct typenum{ enum {value = 3}; }; 48 | template <> struct typenum{ enum {value = 4}; }; 49 | 50 | #ifdef BOOST_MSVC 51 | #pragma warning(push) 52 | #pragma warning(disable: 4510 4512 4610) // non-copyable non-constructable type 53 | #endif 54 | 55 | // my_typeinfo structure is used to save type number 56 | struct my_typeinfo { 57 | const char* const type_; 58 | }; 59 | 60 | #ifdef BOOST_MSVC 61 | #pragma warning(pop) 62 | #endif 63 | 64 | const my_typeinfo infos[5] = { 65 | {"void"}, {"my_class"}, {"my_struct"}, {"my_classes"}, {"my_string"} 66 | }; 67 | 68 | template 69 | inline const my_typeinfo& my_typeinfo_construct() { 70 | return infos[typenum::value]; 71 | } 72 | }} // my_namespace::detail 73 | 74 | //] [/type_index_userdefined_usertypes] 75 | 76 | 77 | //[type_index_my_type_index 78 | /*` 79 | `my_type_index` is a user created type_index class. If in doubt during this phase, you can always 80 | take a look at the `` or `` 81 | files. Documentation for `type_index_facade` could be also useful. 82 | */ 83 | 84 | /*` 85 | Since we are not going to override `type_index_facade::hash_code()` we must additionally include 86 | ``. 87 | */ 88 | #include 89 | 90 | /*` 91 | See implementation of `my_type_index`: 92 | */ 93 | namespace my_namespace { 94 | 95 | class my_type_index: public boost::typeindex::type_index_facade { 96 | const detail::my_typeinfo* data_; 97 | 98 | public: 99 | using type_info_t = detail::my_typeinfo; 100 | 101 | inline my_type_index() noexcept 102 | : data_(&detail::my_typeinfo_construct()) 103 | {} 104 | 105 | inline my_type_index(const type_info_t& data) noexcept 106 | : data_(&data) 107 | {} 108 | 109 | inline const type_info_t& type_info() const noexcept { 110 | return *data_; 111 | } 112 | 113 | inline const char* raw_name() const noexcept { 114 | return data_->type_; 115 | } 116 | 117 | inline std::string pretty_name() const { 118 | return data_->type_; 119 | } 120 | 121 | template 122 | inline static my_type_index type_id() noexcept { 123 | return detail::my_typeinfo_construct(); 124 | } 125 | 126 | template 127 | inline static my_type_index type_id_with_cvr() noexcept { 128 | return detail::my_typeinfo_construct(); 129 | } 130 | 131 | template 132 | inline static my_type_index type_id_runtime(const T& variable) noexcept; 133 | }; 134 | 135 | } // namespace my_namespace 136 | 137 | /*` 138 | Note that we have used the boost::typeindex::type_index_facade class as base. 139 | That class took care about all the helper function and operators (comparison, hashing, ostreaming and others). 140 | */ 141 | 142 | //] [/type_index_my_type_index] 143 | 144 | //[type_index_my_type_index_register_class 145 | /*` 146 | Usually to allow runtime type info we need to register class with some macro. 147 | Let's see how a `MY_TYPEINDEX_REGISTER_CLASS` macro could be implemented for our `my_type_index` class: 148 | */ 149 | namespace my_namespace { namespace detail { 150 | 151 | template 152 | inline const my_typeinfo& my_typeinfo_construct_ref(const T*) { 153 | return my_typeinfo_construct(); 154 | } 155 | 156 | #define MY_TYPEINDEX_REGISTER_CLASS \ 157 | virtual const my_namespace::detail::my_typeinfo& type_id_runtime() const { \ 158 | return my_namespace::detail::my_typeinfo_construct_ref(this); \ 159 | } 160 | 161 | }} // namespace my_namespace::detail 162 | 163 | //] [/type_index_my_type_index_register_class] 164 | 165 | //[type_index_my_type_index_type_id_runtime_implmentation 166 | /*` 167 | Now when we have a MY_TYPEINDEX_REGISTER_CLASS, let's implement a `my_type_index::type_id_runtime` method: 168 | */ 169 | namespace my_namespace { 170 | template 171 | my_type_index my_type_index::type_id_runtime(const T& variable) noexcept { 172 | // Classes that were marked with `MY_TYPEINDEX_REGISTER_CLASS` will have a 173 | // `type_id_runtime()` method. 174 | return variable.type_id_runtime(); 175 | } 176 | } 177 | //] [/type_index_my_type_index_type_id_runtime_implmentation] 178 | 179 | //[type_index_my_type_index_type_id_runtime_classes 180 | /*` 181 | Consider the situation, when `my_class` and `my_struct` are polymorphic classes: 182 | */ 183 | 184 | namespace my_namespace { 185 | 186 | class my_class { 187 | public: 188 | MY_TYPEINDEX_REGISTER_CLASS 189 | virtual ~my_class() {} 190 | }; 191 | 192 | struct my_struct: public my_class { 193 | MY_TYPEINDEX_REGISTER_CLASS 194 | }; 195 | 196 | } // namespace my_namespace 197 | 198 | //] [/type_index_my_type_index_type_id_runtime_classes] 199 | 200 | 201 | //[type_index_my_type_index_worldwide_typedefs 202 | /*` 203 | You'll also need to add some typedefs and macro to your "user_defined_typeinfo.hpp" header file: 204 | */ 205 | #define BOOST_TYPE_INDEX_REGISTER_CLASS MY_TYPEINDEX_REGISTER_CLASS 206 | namespace boost { namespace typeindex { 207 | using type_index = my_namespace::my_type_index; 208 | }} 209 | //] [/type_index_my_type_index_worldwide_typedefs] 210 | 211 | 212 | #endif // USER_DEFINED_TYPEINFO_HPP 213 | 214 | -------------------------------------------------------------------------------- /include/boost/type_index/ctti_type_index.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013-2025 Antony Polukhin. 3 | // 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_TYPE_INDEX_CTTI_TYPE_INDEX_HPP 10 | #define BOOST_TYPE_INDEX_CTTI_TYPE_INDEX_HPP 11 | 12 | /// \file ctti_type_index.hpp 13 | /// \brief Contains boost::typeindex::ctti_type_index class that is constexpr if C++14 constexpr is supported by compiler. 14 | /// 15 | /// boost::typeindex::ctti_type_index class can be used as a drop-in replacement 16 | /// for std::type_index. 17 | /// 18 | /// It is used in situations when typeid() method is not available or 19 | /// BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY macro is defined. 20 | 21 | #include 22 | 23 | #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 24 | 25 | #include 26 | #include 27 | 28 | #if !defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 29 | #include 30 | #include 31 | 32 | #include 33 | #endif 34 | 35 | #ifdef BOOST_HAS_PRAGMA_ONCE 36 | # pragma once 37 | #endif 38 | 39 | namespace boost { namespace typeindex { 40 | 41 | namespace detail { 42 | 43 | // That's the most trickiest part of the TypeIndex library: 44 | // 1) we do not want to give user ability to manually construct and compare `struct-that-represents-type` 45 | // 2) we need to distinguish between `struct-that-represents-type` and `const char*` 46 | // 3) we need a thread-safe way to have references to instances `struct-that-represents-type` 47 | // 4) we need a compile-time control to make sure that user does not copy or 48 | // default construct `struct-that-represents-type` 49 | // 50 | // Solution would be the following: 51 | 52 | /// \class ctti_data 53 | /// Standard-layout class with private constructors and assignment operators. 54 | /// 55 | /// You can not work with this class directly. The purpose of this class is to hold type info 56 | /// \b when \b RTTI \b is \b off and allow ctti_type_index construction from itself. 57 | /// 58 | /// \b Example: 59 | /// \code 60 | /// const detail::ctti_data& foo(); 61 | /// ... 62 | /// type_index ti = type_index(foo()); 63 | /// std::cout << ti.pretty_name(); 64 | /// \endcode 65 | class ctti_data { 66 | public: 67 | ctti_data() = delete; 68 | ctti_data(const ctti_data&) = delete; 69 | ctti_data& operator=(const ctti_data&) = delete; 70 | }; 71 | 72 | } // namespace detail 73 | 74 | BOOST_TYPE_INDEX_BEGIN_MODULE_EXPORT 75 | 76 | /// Helper method for getting detail::ctti_data of a template parameter T. 77 | template 78 | inline const detail::ctti_data& ctti_construct() noexcept { 79 | // Standard C++11, 5.2.10 Reinterpret cast: 80 | // An object pointer can be explicitly converted to an object pointer of a different type. When a prvalue 81 | // v of type "pointer to T1" is converted to the type "pointer to cv T2", the result is static_cast(static_cast(v)) if both T1 and T2 are standard-layout types (3.9) and the alignment 83 | // requirements of T2 are no stricter than those of T1, or if either type is void. Converting a prvalue of type 84 | // "pointer to T1" to the type "pointer to T2" (where T1 and T2 are object types and where the alignment 85 | // requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer 86 | // value. 87 | // 88 | // Alignments are checked in `type_index_test_ctti_alignment.cpp` test. 89 | return *reinterpret_cast(boost::detail::ctti::n()); 90 | } 91 | 92 | /// \class ctti_type_index 93 | /// This class is a wrapper that pretends to work exactly like stl_type_index, but does 94 | /// not require RTTI support. \b For \b description \b of \b functions \b see type_index_facade. 95 | /// 96 | /// This class on C++14 compatible compilers has following functions marked as constexpr: 97 | /// * default constructor 98 | /// * copy constructors and assignemnt operations 99 | /// * class methods: name(), before(const ctti_type_index& rhs), equal(const ctti_type_index& rhs) 100 | /// * static methods type_id(), type_id_with_cvr() 101 | /// * comparison operators 102 | /// 103 | /// This class produces slightly longer type names, so consider using stl_type_index 104 | /// in situations when typeid() is working. 105 | class ctti_type_index: public type_index_facade { 106 | const char* data_; 107 | 108 | inline std::size_t get_raw_name_length() const noexcept; 109 | 110 | BOOST_CXX14_CONSTEXPR inline explicit ctti_type_index(const char* data) noexcept 111 | : data_(data) 112 | {} 113 | 114 | public: 115 | using type_info_t = detail::ctti_data; 116 | 117 | BOOST_CXX14_CONSTEXPR inline ctti_type_index() noexcept 118 | : data_(boost::detail::ctti::n()) 119 | {} 120 | 121 | inline ctti_type_index(const type_info_t& data) noexcept 122 | : data_(reinterpret_cast(&data)) 123 | {} 124 | 125 | inline const type_info_t& type_info() const noexcept; 126 | BOOST_CXX14_CONSTEXPR inline const char* raw_name() const noexcept; 127 | BOOST_CXX14_CONSTEXPR inline const char* name() const noexcept; 128 | inline std::string pretty_name() const; 129 | inline std::size_t hash_code() const noexcept; 130 | 131 | BOOST_CXX14_CONSTEXPR inline bool equal(const ctti_type_index& rhs) const noexcept; 132 | BOOST_CXX14_CONSTEXPR inline bool before(const ctti_type_index& rhs) const noexcept; 133 | 134 | template 135 | BOOST_CXX14_CONSTEXPR inline static ctti_type_index type_id() noexcept; 136 | 137 | template 138 | BOOST_CXX14_CONSTEXPR inline static ctti_type_index type_id_with_cvr() noexcept; 139 | 140 | template 141 | inline static ctti_type_index type_id_runtime(const T& variable) noexcept; 142 | }; 143 | 144 | BOOST_TYPE_INDEX_END_MODULE_EXPORT 145 | 146 | 147 | inline const ctti_type_index::type_info_t& ctti_type_index::type_info() const noexcept { 148 | return *reinterpret_cast(data_); 149 | } 150 | 151 | 152 | BOOST_CXX14_CONSTEXPR inline bool ctti_type_index::equal(const ctti_type_index& rhs) const noexcept { 153 | const char* const left = raw_name(); 154 | const char* const right = rhs.raw_name(); 155 | return /*left == right ||*/ !boost::typeindex::detail::constexpr_strcmp(left, right); 156 | } 157 | 158 | BOOST_CXX14_CONSTEXPR inline bool ctti_type_index::before(const ctti_type_index& rhs) const noexcept { 159 | const char* const left = raw_name(); 160 | const char* const right = rhs.raw_name(); 161 | return /*left != right &&*/ boost::typeindex::detail::constexpr_strcmp(left, right) < 0; 162 | } 163 | 164 | 165 | template 166 | BOOST_CXX14_CONSTEXPR inline ctti_type_index ctti_type_index::type_id() noexcept { 167 | using no_ref_t = typename std::remove_reference::type; 168 | using no_cvr_t = typename std::remove_cv::type; 169 | return ctti_type_index(boost::detail::ctti::n()); 170 | } 171 | 172 | 173 | 174 | template 175 | BOOST_CXX14_CONSTEXPR inline ctti_type_index ctti_type_index::type_id_with_cvr() noexcept { 176 | return ctti_type_index(boost::detail::ctti::n()); 177 | } 178 | 179 | 180 | template 181 | inline ctti_type_index ctti_type_index::type_id_runtime(const T& variable) noexcept { 182 | return variable.boost_type_index_type_id_runtime_(); 183 | } 184 | 185 | 186 | BOOST_CXX14_CONSTEXPR inline const char* ctti_type_index::raw_name() const noexcept { 187 | return data_; 188 | } 189 | 190 | 191 | BOOST_CXX14_CONSTEXPR inline const char* ctti_type_index::name() const noexcept { 192 | return data_; 193 | } 194 | 195 | inline std::size_t ctti_type_index::get_raw_name_length() const noexcept { 196 | return std::strlen(raw_name() + detail::skip().size_at_end); 197 | } 198 | 199 | 200 | inline std::string ctti_type_index::pretty_name() const { 201 | std::size_t len = get_raw_name_length(); 202 | while (raw_name()[len - 1] == ' ') --len; // MSVC sometimes adds whitespaces 203 | return std::string(raw_name(), len); 204 | } 205 | 206 | 207 | inline std::size_t ctti_type_index::hash_code() const noexcept { 208 | return boost::hash_range(raw_name(), raw_name() + get_raw_name_length()); 209 | } 210 | 211 | }} // namespace boost::typeindex 212 | 213 | #endif // #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 214 | 215 | #endif // BOOST_TYPE_INDEX_CTTI_TYPE_INDEX_HPP 216 | 217 | -------------------------------------------------------------------------------- /test/type_index_runtime_cast_test.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright Chris Glover, 2016. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See 5 | // accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | // #include 9 | // #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | #if !defined(BOOST_NO_CXX11_SMART_PTR) 18 | # include 19 | #endif 20 | 21 | // Classes include a member variable "name" with the 22 | // name of the class hard coded so we can be sure that 23 | // the pointer offsets are all working, since we're doing 24 | // a cast from void* at some point. 25 | 26 | #define IMPLEMENT_CLASS(type_name) \ 27 | type_name() : name( #type_name ) {} \ 28 | std::string name; 29 | 30 | struct base { 31 | BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST() 32 | IMPLEMENT_CLASS(base) 33 | }; 34 | 35 | struct single_derived : base { 36 | BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(base) 37 | IMPLEMENT_CLASS(single_derived) 38 | }; 39 | 40 | struct base1 { 41 | BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST() 42 | IMPLEMENT_CLASS(base1) 43 | }; 44 | 45 | struct base2 { 46 | BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST() 47 | IMPLEMENT_CLASS(base2) 48 | }; 49 | 50 | struct multiple_derived : base1, base2 { 51 | BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(base1, base2) 52 | IMPLEMENT_CLASS(multiple_derived) 53 | }; 54 | 55 | struct baseV1 : virtual base { 56 | BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(base) 57 | IMPLEMENT_CLASS(baseV1) 58 | }; 59 | 60 | struct baseV2 : virtual base { 61 | BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(base) 62 | IMPLEMENT_CLASS(baseV2) 63 | }; 64 | 65 | struct multiple_virtual_derived : baseV1, baseV2 { 66 | BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(baseV1, baseV2) 67 | IMPLEMENT_CLASS(multiple_virtual_derived) 68 | }; 69 | 70 | struct unrelated { 71 | BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST() 72 | IMPLEMENT_CLASS(unrelated) 73 | }; 74 | 75 | struct unrelated_with_base : base { 76 | BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(base) 77 | IMPLEMENT_CLASS(unrelated_with_base) 78 | }; 79 | 80 | struct unrelatedV1 : virtual base { 81 | BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(base) 82 | IMPLEMENT_CLASS(unrelatedV1) 83 | }; 84 | 85 | struct level1_a : base { 86 | BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(base) 87 | IMPLEMENT_CLASS(level1_a) 88 | }; 89 | 90 | struct level1_b : base { 91 | BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(base) 92 | IMPLEMENT_CLASS(level1_b) 93 | }; 94 | 95 | struct level2 : level1_a, level1_b { 96 | BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(level1_a, level1_b) 97 | IMPLEMENT_CLASS(level2) 98 | }; 99 | 100 | struct reg_base { 101 | BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS() 102 | }; 103 | 104 | struct reg_derived : reg_base { 105 | BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(reg_base) 106 | }; 107 | 108 | void no_base() 109 | { 110 | using namespace boost::typeindex; 111 | base b; 112 | base* b2 = runtime_pointer_cast(&b); 113 | BOOST_TEST_NE(b2, (base*)NULL); 114 | BOOST_TEST_EQ(b2->name, "base"); 115 | 116 | BOOST_TEST_EQ(runtime_pointer_cast(&b), (unrelated*)NULL); 117 | BOOST_TEST_EQ(runtime_pointer_cast(&b), (single_derived*)NULL); 118 | BOOST_TEST_EQ(runtime_pointer_cast(&b), (unrelatedV1*)NULL); 119 | BOOST_TEST_EQ(runtime_pointer_cast(&b), (unrelated_with_base*)NULL); 120 | } 121 | 122 | void single_base() 123 | { 124 | using namespace boost::typeindex; 125 | single_derived d; 126 | base* b = &d; 127 | single_derived* d2 = runtime_pointer_cast(b); 128 | BOOST_TEST_NE(d2, (single_derived*)NULL); 129 | BOOST_TEST_EQ(d2->name, "single_derived"); 130 | 131 | BOOST_TEST_EQ(runtime_pointer_cast(&d), (unrelated*)NULL); 132 | BOOST_TEST_EQ(runtime_pointer_cast(b), (unrelated*)NULL); 133 | BOOST_TEST_EQ(runtime_pointer_cast(b), (unrelated_with_base*)NULL); 134 | } 135 | 136 | void multiple_base() 137 | { 138 | using namespace boost::typeindex; 139 | multiple_derived d; 140 | base1* b1 = &d; 141 | multiple_derived* d2 = runtime_pointer_cast(b1); 142 | BOOST_TEST_NE(d2, (multiple_derived*)NULL); 143 | BOOST_TEST_EQ(d2->name, "multiple_derived"); 144 | 145 | base2* b2 = runtime_pointer_cast(b1); 146 | BOOST_TEST_NE(b2, (base2*)NULL); 147 | BOOST_TEST_EQ(b2->name, "base2"); 148 | 149 | BOOST_TEST_EQ(runtime_pointer_cast(&d), (unrelated*)NULL); 150 | BOOST_TEST_EQ(runtime_pointer_cast(b1), (unrelated*)NULL); 151 | BOOST_TEST_EQ(runtime_pointer_cast(b1), (unrelated_with_base*)NULL); 152 | } 153 | 154 | void virtual_base() 155 | { 156 | using namespace boost::typeindex; 157 | multiple_virtual_derived d; 158 | base* b = &d; 159 | multiple_virtual_derived* d2 = runtime_pointer_cast(b); 160 | baseV1* bv1 = runtime_pointer_cast(b); 161 | baseV2* bv2 = runtime_pointer_cast(b); 162 | 163 | BOOST_TEST_NE(d2, (multiple_virtual_derived*)NULL); 164 | BOOST_TEST_EQ(d2->name, "multiple_virtual_derived"); 165 | 166 | BOOST_TEST_NE(bv1, (baseV1*)NULL); 167 | BOOST_TEST_EQ(bv1->name, "baseV1"); 168 | 169 | BOOST_TEST_NE(bv2, (baseV2*)NULL); 170 | BOOST_TEST_EQ(bv2->name, "baseV2"); 171 | 172 | BOOST_TEST_EQ(runtime_pointer_cast(b), (unrelated*)NULL); 173 | BOOST_TEST_EQ(runtime_pointer_cast(&d), (unrelated*)NULL); 174 | BOOST_TEST_EQ(runtime_pointer_cast(b), (unrelated_with_base*)NULL); 175 | } 176 | 177 | void pointer_interface() 178 | { 179 | using namespace boost::typeindex; 180 | single_derived d; 181 | base* b = &d; 182 | single_derived* d2 = runtime_cast(b); 183 | BOOST_TEST_NE(d2, (single_derived*)NULL); 184 | BOOST_TEST_EQ(d2->name, "single_derived"); 185 | BOOST_TEST_EQ(runtime_pointer_cast(b), (unrelated*)NULL); 186 | } 187 | 188 | void reference_interface() 189 | { 190 | using namespace boost::typeindex; 191 | single_derived d; 192 | base& b = d; 193 | single_derived& d2 = runtime_cast(b); 194 | BOOST_TEST_EQ(d2.name, "single_derived"); 195 | 196 | try { 197 | unrelated& u = runtime_cast(b); 198 | (void)u; 199 | BOOST_TEST(!"should throw bad_runtime_cast"); 200 | } 201 | catch(boost::typeindex::bad_runtime_cast&) { 202 | } 203 | catch(...) { 204 | BOOST_TEST(!"should throw bad_runtime_cast"); 205 | } 206 | } 207 | 208 | void const_pointer_interface() 209 | { 210 | using namespace boost::typeindex; 211 | const single_derived d; 212 | base const* b = &d; 213 | single_derived const* d2 = runtime_cast(b); 214 | BOOST_TEST_NE(d2, (single_derived*)NULL); 215 | BOOST_TEST_EQ(d2->name, "single_derived"); 216 | BOOST_TEST_EQ(runtime_pointer_cast(b), (unrelated*)NULL); 217 | } 218 | 219 | void const_reference_interface() 220 | { 221 | using namespace boost::typeindex; 222 | const single_derived d; 223 | base const& b = d; 224 | single_derived const& d2 = runtime_cast(b); 225 | BOOST_TEST_EQ(d2.name, "single_derived"); 226 | 227 | try { 228 | unrelated const& u = runtime_cast(b); 229 | (void)u; 230 | BOOST_TEST(!"should throw bad_runtime_cast"); 231 | } 232 | catch(boost::typeindex::bad_runtime_cast&) { 233 | } 234 | catch(...) { 235 | BOOST_TEST(!"should throw bad_runtime_cast"); 236 | } 237 | } 238 | 239 | void diamond_non_virtual() 240 | { 241 | using namespace boost::typeindex; 242 | level2 inst; 243 | level1_a* l1a = &inst; 244 | base* b1 = l1a; 245 | level1_b* l1_b = runtime_cast(b1); 246 | BOOST_TEST_NE(l1_b, (level1_b*)NULL); 247 | BOOST_TEST_EQ(l1_b->name, "level1_b"); 248 | } 249 | 250 | void boost_shared_ptr() 251 | { 252 | using namespace boost::typeindex; 253 | boost::shared_ptr d = boost::make_shared(); 254 | boost::shared_ptr b = d; 255 | boost::shared_ptr d2 = runtime_pointer_cast(b); 256 | BOOST_TEST_NE(d2, boost::shared_ptr()); 257 | BOOST_TEST_EQ(d2->name, "single_derived"); 258 | } 259 | 260 | void std_shared_ptr() 261 | { 262 | #if !defined(BOOST_NO_CXX11_SMART_PTR) 263 | using namespace boost::typeindex; 264 | std::shared_ptr d = std::make_shared(); 265 | std::shared_ptr b = d; 266 | std::shared_ptr d2 = runtime_pointer_cast(b); 267 | BOOST_TEST_NE(d2, std::shared_ptr()); 268 | BOOST_TEST_EQ(d2->name, "single_derived"); 269 | #endif 270 | } 271 | 272 | void register_runtime_class() 273 | { 274 | using namespace boost::typeindex; 275 | reg_derived rd; 276 | reg_base* rb = &rd; 277 | reg_derived* prd = runtime_pointer_cast(rb); 278 | BOOST_TEST_NE(prd, (reg_derived*)NULL); 279 | BOOST_TEST_EQ(type_id_runtime(*prd), type_id()); 280 | } 281 | 282 | int main() { 283 | no_base(); 284 | single_derived(); 285 | multiple_base(); 286 | virtual_base(); 287 | pointer_interface(); 288 | reference_interface(); 289 | const_pointer_interface(); 290 | const_reference_interface(); 291 | diamond_non_virtual(); 292 | boost_shared_ptr(); 293 | std_shared_ptr(); 294 | register_runtime_class(); 295 | return boost::report_errors(); 296 | } 297 | -------------------------------------------------------------------------------- /include/boost/type_index/stl_type_index.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013-2025 Antony Polukhin. 3 | // 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_TYPE_INDEX_STL_TYPE_INDEX_HPP 10 | #define BOOST_TYPE_INDEX_STL_TYPE_INDEX_HPP 11 | 12 | /// \file stl_type_index.hpp 13 | /// \brief Contains boost::typeindex::stl_type_index class. 14 | /// 15 | /// boost::typeindex::stl_type_index class can be used as a drop-in replacement 16 | /// for std::type_index. 17 | /// 18 | /// It is used in situations when RTTI is enabled or typeid() method is available. 19 | /// When typeid() is disabled or BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY macro 20 | /// is defined boost::typeindex::ctti is usually used instead of boost::typeindex::stl_type_index. 21 | 22 | #include 23 | 24 | #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 25 | 26 | #include 27 | 28 | // MSVC is capable of calling typeid(T) even when RTTI is off 29 | #if defined(BOOST_NO_RTTI) && !defined(BOOST_MSVC) 30 | #error "File boost/type_index/stl_type_index.ipp is not usable when typeid() is not available." 31 | #endif 32 | 33 | #if defined(__has_include) 34 | # if __has_include() 35 | # define BOOST_TYPE_INDEX_IMPL_HAS_CXXABI 36 | # endif 37 | #endif 38 | 39 | #if !defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 40 | #include 41 | #include // std::strcmp, std::strlen, std::strstr 42 | #include 43 | #include 44 | #include 45 | #include 46 | 47 | #include 48 | 49 | #ifdef BOOST_TYPE_INDEX_IMPL_HAS_CXXABI 50 | # include 51 | # include 52 | # include 53 | #endif 54 | 55 | #endif 56 | 57 | // Copied from boost/core/demangle.hpp 58 | #ifdef BOOST_TYPE_INDEX_IMPL_HAS_CXXABI 59 | // For some architectures (mips, mips64, x86, x86_64) cxxabi.h in Android NDK is implemented by gabi++ library 60 | // (https://android.googlesource.com/platform/ndk/+/master/sources/cxx-stl/gabi++/), which does not implement 61 | // abi::__cxa_demangle(). We detect this implementation by checking the include guard here. 62 | # ifdef __GABIXX_CXXABI_H__ 63 | # undef BOOST_TYPE_INDEX_IMPL_HAS_CXXABI 64 | # endif 65 | #endif 66 | 67 | #ifdef BOOST_HAS_PRAGMA_ONCE 68 | # pragma once 69 | #endif 70 | 71 | namespace boost { namespace typeindex { 72 | 73 | namespace impl { 74 | 75 | #ifdef BOOST_TYPE_INDEX_IMPL_HAS_CXXABI 76 | 77 | inline const char* demangle_alloc(const char* name) noexcept { 78 | int status = 0; 79 | std::size_t size = 0; 80 | return abi::__cxa_demangle(name, NULL, &size, &status); 81 | } 82 | 83 | inline void demangle_free(const void* name) noexcept { 84 | std::free(const_cast(name)); 85 | } 86 | 87 | #else 88 | 89 | inline const char* demangle_alloc(const char* name) noexcept { 90 | return name; 91 | } 92 | 93 | inline void demangle_free(const void* ) noexcept {} 94 | 95 | #endif 96 | 97 | #undef BOOST_TYPE_INDEX_IMPL_HAS_CXXABI 98 | 99 | } // namespace impl 100 | 101 | BOOST_TYPE_INDEX_BEGIN_MODULE_EXPORT 102 | 103 | /// \class stl_type_index 104 | /// This class is a wrapper around std::type_info, that workarounds issues and provides 105 | /// much more rich interface. \b For \b description \b of \b functions \b see type_index_facade. 106 | /// 107 | /// This class requires typeid() to work. For cases when RTTI is disabled see ctti_type_index. 108 | class stl_type_index 109 | : public type_index_facade< 110 | stl_type_index, 111 | #ifdef BOOST_NO_STD_TYPEINFO 112 | type_info 113 | #else 114 | std::type_info 115 | #endif 116 | > 117 | { 118 | public: 119 | #ifdef BOOST_NO_STD_TYPEINFO 120 | using type_info_t = type_info; 121 | #else 122 | using type_info_t = std::type_info; 123 | #endif 124 | 125 | private: 126 | const type_info_t* data_; 127 | 128 | public: 129 | inline stl_type_index() noexcept 130 | : data_(&typeid(void)) 131 | {} 132 | 133 | inline stl_type_index(const type_info_t& data) noexcept 134 | : data_(&data) 135 | {} 136 | 137 | inline const type_info_t& type_info() const noexcept; 138 | 139 | inline const char* raw_name() const noexcept; 140 | inline const char* name() const noexcept; 141 | inline std::string pretty_name() const; 142 | 143 | inline std::size_t hash_code() const noexcept; 144 | inline bool equal(const stl_type_index& rhs) const noexcept; 145 | inline bool before(const stl_type_index& rhs) const noexcept; 146 | 147 | template 148 | inline static stl_type_index type_id() noexcept; 149 | 150 | template 151 | inline static stl_type_index type_id_with_cvr() noexcept; 152 | 153 | template 154 | inline static stl_type_index type_id_runtime(const T& value) noexcept; 155 | }; 156 | 157 | BOOST_TYPE_INDEX_END_MODULE_EXPORT 158 | 159 | inline const stl_type_index::type_info_t& stl_type_index::type_info() const noexcept { 160 | return *data_; 161 | } 162 | 163 | 164 | inline const char* stl_type_index::raw_name() const noexcept { 165 | #ifdef _MSC_VER 166 | return data_->raw_name(); 167 | #else 168 | return data_->name(); 169 | #endif 170 | } 171 | 172 | inline const char* stl_type_index::name() const noexcept { 173 | return data_->name(); 174 | } 175 | 176 | inline std::string stl_type_index::pretty_name() const { 177 | static const char cvr_saver_name[] = "boost::typeindex::detail::cvr_saver"; 178 | constexpr std::string::size_type cvr_saver_name_len = sizeof(cvr_saver_name) - 1; 179 | 180 | // In case of MSVC demangle() is a no-op, and name() already returns demangled name. 181 | // In case of GCC and Clang (on non-Windows systems) name() returns mangled name and demangle() undecorates it. 182 | const std::unique_ptr demangled_name( 183 | impl::demangle_alloc(data_->name()), &impl::demangle_free 184 | ); 185 | 186 | const char* begin = demangled_name.get(); 187 | if (!begin) { 188 | boost::throw_exception(std::runtime_error("Type name demangling failed")); 189 | } 190 | 191 | const std::string::size_type len = std::strlen(begin); 192 | const char* end = begin + len; 193 | 194 | if (len > cvr_saver_name_len) { 195 | const char* b = std::strstr(begin, cvr_saver_name); 196 | if (b) { 197 | b += cvr_saver_name_len; 198 | 199 | // Trim everything till '<'. In modules the name could be boost::typeindex::detail::cvr_saver@boost.type_index< 200 | while (*b != '<') { // the string is zero terminated, we won't exceed the buffer size 201 | ++ b; 202 | } 203 | ++b; 204 | 205 | // Trim leading spaces 206 | while (*b == ' ') { // the string is zero terminated, we won't exceed the buffer size 207 | ++ b; 208 | } 209 | 210 | // Skip the closing angle bracket 211 | const char* e = end - 1; 212 | while (e > b && *e != '>') { 213 | -- e; 214 | } 215 | 216 | // Trim trailing spaces 217 | while (e > b && *(e - 1) == ' ') { 218 | -- e; 219 | } 220 | 221 | if (b < e) { 222 | // Parsing seems to have succeeded, the type name is not empty 223 | begin = b; 224 | end = e; 225 | } 226 | } 227 | } 228 | 229 | return std::string(begin, end); 230 | } 231 | 232 | 233 | inline std::size_t stl_type_index::hash_code() const noexcept { 234 | return data_->hash_code(); 235 | } 236 | 237 | 238 | /// @cond 239 | 240 | // for this compiler at least, cross-shared-library type_info 241 | // comparisons don't work, so we are using typeid(x).name() instead. 242 | # if (defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5))) \ 243 | || defined(_AIX) \ 244 | || (defined(__sgi) && defined(__host_mips)) \ 245 | || (defined(__hpux) && defined(__HP_aCC)) \ 246 | || (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC)) 247 | # define BOOST_TYPE_INDEX_CLASSINFO_COMPARE_BY_NAMES 248 | # endif 249 | 250 | /// @endcond 251 | 252 | inline bool stl_type_index::equal(const stl_type_index& rhs) const noexcept { 253 | #ifdef BOOST_TYPE_INDEX_CLASSINFO_COMPARE_BY_NAMES 254 | return raw_name() == rhs.raw_name() || !std::strcmp(raw_name(), rhs.raw_name()); 255 | #else 256 | return !!(*data_ == *rhs.data_); 257 | #endif 258 | } 259 | 260 | inline bool stl_type_index::before(const stl_type_index& rhs) const noexcept { 261 | #ifdef BOOST_TYPE_INDEX_CLASSINFO_COMPARE_BY_NAMES 262 | return raw_name() != rhs.raw_name() && std::strcmp(raw_name(), rhs.raw_name()) < 0; 263 | #else 264 | return !!data_->before(*rhs.data_); 265 | #endif 266 | } 267 | 268 | #undef BOOST_TYPE_INDEX_CLASSINFO_COMPARE_BY_NAMES 269 | 270 | 271 | template 272 | inline stl_type_index stl_type_index::type_id() noexcept { 273 | using no_ref_t = typename std::remove_reference::type; 274 | using no_cvr_t = typename std::remove_cv::type; 275 | return typeid(no_cvr_t); 276 | } 277 | 278 | namespace detail { 279 | template class cvr_saver{}; 280 | } 281 | 282 | template 283 | inline stl_type_index stl_type_index::type_id_with_cvr() noexcept { 284 | using type = typename std::conditional< 285 | std::is_reference::value || std::is_const::value || std::is_volatile::value, 286 | detail::cvr_saver, 287 | T 288 | >::type; 289 | 290 | return typeid(type); 291 | } 292 | 293 | 294 | template 295 | inline stl_type_index stl_type_index::type_id_runtime(const T& value) noexcept { 296 | #ifdef BOOST_NO_RTTI 297 | return value.boost_type_index_type_id_runtime_(); 298 | #else 299 | return typeid(value); 300 | #endif 301 | } 302 | 303 | }} // namespace boost::typeindex 304 | 305 | #endif // #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 306 | 307 | #endif // BOOST_TYPE_INDEX_STL_TYPE_INDEX_HPP 308 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - master 8 | - develop 9 | - feature/** 10 | 11 | env: 12 | UBSAN_OPTIONS: print_stacktrace=1 13 | 14 | jobs: 15 | posix: 16 | strategy: 17 | fail-fast: false 18 | matrix: 19 | include: 20 | - toolset: gcc-14 # Do not remove! It is the only toolset that tests CMake tests down below 21 | cxxstd: "03,11,14,17,20" 22 | os: ubuntu-24.04 23 | - toolset: gcc-12 24 | cxxstd: "03,11,14,17,2a" 25 | os: ubuntu-22.04 26 | cxxflags: "cxxflags=--coverage -fsanitize=address,leak,undefined -fno-sanitize-recover=undefined" 27 | linkflags: "linkflags=--coverage -lasan -lubsan" 28 | gcov_tool: "gcov-12" 29 | launcher: "testing.launcher=LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libasan.so.8" 30 | - toolset: gcc-11 31 | cxxstd: "03,11,14,17,2a" 32 | os: ubuntu-22.04 33 | cxxflags: "cxxflags=--coverage -fsanitize=address,leak,undefined -fno-sanitize-recover=undefined" 34 | linkflags: "linkflags=--coverage -lasan -lubsan" 35 | gcov_tool: "gcov-11" 36 | launcher: "testing.launcher=LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libasan.so.6" 37 | - toolset: gcc-10 38 | cxxstd: "03,11,14,17,2a" 39 | os: ubuntu-22.04 40 | cxxflags: "cxxflags=--coverage -fsanitize=address,leak,undefined -fno-sanitize-recover=undefined" 41 | linkflags: "linkflags=--coverage -lasan -lubsan" 42 | gcov_tool: "gcov-10" 43 | launcher: "testing.launcher=LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libasan.so.6" 44 | - toolset: clang 45 | compiler: clang++-14 46 | cxxstd: "03,11,14,17,2a" 47 | os: ubuntu-22.04 48 | - toolset: clang-19 49 | cxxstd: "20,23" 50 | os: ubuntu-24.04 51 | install: clang-19 llvm-19 libclang-rt-19-dev libc++-19-dev libc++abi-19-dev clang-tools-19 52 | 53 | runs-on: ${{matrix.os}} 54 | 55 | steps: 56 | - uses: actions/checkout@v3 57 | 58 | - name: Install packages 59 | if: matrix.install 60 | run: sudo apt install ${{matrix.install}} 61 | 62 | - name: Setup Boost 63 | run: | 64 | echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY 65 | LIBRARY=${GITHUB_REPOSITORY#*/} 66 | echo LIBRARY: $LIBRARY 67 | echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV 68 | echo GITHUB_BASE_REF: $GITHUB_BASE_REF 69 | echo GITHUB_REF: $GITHUB_REF 70 | REF=${GITHUB_BASE_REF:-$GITHUB_REF} 71 | REF=${REF#refs/heads/} 72 | echo REF: $REF 73 | BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true 74 | echo BOOST_BRANCH: $BOOST_BRANCH 75 | cd .. 76 | git clone -b $BOOST_BRANCH --depth 10 https://github.com/boostorg/boost.git boost-root 77 | cd boost-root 78 | git submodule update --init --depth 10 --jobs 2 tools/boostdep tools/inspect libs/filesystem 79 | python tools/boostdep/depinst/depinst.py --git_args "--depth 10 --jobs 3" filesystem 80 | rm -rf libs/$LIBRARY/* 81 | cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY 82 | python tools/boostdep/depinst/depinst.py --include benchmark --include example --include examples --include tools --git_args "--depth 10 --jobs 3" $LIBRARY 83 | ./bootstrap.sh 84 | ./b2 -j4 variant=debug tools/inspect 85 | 86 | - name: Run CMake tests 87 | if: ${{matrix.toolset == 'gcc-14'}} 88 | run: | 89 | cd ../boost-root/ 90 | mkdir __build 91 | cd __build 92 | cmake -DBUILD_TESTING=1 -DBOOST_INCLUDE_LIBRARIES=type_index -DCMAKE_CXX_COMPILER=g++-14 -DCMAKE_C_COMPILER=gcc-14 .. 93 | cmake --build . --target tests 94 | ctest --output-on-failure --no-tests=error 95 | cd .. 96 | rm -rf __build 97 | 98 | - name: Run modules tests without 'import std;' 99 | if: ${{matrix.toolset == 'clang-19'}} 100 | run: | 101 | cd ../boost-root/libs/type_index 102 | mkdir build_module 103 | cd build_module 104 | cmake -DBOOST_USE_MODULES=1 -DBUILD_TESTING=1 -GNinja -DCMAKE_CXX_COMPILER=clang++-19 ../test/cmake_subdir_test/ 105 | cmake --build . 106 | ctest -V 107 | cd .. 108 | rm -rf build_module 109 | 110 | - name: Run modules tests 111 | if: false 112 | #if: ${{matrix.toolset == 'clang-19'}} 113 | run: | 114 | cd ../boost-root/libs/type_index 115 | mkdir build_module 116 | cd build_module 117 | cmake -DBUILD_TESTING=1 -DBOOST_USE_MODULES=1 -DCMAKE_CXX_COMPILER=clang++-19 -DCMAKE_CXX_FLAGS=-stdlib=libc++ -DCMAKE_EXE_LINKER_FLAGS=-stdlib=libc++ -DCMAKE_CXX_STANDARD=23 -DCMAKE_EXPERIMENTAL_CXX_IMPORT_STD=0e5b6991-d74f-4b3d-a41c-cf096e0b2508 -G Ninja ../test/cmake_subdir_test/ 118 | cmake --build . 119 | ctest -V 120 | cd .. 121 | rm -rf build_module 122 | 123 | - name: Run tests 124 | run: | 125 | cd ../boost-root 126 | ./b2 -j3 libs/$LIBRARY/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} variant=debug,release "${{matrix.cxxflags}}" "${{matrix.linkflags}}" "${{matrix.launcher}}" 127 | dist/bin/inspect libs/$LIBRARY 128 | 129 | - name: Prepare coverage data 130 | if: matrix.gcov_tool 131 | run: | 132 | mkdir -p $GITHUB_WORKSPACE/coveralls 133 | 134 | echo -e "#!/bin/bash\nexec ${{matrix.gcov_tool}} \"\$@\"" > $GITHUB_WORKSPACE/coveralls/gcov_wrapper.sh 135 | chmod +x $GITHUB_WORKSPACE/coveralls/gcov_wrapper.sh 136 | wget https://github.com/linux-test-project/lcov/archive/v1.15.zip 137 | unzip v1.15.zip 138 | LCOV="`pwd`/lcov-1.15/bin/lcov --gcov-tool $GITHUB_WORKSPACE/coveralls/gcov_wrapper.sh" 139 | 140 | echo "$LCOV --directory ../boost-root/bin.v2/libs/$LIBRARY/ --base-directory `pwd`/libs/$LIBRARY/test --capture --output-file $GITHUB_WORKSPACE/coveralls/coverage.info" 141 | $LCOV --directory ../boost-root/bin.v2/libs/$LIBRARY/ --base-directory ../boost-root/ --capture --output-file $GITHUB_WORKSPACE/coveralls/coverage.info 142 | $LCOV --remove $GITHUB_WORKSPACE/coveralls/coverage.info "/usr*" "*/$LIBRARY/test/*" ${{matrix.ignore_coverage}} "*/$LIBRARY/tests/*" "*/$LIBRARY/examples/*" "*/$LIBRARY/example/*" -o $GITHUB_WORKSPACE/coveralls/coverage.info 143 | 144 | cd ../boost-root 145 | OTHER_LIBS=`grep "submodule .*" .gitmodules | sed 's/\[submodule\ "\(.*\)"\]/"\*\/boost\/\1\.hpp" "\*\/boost\/\1\/\*"/g'| sed "/\"\*\/boost\/$LIBRARY\/\*\"/d" | sed ':a;N;$!ba;s/\n/ /g'` 146 | echo $OTHER_LIBS 147 | eval "$LCOV --remove $GITHUB_WORKSPACE/coveralls/coverage.info $OTHER_LIBS -o $GITHUB_WORKSPACE/coveralls/coverage.info" 148 | 149 | - name: Coveralls 150 | uses: coverallsapp/github-action@master 151 | if: matrix.gcov_tool 152 | with: 153 | github-token: ${{ secrets.GITHUB_TOKEN }} 154 | path-to-lcov: ./coveralls/coverage.info 155 | parallel: true 156 | 157 | windows: 158 | strategy: 159 | fail-fast: false 160 | matrix: 161 | include: 162 | - toolset: msvc 163 | cxxstd: "14,17,20,latest" 164 | addrmd: 32,64 165 | os: windows-2025 166 | - toolset: msvc-14.3 167 | cxxstd: "14,17,20,latest" 168 | addrmd: 32,64 169 | os: windows-2022 170 | - toolset: clang-win 171 | cxxstd: "14,17,latest" 172 | addrmd: 32,64 173 | os: windows-2022 174 | - toolset: gcc 175 | cxxstd: "03,11,14,17,2a" 176 | addrmd: 64 177 | os: windows-2025 178 | 179 | runs-on: ${{matrix.os}} 180 | 181 | steps: 182 | - uses: actions/checkout@v3 183 | 184 | - name: Setup Boost 185 | shell: cmd 186 | run: | 187 | echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY% 188 | for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi 189 | echo LIBRARY: %LIBRARY% 190 | echo LIBRARY=%LIBRARY%>>%GITHUB_ENV% 191 | echo GITHUB_BASE_REF: %GITHUB_BASE_REF% 192 | echo GITHUB_REF: %GITHUB_REF% 193 | if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF% 194 | set BOOST_BRANCH=develop 195 | for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master 196 | echo BOOST_BRANCH: %BOOST_BRANCH% 197 | cd .. 198 | git clone -b %BOOST_BRANCH% --depth 10 https://github.com/boostorg/boost.git boost-root 199 | cd boost-root 200 | xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\ 201 | git submodule update --init tools/boostdep 202 | python tools/boostdep/depinst/depinst.py --include benchmark --include example --include examples --include tools --git_args "--jobs 3" %LIBRARY% 203 | cmd /c bootstrap 204 | 205 | - name: Run CMake tests 206 | if: ${{matrix.toolset == 'msvc-14.3'}} 207 | shell: cmd 208 | run: | 209 | call "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvarsall.bat" x64 210 | cd ../boost-root 211 | mkdir __build_cmake 212 | cd __build_cmake 213 | cmake -DBUILD_TESTING=1 -DBOOST_INCLUDE_LIBRARIES=type_index .. 214 | cmake --build . --target tests --config Debug 215 | ctest --output-on-failure --no-tests=error -C Debug 216 | 217 | - name: Run modules tests 218 | if: false # No std module in ${{matrix.toolset == 'msvc-14.3'}} 219 | shell: cmd 220 | run: | 221 | call "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvarsall.bat" x64 222 | cd ../boost-root 223 | mkdir __build_modules 224 | cd __build_modules 225 | cmake -DBOOST_USE_MODULES=1 -DBUILD_TESTING=1 -DCMAKE_CXX_STANDARD=23 -DCMAKE_EXPERIMENTAL_CXX_IMPORT_STD=0e5b6991-d74f-4b3d-a41c-cf096e0b2508 -G Ninja ../libs/type_index/test/cmake_subdir_test 226 | cmake --build . 227 | ctest --no-tests=error -V 228 | 229 | - name: Run modules tests without 'import std;' 230 | if: ${{matrix.toolset == 'msvc-14.3'}} 231 | shell: cmd 232 | run: | 233 | call "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvarsall.bat" x64 234 | cd ../boost-root 235 | mkdir __build_modules_std 236 | cd __build_modules_std 237 | cmake -DBOOST_USE_MODULES=1 -DBUILD_TESTING=1 -DCMAKE_CXX_STANDARD=20 -G Ninja ../libs/type_index/test/cmake_subdir_test 238 | cmake --build . 239 | ctest --no-tests=error -V 240 | 241 | - name: Run tests 242 | shell: cmd 243 | run: | 244 | cd ../boost-root 245 | b2 -j3 libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release embed-manifest-via=linker 246 | 247 | finish: 248 | needs: posix 249 | runs-on: ubuntu-latest 250 | steps: 251 | - name: Coveralls Finished 252 | uses: coverallsapp/github-action@master 253 | with: 254 | github-token: ${{ secrets.github_token }} 255 | parallel-finished: true 256 | -------------------------------------------------------------------------------- /include/boost/type_index.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2012-2025 Antony Polukhin. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | 8 | #ifndef BOOST_TYPE_INDEX_HPP 9 | #define BOOST_TYPE_INDEX_HPP 10 | 11 | /// \file boost/type_index.hpp 12 | /// \brief Includes minimal set of headers required to use the Boost.TypeIndex library. 13 | /// 14 | /// By inclusion of this file most optimal type index classes will be included and used 15 | /// as a boost::typeindex::type_index and boost::typeindex::type_info. 16 | 17 | #include 18 | 19 | #ifdef BOOST_HAS_PRAGMA_ONCE 20 | # pragma once 21 | #endif 22 | 23 | #if defined(BOOST_TYPE_INDEX_USER_TYPEINDEX) 24 | # include BOOST_TYPE_INDEX_USER_TYPEINDEX 25 | # ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH 26 | # pragma detect_mismatch( "boost__type_index__abi", "user defined type_index class is used: " BOOST_STRINGIZE(BOOST_TYPE_INDEX_USER_TYPEINDEX)) 27 | # endif 28 | #elif (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC) 29 | # include 30 | # if defined(BOOST_NO_RTTI) || defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY) 31 | # include 32 | # ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH 33 | # pragma detect_mismatch( "boost__type_index__abi", "RTTI is off - typeid() is used only for templates") 34 | # endif 35 | # else 36 | # ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH 37 | # pragma detect_mismatch( "boost__type_index__abi", "RTTI is used") 38 | # endif 39 | # endif 40 | #else 41 | # include 42 | # include 43 | # ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH 44 | # pragma detect_mismatch( "boost__type_index__abi", "RTTI is off - using CTTI") 45 | # endif 46 | #endif 47 | 48 | #ifndef BOOST_TYPE_INDEX_REGISTER_CLASS 49 | #define BOOST_TYPE_INDEX_REGISTER_CLASS 50 | #endif 51 | 52 | #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 53 | 54 | namespace boost { namespace typeindex { 55 | 56 | BOOST_TYPE_INDEX_BEGIN_MODULE_EXPORT 57 | 58 | #if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED) 59 | 60 | /// \def BOOST_TYPE_INDEX_FUNCTION_SIGNATURE 61 | /// BOOST_TYPE_INDEX_FUNCTION_SIGNATURE is used by boost::typeindex::ctti_type_index class to 62 | /// deduce the name of a type. If your compiler is not recognized 63 | /// by the TypeIndex library and you wish to work with boost::typeindex::ctti_type_index, you may 64 | /// define this macro by yourself. 65 | /// 66 | /// BOOST_TYPE_INDEX_FUNCTION_SIGNATURE must be defined to a compiler specific macro 67 | /// that outputs the \b whole function signature \b including \b template \b parameters. 68 | /// 69 | /// If your compiler is not recognised and BOOST_TYPE_INDEX_FUNCTION_SIGNATURE is not defined, 70 | /// then a compile-time error will arise at any attempt to use boost::typeindex::ctti_type_index classes. 71 | /// 72 | /// See BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS and BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING 73 | /// for an information of how to tune the implementation to make a nice pretty_name() output. 74 | #define BOOST_TYPE_INDEX_FUNCTION_SIGNATURE BOOST_CURRENT_FUNCTION 75 | 76 | /// \def BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING 77 | /// This is a helper macro for making correct pretty_names() with RTTI off. 78 | /// 79 | /// BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING macro may be defined to 80 | /// '(begin_skip, end_skip, runtime_skip, runtime_skip_until)' with parameters for adding a 81 | /// support for compilers, that by default are not recognized by TypeIndex library. 82 | /// 83 | /// \b Example: 84 | /// 85 | /// Imagine the situation when 86 | /// \code boost::typeindex::ctti_type_index::type_id().pretty_name() \endcode 87 | /// returns the following string: 88 | /// \code "static const char *boost::detail::ctti::n() [T = int]" \endcode 89 | /// and \code boost::typeindex::ctti_type_index::type_id().pretty_name() \endcode returns the following: 90 | /// \code "static const char *boost::detail::ctti::n() [T = short]" \endcode 91 | /// 92 | /// As we may see first 39 characters are "static const char *boost::detail::ctti<" and they do not depend on 93 | /// the type T. After first 39 characters we have a human readable type name which is duplicated at the end 94 | /// of a string. String always ends on ']', which consumes 1 character. 95 | /// 96 | /// Now if we define `BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING` to 97 | /// `(39, 1, false, "")` we'll be getting \code "int>::n() [T = int" \endcode 98 | /// for `boost::typeindex::ctti_type_index::type_id().pretty_name()` and \code "short>::n() [T = short" \endcode 99 | /// for `boost::typeindex::ctti_type_index::type_id().pretty_name()`. 100 | /// 101 | /// Now we need to take additional care of the characters that go before the last mention of our type. We'll 102 | /// do that by telling the macro that we need to cut off everything that goes before the "T = " including the "T = " 103 | /// itself: 104 | /// 105 | /// \code (39, 1, true, "T = ") \endcode 106 | /// 107 | /// In case of GCC or Clang command line we need to add the following line while compiling all the sources: 108 | /// 109 | /// \code 110 | /// -DBOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING='(39, 1, true, "T = ")' 111 | /// \endcode 112 | /// \param begin_skip How many characters must be skipped at the beginning of the type holding string. 113 | /// Must be a compile time constant. 114 | /// \param end_skip How many characters must be skipped at the end of the type holding string. 115 | /// Must be a compile time constant. 116 | /// \param runtime_skip Do we need additional checks at runtime to cut off the more characters. 117 | /// Must be `true` or `false`. 118 | /// \param runtime_skip_until Skip all the characters before the following string (including the string itself). 119 | /// Must be a compile time array of characters. 120 | /// 121 | /// See [RTTI emulation limitations](boost_typeindex/rtti_emulation_limitations.html) for more info. 122 | #define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING (0, 0, false, "") 123 | 124 | 125 | /// Depending on a compiler flags, optimal implementation of type_index will be used 126 | /// as a default boost::typeindex::type_index. 127 | /// 128 | /// Could be a boost::typeindex::stl_type_index, boost::typeindex::ctti_type_index or 129 | /// user defined type_index class. 130 | /// 131 | /// \b See boost::typeindex::type_index_facade for a full description of type_index functions. 132 | using type_index = platform_specific; 133 | #elif defined(BOOST_TYPE_INDEX_USER_TYPEINDEX) 134 | // Nothing to do 135 | #elif (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC) 136 | using type_index = boost::typeindex::stl_type_index; 137 | #else 138 | using type_index = boost::typeindex::ctti_type_index; 139 | #endif 140 | 141 | /// Depending on a compiler flags, optimal implementation of type_info will be used 142 | /// as a default boost::typeindex::type_info. 143 | /// 144 | /// Could be a std::type_info, boost::typeindex::detail::ctti_data or 145 | /// some user defined class. 146 | /// 147 | /// type_info \b is \b not copyable or default constructible. It is \b not assignable too! 148 | using type_info = type_index::type_info_t; 149 | 150 | #if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED) 151 | 152 | /// \def BOOST_TYPE_INDEX_USER_TYPEINDEX 153 | /// BOOST_TYPE_INDEX_USER_TYPEINDEX can be defined to the path to header file 154 | /// with user provided implementation of type_index. 155 | /// 156 | /// See [Making a custom type_index](boost_typeindex/making_a_custom_type_index.html) section 157 | /// of documentation for usage example. 158 | #define BOOST_TYPE_INDEX_USER_TYPEINDEX 159 | 160 | 161 | /// \def BOOST_TYPE_INDEX_REGISTER_CLASS 162 | /// BOOST_TYPE_INDEX_REGISTER_CLASS is used to help to emulate RTTI. 163 | /// Put this macro into the public section of polymorphic class to allow runtime type detection. 164 | /// 165 | /// Depending on the typeid() availability this macro will expand to nothing or to virtual helper function 166 | /// `virtual const type_info& boost_type_info_type_id_runtime_() const noexcept`. 167 | /// 168 | /// \b Example: 169 | /// \code 170 | /// class A { 171 | /// public: 172 | /// BOOST_TYPE_INDEX_REGISTER_CLASS 173 | /// virtual ~A(){} 174 | /// }; 175 | /// 176 | /// struct B: public A { 177 | /// BOOST_TYPE_INDEX_REGISTER_CLASS 178 | /// }; 179 | /// 180 | /// struct C: public B { 181 | /// BOOST_TYPE_INDEX_REGISTER_CLASS 182 | /// }; 183 | /// 184 | /// ... 185 | /// 186 | /// C c1; 187 | /// A* pc1 = &c1; 188 | /// assert(boost::typeindex::type_id() == boost::typeindex::type_id_runtime(*pc1)); 189 | /// \endcode 190 | #define BOOST_TYPE_INDEX_REGISTER_CLASS nothing-or-some-virtual-functions 191 | 192 | /// \def BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY 193 | /// BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY is a helper macro that must be defined if mixing 194 | /// RTTI on/off modules. See 195 | /// [Mixing sources with RTTI on and RTTI off](boost_typeindex/mixing_sources_with_rtti_on_and_.html) 196 | /// section of documentation for more info. 197 | #define BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY 198 | 199 | #endif // defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED) 200 | 201 | 202 | /// Function to get boost::typeindex::type_index for a type T. 203 | /// Removes const, volatile && and & modifiers from T. 204 | /// 205 | /// \b Example: 206 | /// \code 207 | /// type_index ti = type_id(); 208 | /// std::cout << ti.pretty_name(); // Outputs 'int' 209 | /// \endcode 210 | /// 211 | /// \tparam T Type for which type_index must be created. 212 | /// \throw Nothing. 213 | /// \return boost::typeindex::type_index with information about the specified type T. 214 | template 215 | inline type_index type_id() noexcept { 216 | return type_index::type_id(); 217 | } 218 | 219 | /// Function for constructing boost::typeindex::type_index instance for type T. 220 | /// Does not remove const, volatile, & and && modifiers from T. 221 | /// 222 | /// If T has no const, volatile, & and && modifiers, then returns exactly 223 | /// the same result as in case of calling `type_id()`. 224 | /// 225 | /// \b Example: 226 | /// \code 227 | /// type_index ti = type_id_with_cvr(); 228 | /// std::cout << ti.pretty_name(); // Outputs 'int&' 229 | /// \endcode 230 | /// 231 | /// \tparam T Type for which type_index must be created. 232 | /// \throw Nothing. 233 | /// \return boost::typeindex::type_index with information about the specified type T. 234 | template 235 | inline type_index type_id_with_cvr() noexcept { 236 | return type_index::type_id_with_cvr(); 237 | } 238 | 239 | /// Function that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index. 240 | /// 241 | /// Returns runtime information about specified type. 242 | /// 243 | /// \b Requirements: RTTI available or Base and Derived classes must be marked with BOOST_TYPE_INDEX_REGISTER_CLASS. 244 | /// 245 | /// \b Example: 246 | /// \code 247 | /// struct Base { virtual ~Base(){} }; 248 | /// struct Derived: public Base {}; 249 | /// ... 250 | /// Derived d; 251 | /// Base& b = d; 252 | /// type_index ti = type_id_runtime(b); 253 | /// std::cout << ti.pretty_name(); // Outputs 'Derived' 254 | /// \endcode 255 | /// 256 | /// \param runtime_val Variable which runtime type must be returned. 257 | /// \throw Nothing. 258 | /// \return boost::typeindex::type_index with information about the specified variable. 259 | template 260 | inline type_index type_id_runtime(const T& runtime_val) noexcept { 261 | return type_index::type_id_runtime(runtime_val); 262 | } 263 | 264 | BOOST_TYPE_INDEX_END_MODULE_EXPORT 265 | 266 | }} // namespace boost::typeindex 267 | 268 | #endif // #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 269 | 270 | #endif // BOOST_TYPE_INDEX_HPP 271 | 272 | -------------------------------------------------------------------------------- /include/boost/type_index/type_index_facade.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013-2025 Antony Polukhin. 3 | // 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_TYPE_INDEX_TYPE_INDEX_FACADE_HPP 10 | #define BOOST_TYPE_INDEX_TYPE_INDEX_FACADE_HPP 11 | 12 | #include 13 | 14 | #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 15 | 16 | #if !defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 17 | #include 18 | #include 19 | #include 20 | #include // for std::basic_ostream 21 | 22 | #include 23 | #include 24 | #endif 25 | 26 | #ifdef BOOST_HAS_PRAGMA_ONCE 27 | # pragma once 28 | #endif 29 | 30 | namespace boost { namespace typeindex { 31 | 32 | BOOST_TYPE_INDEX_BEGIN_MODULE_EXPORT 33 | 34 | /// \class type_index_facade 35 | /// 36 | /// This class takes care about the comparison operators, hash functions and 37 | /// ostream operators. Use this class as a public base class for defining new 38 | /// type_info-conforming classes. 39 | /// 40 | /// \b Example: 41 | /// \code 42 | /// class stl_type_index: public type_index_facade 43 | /// { 44 | /// public: 45 | /// using type_info_t = std::type_info; 46 | /// private: 47 | /// const type_info_t* data_; 48 | /// 49 | /// public: 50 | /// stl_type_index(const type_info_t& data) noexcept 51 | /// : data_(&data) 52 | /// {} 53 | /// // ... 54 | /// }; 55 | /// \endcode 56 | /// 57 | /// \tparam Derived Class derived from type_index_facade. 58 | /// \tparam TypeInfo Class that will be used as a base type_info class. 59 | /// \note Take a look at the protected methods. They are \b not \b defined in type_index_facade. 60 | /// Protected member functions raw_name() \b must be defined in Derived class. All the other 61 | /// methods are mandatory. 62 | /// \see 'Making a custom type_index' section for more information about 63 | /// creating your own type_index using type_index_facade. 64 | template 65 | class type_index_facade { 66 | private: 67 | /// @cond 68 | BOOST_CXX14_CONSTEXPR const Derived & derived() const noexcept { 69 | return *static_cast(this); 70 | } 71 | /// @endcond 72 | public: 73 | using type_info_t = TypeInfo; 74 | 75 | /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw. 76 | /// \return Name of a type. By default returns Derived::raw_name(). 77 | inline const char* name() const noexcept { 78 | return derived().raw_name(); 79 | } 80 | 81 | /// \b Override: This function \b may be redefined in Derived class. Overrides may throw. 82 | /// \return Human readable type name. By default returns Derived::name(). 83 | inline std::string pretty_name() const { 84 | return derived().name(); 85 | } 86 | 87 | /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw. 88 | /// \return True if two types are equal. By default compares types by raw_name(). 89 | inline bool equal(const Derived& rhs) const noexcept { 90 | const char* const left = derived().raw_name(); 91 | const char* const right = rhs.raw_name(); 92 | return left == right || !std::strcmp(left, right); 93 | } 94 | 95 | /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw. 96 | /// \return True if rhs is greater than this. By default compares types by raw_name(). 97 | inline bool before(const Derived& rhs) const noexcept { 98 | const char* const left = derived().raw_name(); 99 | const char* const right = rhs.raw_name(); 100 | return left != right && std::strcmp(left, right) < 0; 101 | } 102 | 103 | /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw. 104 | /// \return Hash code of a type. By default hashes types by raw_name(). 105 | /// \note Derived class header \b must include , \b unless this function is redefined in 106 | /// Derived class to not use boost::hash_range(). 107 | inline std::size_t hash_code() const noexcept { 108 | const char* const name_raw = derived().raw_name(); 109 | return boost::hash_range(name_raw, name_raw + std::strlen(name_raw)); 110 | } 111 | 112 | #if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED) 113 | protected: 114 | /// \b Override: This function \b must be redefined in Derived class. Overrides \b must not throw. 115 | /// \return Pointer to unredable/raw type name. 116 | inline const char* raw_name() const noexcept; 117 | 118 | /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw. 119 | /// \return Const reference to underlying low level type_info_t. 120 | inline const type_info_t& type_info() const noexcept; 121 | 122 | /// This is a factory method that is used to create instances of Derived classes. 123 | /// boost::typeindex::type_id() will call this method, if Derived has same type as boost::typeindex::type_index. 124 | /// 125 | /// \b Override: This function \b may be redefined and made public in Derived class. Overrides \b must not throw. 126 | /// Overrides \b must remove const, volatile && and & modifiers from T. 127 | /// \tparam T Type for which type_index must be created. 128 | /// \return type_index for type T. 129 | template 130 | static Derived type_id() noexcept; 131 | 132 | /// This is a factory method that is used to create instances of Derived classes. 133 | /// boost::typeindex::type_id_with_cvr() will call this method, if Derived has same type as boost::typeindex::type_index. 134 | /// 135 | /// \b Override: This function \b may be redefined and made public in Derived class. Overrides \b must not throw. 136 | /// Overrides \b must \b not remove const, volatile && and & modifiers from T. 137 | /// \tparam T Type for which type_index must be created. 138 | /// \return type_index for type T. 139 | template 140 | static Derived type_id_with_cvr() noexcept; 141 | 142 | /// This is a factory method that is used to create instances of Derived classes. 143 | /// boost::typeindex::type_id_runtime(const T&) will call this method, if Derived has same type as boost::typeindex::type_index. 144 | /// 145 | /// \b Override: This function \b may be redefined and made public in Derived class. 146 | /// \param variable Variable which runtime type will be stored in type_index. 147 | /// \return type_index with runtime type of variable. 148 | template 149 | static Derived type_id_runtime(const T& variable) noexcept; 150 | 151 | #endif 152 | 153 | }; 154 | 155 | /// @cond 156 | template 157 | BOOST_CXX14_CONSTEXPR inline bool operator == (const type_index_facade& lhs, const type_index_facade& rhs) noexcept { 158 | return static_cast(lhs).equal(static_cast(rhs)); 159 | } 160 | 161 | template 162 | BOOST_CXX14_CONSTEXPR inline bool operator < (const type_index_facade& lhs, const type_index_facade& rhs) noexcept { 163 | return static_cast(lhs).before(static_cast(rhs)); 164 | } 165 | 166 | 167 | 168 | template 169 | BOOST_CXX14_CONSTEXPR inline bool operator > (const type_index_facade& lhs, const type_index_facade& rhs) noexcept { 170 | return rhs < lhs; 171 | } 172 | 173 | template 174 | BOOST_CXX14_CONSTEXPR inline bool operator <= (const type_index_facade& lhs, const type_index_facade& rhs) noexcept { 175 | return !(lhs > rhs); 176 | } 177 | 178 | template 179 | BOOST_CXX14_CONSTEXPR inline bool operator >= (const type_index_facade& lhs, const type_index_facade& rhs) noexcept { 180 | return !(lhs < rhs); 181 | } 182 | 183 | template 184 | BOOST_CXX14_CONSTEXPR inline bool operator != (const type_index_facade& lhs, const type_index_facade& rhs) noexcept { 185 | return !(lhs == rhs); 186 | } 187 | 188 | // ######################### COMPARISONS with Derived ############################ // 189 | template 190 | inline bool operator == (const TypeInfo& lhs, const type_index_facade& rhs) noexcept { 191 | return Derived(lhs) == rhs; 192 | } 193 | 194 | template 195 | inline bool operator < (const TypeInfo& lhs, const type_index_facade& rhs) noexcept { 196 | return Derived(lhs) < rhs; 197 | } 198 | 199 | template 200 | inline bool operator > (const TypeInfo& lhs, const type_index_facade& rhs) noexcept { 201 | return rhs < Derived(lhs); 202 | } 203 | 204 | template 205 | inline bool operator <= (const TypeInfo& lhs, const type_index_facade& rhs) noexcept { 206 | return !(Derived(lhs) > rhs); 207 | } 208 | 209 | template 210 | inline bool operator >= (const TypeInfo& lhs, const type_index_facade& rhs) noexcept { 211 | return !(Derived(lhs) < rhs); 212 | } 213 | 214 | template 215 | inline bool operator != (const TypeInfo& lhs, const type_index_facade& rhs) noexcept { 216 | return !(Derived(lhs) == rhs); 217 | } 218 | 219 | 220 | template 221 | inline bool operator == (const type_index_facade& lhs, const TypeInfo& rhs) noexcept { 222 | return lhs == Derived(rhs); 223 | } 224 | 225 | template 226 | inline bool operator < (const type_index_facade& lhs, const TypeInfo& rhs) noexcept { 227 | return lhs < Derived(rhs); 228 | } 229 | 230 | template 231 | inline bool operator > (const type_index_facade& lhs, const TypeInfo& rhs) noexcept { 232 | return Derived(rhs) < lhs; 233 | } 234 | 235 | template 236 | inline bool operator <= (const type_index_facade& lhs, const TypeInfo& rhs) noexcept { 237 | return !(lhs > Derived(rhs)); 238 | } 239 | 240 | template 241 | inline bool operator >= (const type_index_facade& lhs, const TypeInfo& rhs) noexcept { 242 | return !(lhs < Derived(rhs)); 243 | } 244 | 245 | template 246 | inline bool operator != (const type_index_facade& lhs, const TypeInfo& rhs) noexcept { 247 | return !(lhs == Derived(rhs)); 248 | } 249 | 250 | // ######################### COMPARISONS with Derived END ############################ // 251 | 252 | /// @endcond 253 | 254 | #if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED) 255 | 256 | /// noexcept comparison operators for type_index_facade classes. 257 | bool operator ==, !=, <, ... (const type_index_facade& lhs, const type_index_facade& rhs) noexcept; 258 | 259 | /// noexcept comparison operators for type_index_facade and it's TypeInfo classes. 260 | bool operator ==, !=, <, ... (const type_index_facade& lhs, const TypeInfo& rhs) noexcept; 261 | 262 | /// noexcept comparison operators for type_index_facade's TypeInfo and type_index_facade classes. 263 | bool operator ==, !=, <, ... (const TypeInfo& lhs, const type_index_facade& rhs) noexcept; 264 | 265 | #endif 266 | 267 | #ifndef BOOST_NO_IOSTREAM 268 | /// Ostream operator that will output demangled name. 269 | template 270 | inline std::basic_ostream& operator<<( 271 | std::basic_ostream& ostr, 272 | const type_index_facade& ind) 273 | { 274 | ostr << static_cast(ind).pretty_name(); 275 | return ostr; 276 | } 277 | #endif // BOOST_NO_IOSTREAM 278 | 279 | /// This free function is used by Boost's unordered containers. 280 | /// \note has to be included if this function is used. 281 | template 282 | inline std::size_t hash_value(const type_index_facade& lhs) noexcept { 283 | return static_cast(lhs).hash_code(); 284 | } 285 | 286 | BOOST_TYPE_INDEX_END_MODULE_EXPORT 287 | 288 | }} // namespace boost::typeindex 289 | 290 | #endif // #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 291 | 292 | #endif // BOOST_TYPE_INDEX_TYPE_INDEX_FACADE_HPP 293 | 294 | -------------------------------------------------------------------------------- /test/type_index_test.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2012-2025 Antony Polukhin. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See 5 | // accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | 14 | namespace my_namespace1 { 15 | class my_class{}; 16 | } 17 | 18 | 19 | namespace my_namespace2 { 20 | class my_class{}; 21 | } 22 | 23 | 24 | void names_matches_type_id() 25 | { 26 | using namespace boost::typeindex; 27 | BOOST_TEST_EQ(type_id().pretty_name(), "int"); 28 | BOOST_TEST_EQ(type_id().pretty_name(), "double"); 29 | 30 | BOOST_TEST_EQ(type_id().name(), type_id().name()); 31 | BOOST_TEST_NE(type_id().name(), type_id().name()); 32 | BOOST_TEST_NE(type_id().name(), type_id().name()); 33 | BOOST_TEST_EQ(type_id().name(), type_id().name()); 34 | } 35 | 36 | void default_construction() 37 | { 38 | using namespace boost::typeindex; 39 | type_index ti1, ti2; 40 | BOOST_TEST_EQ(ti1, ti2); 41 | BOOST_TEST_EQ(type_id(), ti1); 42 | 43 | BOOST_TEST_EQ(type_id().name(), ti1.name()); 44 | BOOST_TEST_NE(type_id(), ti1); 45 | } 46 | 47 | 48 | void copy_construction() 49 | { 50 | using namespace boost::typeindex; 51 | type_index ti1, ti2 = type_id(); 52 | BOOST_TEST_NE(ti1, ti2); 53 | ti1 = ti2; 54 | BOOST_TEST_EQ(ti2, ti1); 55 | 56 | const type_index ti3(ti1); 57 | BOOST_TEST_EQ(ti3, ti1); 58 | } 59 | 60 | void comparators_type_id() 61 | { 62 | using namespace boost::typeindex; 63 | type_index t_int = type_id(); 64 | type_index t_double = type_id(); 65 | 66 | BOOST_TEST_EQ(t_int, t_int); 67 | BOOST_TEST_LE(t_int, t_int); 68 | BOOST_TEST_GE(t_int, t_int); 69 | BOOST_TEST_NE(t_int, t_double); 70 | 71 | BOOST_TEST_LE(t_double, t_double); 72 | BOOST_TEST_GE(t_double, t_double); 73 | BOOST_TEST_NE(t_double, t_int); 74 | 75 | BOOST_TEST(t_double < t_int || t_int < t_double); 76 | BOOST_TEST(t_double > t_int || t_int > t_double); 77 | } 78 | 79 | void hash_code_type_id() 80 | { 81 | using namespace boost::typeindex; 82 | std::size_t t_int1 = type_id().hash_code(); 83 | std::size_t t_double1 = type_id().hash_code(); 84 | 85 | std::size_t t_int2 = type_id().hash_code(); 86 | std::size_t t_double2 = type_id().hash_code(); 87 | 88 | BOOST_TEST_EQ(t_int1, t_int2); 89 | BOOST_TEST_NE(t_int1, t_double2); 90 | BOOST_TEST_LE(t_double1, t_double2); 91 | } 92 | 93 | 94 | 95 | template 96 | static void test_with_modofiers() { 97 | using namespace boost::typeindex; 98 | 99 | type_index t1 = type_id_with_cvr(); 100 | type_index t2 = type_id_with_cvr(); 101 | 102 | BOOST_TEST_NE(t2, t1); 103 | BOOST_TEST(t2 != t1.type_info()); 104 | BOOST_TEST(t2.type_info() != t1); 105 | 106 | BOOST_TEST(t1 < t2 || t2 < t1); 107 | BOOST_TEST(t1 > t2 || t2 > t1); 108 | BOOST_TEST(t1.type_info() < t2 || t2.type_info() < t1); 109 | BOOST_TEST(t1.type_info() > t2 || t2.type_info() > t1); 110 | BOOST_TEST(t1 < t2.type_info() || t2 < t1.type_info()); 111 | BOOST_TEST(t1 > t2.type_info() || t2 > t1.type_info()); 112 | 113 | // Chaecking that comparison operators overloads compile 114 | BOOST_TEST(t1 <= t2 || t2 <= t1); 115 | BOOST_TEST(t1 >= t2 || t2 >= t1); 116 | BOOST_TEST(t1.type_info() <= t2 || t2.type_info() <= t1); 117 | BOOST_TEST(t1.type_info() >= t2 || t2.type_info() >= t1); 118 | BOOST_TEST(t1 <= t2.type_info() || t2 <= t1.type_info()); 119 | BOOST_TEST(t1 >= t2.type_info() || t2 >= t1.type_info()); 120 | 121 | BOOST_TEST_EQ(t1, type_id_with_cvr()); 122 | BOOST_TEST_EQ(t2, type_id_with_cvr()); 123 | BOOST_TEST(t1 == type_id_with_cvr().type_info()); 124 | BOOST_TEST(t2 == type_id_with_cvr().type_info()); 125 | BOOST_TEST(t1.type_info() == type_id_with_cvr()); 126 | BOOST_TEST(t2.type_info() == type_id_with_cvr()); 127 | 128 | BOOST_TEST_EQ(t1.hash_code(), type_id_with_cvr().hash_code()); 129 | BOOST_TEST_EQ(t2.hash_code(), type_id_with_cvr().hash_code()); 130 | 131 | BOOST_TEST_NE(t1.hash_code(), type_id_with_cvr().hash_code()); 132 | BOOST_TEST_NE(t2.hash_code(), type_id_with_cvr().hash_code()); 133 | } 134 | 135 | void type_id_storing_modifiers() 136 | { 137 | test_with_modofiers(); 138 | test_with_modofiers(); 139 | test_with_modofiers(); 140 | test_with_modofiers(); 141 | test_with_modofiers(); 142 | test_with_modofiers(); 143 | test_with_modofiers(); 144 | 145 | test_with_modofiers(); 146 | test_with_modofiers(); 147 | test_with_modofiers(); 148 | test_with_modofiers(); 149 | test_with_modofiers(); 150 | test_with_modofiers(); 151 | test_with_modofiers(); 152 | 153 | test_with_modofiers(); 154 | test_with_modofiers(); 155 | test_with_modofiers(); 156 | test_with_modofiers(); 157 | test_with_modofiers(); 158 | test_with_modofiers(); 159 | test_with_modofiers(); 160 | 161 | test_with_modofiers(); 162 | test_with_modofiers(); 163 | test_with_modofiers(); 164 | test_with_modofiers(); 165 | test_with_modofiers(); 166 | test_with_modofiers(); 167 | test_with_modofiers(); 168 | 169 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES 170 | test_with_modofiers(); 171 | test_with_modofiers(); 172 | test_with_modofiers(); 173 | test_with_modofiers(); 174 | test_with_modofiers(); 175 | test_with_modofiers(); 176 | test_with_modofiers(); 177 | test_with_modofiers(); 178 | test_with_modofiers(); 179 | test_with_modofiers(); 180 | #endif 181 | } 182 | 183 | template 184 | static void test_storing_nonstoring_modifiers_templ() { 185 | using namespace boost::typeindex; 186 | 187 | type_index t1 = type_id_with_cvr(); 188 | type_index t2 = type_id(); 189 | 190 | BOOST_TEST_EQ(t2, t1); 191 | BOOST_TEST_EQ(t1, t2); 192 | BOOST_TEST(t1 <= t2); 193 | BOOST_TEST(t1 >= t2); 194 | BOOST_TEST(t2 <= t1); 195 | BOOST_TEST(t2 >= t1); 196 | 197 | BOOST_TEST_EQ(t2.pretty_name(), t1.pretty_name()); 198 | } 199 | 200 | void type_id_storing_modifiers_vs_nonstoring() 201 | { 202 | test_storing_nonstoring_modifiers_templ(); 203 | test_storing_nonstoring_modifiers_templ(); 204 | test_storing_nonstoring_modifiers_templ(); 205 | 206 | boost::typeindex::type_index t1 = boost::typeindex::type_id_with_cvr(); 207 | boost::typeindex::type_index t2 = boost::typeindex::type_id(); 208 | BOOST_TEST_NE(t2, t1); 209 | BOOST_TEST(t1.pretty_name() == "const int" || t1.pretty_name() == "int const"); 210 | } 211 | 212 | void type_index_stream_operator_via_stringstream_testing() 213 | { 214 | using namespace boost::typeindex; 215 | 216 | { 217 | std::ostringstream oss; 218 | oss << type_id(); 219 | BOOST_TEST_EQ(oss.str(), "int"); 220 | } 221 | { 222 | std::ostringstream oss; 223 | oss << type_id(); 224 | BOOST_TEST_EQ(oss.str(), "double"); 225 | } 226 | } 227 | 228 | void type_index_stripping_cvr_test() 229 | { 230 | using namespace boost::typeindex; 231 | 232 | BOOST_TEST_EQ(type_id(), type_id()); 233 | BOOST_TEST_EQ(type_id(), type_id()); 234 | BOOST_TEST_EQ(type_id(), type_id()); 235 | 236 | BOOST_TEST_EQ(type_id(), type_id()); 237 | BOOST_TEST_EQ(type_id(), type_id()); 238 | BOOST_TEST_EQ(type_id(), type_id()); 239 | 240 | 241 | BOOST_TEST_EQ(type_id(), type_id()); 242 | BOOST_TEST_EQ(type_id(), type_id()); 243 | BOOST_TEST_EQ(type_id(), type_id()); 244 | 245 | BOOST_TEST_EQ(type_id(), type_id()); 246 | BOOST_TEST_EQ(type_id(), type_id()); 247 | BOOST_TEST_EQ(type_id(), type_id()); 248 | } 249 | 250 | 251 | void type_index_user_defined_class_test() 252 | { 253 | using namespace boost::typeindex; 254 | 255 | BOOST_TEST_EQ(type_id(), type_id()); 256 | BOOST_TEST_EQ(type_id(), type_id()); 257 | 258 | #ifndef BOOST_NO_RTTI 259 | BOOST_TEST(type_id() == typeid(my_namespace1::my_class)); 260 | BOOST_TEST(type_id() == typeid(my_namespace2::my_class)); 261 | BOOST_TEST(typeid(my_namespace1::my_class) == type_id()); 262 | BOOST_TEST(typeid(my_namespace2::my_class) == type_id()); 263 | #endif 264 | 265 | BOOST_TEST_NE(type_id(), type_id()); 266 | BOOST_TEST_NE( 267 | type_id().pretty_name().find("my_namespace1::my_class"), 268 | std::string::npos); 269 | } 270 | 271 | 272 | 273 | 274 | 275 | struct A { 276 | public: 277 | BOOST_TYPE_INDEX_REGISTER_CLASS 278 | virtual ~A(){} 279 | }; 280 | 281 | struct B: public A { 282 | BOOST_TYPE_INDEX_REGISTER_CLASS 283 | }; 284 | 285 | struct C: public B { 286 | BOOST_TYPE_INDEX_REGISTER_CLASS 287 | }; 288 | 289 | void comparators_type_id_runtime() 290 | { 291 | C c1; 292 | B b1; 293 | A* pc1 = &c1; 294 | A& rc1 = c1; 295 | A* pb1 = &b1; 296 | A& rb1 = b1; 297 | 298 | #ifndef BOOST_NO_RTTI 299 | BOOST_TEST(typeid(rc1) == typeid(*pc1)); 300 | BOOST_TEST(typeid(rb1) == typeid(*pb1)); 301 | 302 | BOOST_TEST(typeid(rc1) != typeid(*pb1)); 303 | BOOST_TEST(typeid(rb1) != typeid(*pc1)); 304 | 305 | BOOST_TEST(typeid(&rc1) == typeid(pb1)); 306 | BOOST_TEST(typeid(&rb1) == typeid(pc1)); 307 | #else 308 | BOOST_TEST(boost::typeindex::type_index(pc1->boost_type_index_type_id_runtime_()).raw_name()); 309 | #endif 310 | 311 | BOOST_TEST_EQ(boost::typeindex::type_id_runtime(rc1), boost::typeindex::type_id_runtime(*pc1)); 312 | BOOST_TEST_EQ(boost::typeindex::type_id(), boost::typeindex::type_id_runtime(*pc1)); 313 | BOOST_TEST_EQ(boost::typeindex::type_id_runtime(rb1), boost::typeindex::type_id_runtime(*pb1)); 314 | BOOST_TEST_EQ(boost::typeindex::type_id(), boost::typeindex::type_id_runtime(*pb1)); 315 | 316 | BOOST_TEST_NE(boost::typeindex::type_id_runtime(rc1), boost::typeindex::type_id_runtime(*pb1)); 317 | BOOST_TEST_NE(boost::typeindex::type_id_runtime(rb1), boost::typeindex::type_id_runtime(*pc1)); 318 | 319 | #ifndef BOOST_NO_RTTI 320 | BOOST_TEST_EQ(boost::typeindex::type_id_runtime(&rc1), boost::typeindex::type_id_runtime(pb1)); 321 | BOOST_TEST_EQ(boost::typeindex::type_id_runtime(&rb1), boost::typeindex::type_id_runtime(pc1)); 322 | 323 | BOOST_TEST(boost::typeindex::type_id_runtime(rc1) == typeid(*pc1)); 324 | BOOST_TEST(boost::typeindex::type_id_runtime(rb1) == typeid(*pb1)); 325 | 326 | BOOST_TEST(boost::typeindex::type_id_runtime(rc1) != typeid(*pb1)); 327 | BOOST_TEST(boost::typeindex::type_id_runtime(rb1) != typeid(*pc1)); 328 | BOOST_TEST(boost::typeindex::type_id_runtime(&rc1) == typeid(pb1)); 329 | BOOST_TEST(boost::typeindex::type_id_runtime(&rb1) == typeid(pc1)); 330 | #endif 331 | } 332 | 333 | 334 | #ifndef BOOST_NO_RTTI 335 | 336 | void comparators_type_id_vs_type_info() 337 | { 338 | using namespace boost::typeindex; 339 | type_index t_int = type_id(); 340 | 341 | BOOST_TEST(t_int == typeid(int)); 342 | BOOST_TEST(typeid(int) == t_int); 343 | BOOST_TEST(t_int <= typeid(int)); 344 | BOOST_TEST(typeid(int) <= t_int); 345 | BOOST_TEST(t_int >= typeid(int)); 346 | BOOST_TEST(typeid(int) >= t_int); 347 | 348 | type_index t_double = type_id(); 349 | 350 | BOOST_TEST(t_double == typeid(double)); 351 | BOOST_TEST(typeid(double) == t_double); 352 | BOOST_TEST(t_double <= typeid(double)); 353 | BOOST_TEST(typeid(double) <= t_double); 354 | BOOST_TEST(t_double >= typeid(double)); 355 | BOOST_TEST(typeid(double) >= t_double); 356 | 357 | if (t_double < t_int) { 358 | BOOST_TEST(t_double < typeid(int)); 359 | BOOST_TEST(typeid(double) < t_int); 360 | BOOST_TEST(typeid(int) > t_double); 361 | BOOST_TEST(t_int > typeid(double)); 362 | 363 | 364 | BOOST_TEST(t_double <= typeid(int)); 365 | BOOST_TEST(typeid(double) <= t_int); 366 | BOOST_TEST(typeid(int) >= t_double); 367 | BOOST_TEST(t_int >= typeid(double)); 368 | } else { 369 | BOOST_TEST(t_double > typeid(int)); 370 | BOOST_TEST(typeid(double) > t_int); 371 | BOOST_TEST(typeid(int) < t_double); 372 | BOOST_TEST(t_int < typeid(double)); 373 | 374 | 375 | BOOST_TEST(t_double >= typeid(int)); 376 | BOOST_TEST(typeid(double) >= t_int); 377 | BOOST_TEST(typeid(int) <= t_double); 378 | BOOST_TEST(t_int <= typeid(double)); 379 | } 380 | 381 | } 382 | 383 | #endif // BOOST_NO_RTTI 384 | 385 | int main() { 386 | names_matches_type_id(); 387 | default_construction(); 388 | copy_construction(); 389 | comparators_type_id(); 390 | hash_code_type_id(); 391 | 392 | type_id_storing_modifiers(); 393 | type_id_storing_modifiers_vs_nonstoring(); 394 | type_index_stream_operator_via_stringstream_testing(); 395 | type_index_stripping_cvr_test(); 396 | type_index_user_defined_class_test(); 397 | 398 | comparators_type_id_runtime(); 399 | #ifndef BOOST_NO_RTTI 400 | comparators_type_id_vs_type_info(); 401 | #endif 402 | 403 | return boost::report_errors(); 404 | } 405 | 406 | -------------------------------------------------------------------------------- /include/boost/type_index/detail/compile_time_type_info.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2012-2025 Antony Polukhin. 3 | // 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP 10 | #define BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP 11 | 12 | /// \file compile_time_type_info.hpp 13 | /// \brief Contains helper macros and implementation details of boost::typeindex::ctti_type_index. 14 | /// Not intended for inclusion from user's code. 15 | 16 | #include 17 | 18 | #if !defined(BOOST_TYPE_INDEX_INTERFACE_UNIT) 19 | #include 20 | #include 21 | #endif 22 | 23 | #ifdef BOOST_HAS_PRAGMA_ONCE 24 | # pragma once 25 | #endif 26 | 27 | /// @cond 28 | #if defined(__has_builtin) 29 | #if __has_builtin(__builtin_constant_p) 30 | #define BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT(x) __builtin_constant_p(x) 31 | #endif 32 | #if __has_builtin(__builtin_strcmp) 33 | #define BOOST_TYPE_INDEX_DETAIL_BUILTIN_STRCMP(str1, str2) __builtin_strcmp(str1, str2) 34 | #endif 35 | #elif defined(__GNUC__) 36 | #define BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT(x) __builtin_constant_p(x) 37 | #define BOOST_TYPE_INDEX_DETAIL_BUILTIN_STRCMP(str1, str2) __builtin_strcmp(str1, str2) 38 | #endif 39 | 40 | /// @endcond 41 | 42 | 43 | namespace boost { namespace typeindex { namespace detail { 44 | struct ctti_skip { 45 | std::size_t size_at_begin; 46 | std::size_t size_at_end; 47 | const char* until_runtime; 48 | std::size_t until_runtime_length; 49 | }; 50 | 51 | template 52 | constexpr ctti_skip make_ctti_skip(std::size_t size_at_begin, 53 | std::size_t size_at_end, 54 | bool more_at_runtime, 55 | const char (&until_runtime)[N]) 56 | { 57 | return ctti_skip{size_at_begin, size_at_end, until_runtime, more_at_runtime ? N - 1 : 0}; 58 | } 59 | 60 | template 61 | constexpr ctti_skip make_ctti_skip(std::size_t size_at_begin, 62 | std::size_t size_at_end, 63 | const char (&until_runtime)[N]) 64 | { 65 | return ctti_skip{size_at_begin, size_at_end, until_runtime, N - 1}; 66 | } 67 | 68 | #if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED) 69 | /* Nothing to document. All the macro docs are moved to */ 70 | #elif defined(BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING) 71 | constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING; } 72 | #elif defined(_MSC_VER) && !defined(__clang__) && defined (BOOST_NO_CXX11_NOEXCEPT) 73 | // sizeof("const char *__cdecl boost::detail::ctti<") - 1, sizeof(">::n(void)") - 1 74 | constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(40, 10, ""); } 75 | #elif defined(_MSC_VER) && !defined(__clang__) && !defined (BOOST_NO_CXX11_NOEXCEPT) 76 | // sizeof("const char *__cdecl boost::detail::ctti<") - 1, sizeof(">::n(void) noexcept") - 1 77 | constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(40, 19, ""); } 78 | #elif defined(__clang__) && defined(__APPLE__) 79 | // Someone made __clang_major__ equal to LLVM version rather than compiler version 80 | // on APPLE platform. 81 | // 82 | // Using less efficient solution because there is no good way to detect real version of Clang. 83 | // sizeof("static const char *boost::detail::ctti<") - 1, sizeof("]") - 1, true, "???????????>::n() [T = int" 84 | constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(39, 1, "T = "); } 85 | #elif defined(__clang__) && (__clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ == 0)) 86 | // sizeof("static const char *boost::detail::ctti<") - 1, sizeof(">::n()") - 1 87 | // note: checked on 3.0 88 | constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(39, 6, ""); } 89 | #elif defined(__clang__) && (__clang_major__ >= 4 || (__clang_major__ == 3 && __clang_minor__ > 0)) 90 | // sizeof("static const char *boost::detail::ctti<") - 1, sizeof("]") - 1, true, "int>::n() [T = int" 91 | // note: checked on 3.1, 3.4 92 | constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(39, 1, "T = "); } 93 | #elif defined(__EDG__) && !defined(BOOST_NO_CXX14_CONSTEXPR) 94 | // sizeof("static cha boost::detail::ctti::s() [with I = 40U, T = ") - 1, sizeof("]") - 1 95 | // note: checked on 4.14 96 | constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(58, 1, ""); } 97 | #elif defined(__EDG__) && defined(BOOST_NO_CXX14_CONSTEXPR) 98 | // sizeof("static const char *boost::detail::ctti::n() [with T = ") - 1, sizeof("]") - 1 99 | // note: checked on 4.14 100 | constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(57, 1, ""); } 101 | #elif defined(__GNUC__) && (__GNUC__ < 7) && !defined(BOOST_NO_CXX14_CONSTEXPR) 102 | // sizeof("static constexpr char boost::detail::ctti::s() [with unsigned int I = 0u; } T = ") - 1, sizeof("]") - 1 103 | constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(81, 1, ""); } 104 | #elif defined(__GNUC__) && (__GNUC__ >= 7) && !defined(BOOST_NO_CXX14_CONSTEXPR) 105 | // sizeof("static constexpr char boost::detail::ctti::s() [with unsigned int I = 0; } T = ") - 1, sizeof("]") - 1 106 | constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(80, 1, ""); } 107 | #elif defined(__GNUC__) && defined(BOOST_NO_CXX14_CONSTEXPR) 108 | // sizeof("static const char* boost::detail::ctti::n() [with T = ") - 1, sizeof("]") - 1 109 | constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(57, 1, ""); } 110 | #elif defined(__ghs__) 111 | // sizeof("static const char *boost::detail::ctti::n() [with T = ") - 1, sizeof("]") - 1 112 | constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(57, 1, ""); } 113 | #else 114 | // Deafult code for other platforms... Just skip nothing! 115 | constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(0, 0, ""); } 116 | #endif 117 | 118 | template 119 | BOOST_CXX14_CONSTEXPR inline void assert_compile_time_legths() noexcept { 120 | static_assert( 121 | Condition, 122 | "TypeIndex library is misconfigured for your compiler. " 123 | "Please define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING to correct values. See section " 124 | "'RTTI emulation limitations' of the documentation for more information." 125 | ); 126 | } 127 | 128 | template 129 | BOOST_CXX14_CONSTEXPR inline void failed_to_get_function_name() noexcept { 130 | static_assert( 131 | sizeof(T) && false, 132 | "TypeIndex library could not detect your compiler. " 133 | "Please make the BOOST_TYPE_INDEX_FUNCTION_SIGNATURE macro use " 134 | "correct compiler macro for getting the whole function name. " 135 | "Define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING to correct value after that." 136 | ); 137 | } 138 | 139 | #if defined(BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT) 140 | BOOST_CXX14_CONSTEXPR BOOST_FORCEINLINE bool is_constant_string(const char* str) noexcept { 141 | while (BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT(*str)) { 142 | if (*str == '\0') 143 | return true; 144 | ++str; 145 | } 146 | return false; 147 | } 148 | #endif // defined(BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT) 149 | 150 | template 151 | BOOST_CXX14_CONSTEXPR inline ForwardIterator1 constexpr_search( 152 | ForwardIterator1 first1, 153 | ForwardIterator1 last1, 154 | ForwardIterator2 first2, 155 | ForwardIterator2 last2) noexcept 156 | { 157 | if (first2 == last2) { 158 | return first1; // specified in C++11 159 | } 160 | 161 | while (first1 != last1) { 162 | ForwardIterator1 it1 = first1; 163 | ForwardIterator2 it2 = first2; 164 | 165 | while (*it1 == *it2) { 166 | ++it1; 167 | ++it2; 168 | if (it2 == last2) return first1; 169 | if (it1 == last1) return last1; 170 | } 171 | 172 | ++first1; 173 | } 174 | 175 | return last1; 176 | } 177 | 178 | BOOST_CXX14_CONSTEXPR inline int constexpr_strcmp_loop(const char *v1, const char *v2) noexcept { 179 | while (*v1 != '\0' && *v1 == *v2) { 180 | ++v1; 181 | ++v2; 182 | } 183 | 184 | return static_cast(*v1) - *v2; 185 | } 186 | 187 | BOOST_CXX14_CONSTEXPR inline int constexpr_strcmp(const char *v1, const char *v2) noexcept { 188 | #if !defined(BOOST_NO_CXX14_CONSTEXPR) && defined(BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT) && defined(BOOST_TYPE_INDEX_DETAIL_BUILTIN_STRCMP) 189 | if (boost::typeindex::detail::is_constant_string(v1) && boost::typeindex::detail::is_constant_string(v2)) 190 | return boost::typeindex::detail::constexpr_strcmp_loop(v1, v2); 191 | return BOOST_TYPE_INDEX_DETAIL_BUILTIN_STRCMP(v1, v2); 192 | #elif !defined(BOOST_NO_CXX14_CONSTEXPR) 193 | return boost::typeindex::detail::constexpr_strcmp_loop(v1, v2); 194 | #else 195 | return std::strcmp(v1, v2); 196 | #endif 197 | } 198 | 199 | template 200 | BOOST_CXX14_CONSTEXPR inline const char* skip_begining_runtime(const char* begin) noexcept { 201 | constexpr auto skip_value = detail::skip(); // to have the same `.until_runtime` value in code below 202 | const char* const it = detail::constexpr_search( 203 | begin, begin + ArrayLength, 204 | skip_value.until_runtime, skip_value.until_runtime + skip_value.until_runtime_length 205 | ); 206 | return (it == begin + ArrayLength ? begin : it + skip_value.until_runtime_length); 207 | } 208 | 209 | template 210 | BOOST_CXX14_CONSTEXPR inline const char* skip_begining(const char* begin) noexcept { 211 | detail::assert_compile_time_legths<(ArrayLength > skip().size_at_begin + skip().size_at_end)>(); 212 | return skip().until_runtime_length 213 | ? detail::skip_begining_runtime(begin + skip().size_at_begin) 214 | : begin + skip().size_at_begin 215 | ; 216 | } 217 | 218 | #if !defined(__clang__) && defined(__GNUC__) && !defined(BOOST_NO_CXX14_CONSTEXPR) 219 | template 220 | struct index_seq {}; 221 | 222 | template 223 | struct make_index_sequence_join; 224 | 225 | template 226 | struct make_index_sequence_join, index_seq > { 227 | using type = index_seq; 228 | }; 229 | 230 | template 231 | struct make_index_seq_impl { 232 | using type = typename make_index_sequence_join< 233 | typename make_index_seq_impl::type, 234 | typename make_index_seq_impl::type 235 | >::type; 236 | }; 237 | 238 | template 239 | struct make_index_seq_impl { 240 | using type = index_seq<>; 241 | }; 242 | 243 | template 244 | struct make_index_seq_impl { 245 | using type = index_seq; 246 | }; 247 | 248 | template 249 | struct cstring { 250 | static constexpr unsigned int size_ = sizeof...(C); 251 | static constexpr char data_[size_] = { C... }; 252 | }; 253 | 254 | template 255 | constexpr char cstring::data_[]; 256 | #endif 257 | 258 | }}} // namespace boost::typeindex::detail 259 | 260 | namespace boost { namespace detail { 261 | 262 | /// Noncopyable type_info that does not require RTTI. 263 | /// CTTI == Compile Time Type Info. 264 | /// This name must be as short as possible, to avoid code bloat 265 | template 266 | struct ctti { 267 | 268 | #if !defined(__clang__) && defined(__GNUC__) && !defined(BOOST_NO_CXX14_CONSTEXPR) 269 | //helper functions 270 | template 271 | constexpr static char s() noexcept { // step 272 | constexpr unsigned int offset = 273 | (I >= 10u ? 1u : 0u) 274 | + (I >= 100u ? 1u : 0u) 275 | + (I >= 1000u ? 1u : 0u) 276 | + (I >= 10000u ? 1u : 0u) 277 | + (I >= 100000u ? 1u : 0u) 278 | + (I >= 1000000u ? 1u : 0u) 279 | ; 280 | 281 | #if defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE) 282 | return BOOST_TYPE_INDEX_FUNCTION_SIGNATURE[I + offset]; 283 | #elif defined(__FUNCSIG__) 284 | return __FUNCSIG__[I + offset]; 285 | #else 286 | return __PRETTY_FUNCTION__[I + offset]; 287 | #endif 288 | } 289 | 290 | template 291 | constexpr static const char* impl(::boost::typeindex::detail::index_seq ) noexcept { 292 | return ::boost::typeindex::detail::cstring()...>::data_; 293 | } 294 | 295 | template // `D` means `Dummy` 296 | constexpr static const char* n() noexcept { 297 | #if defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE) 298 | constexpr unsigned int size = sizeof(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE); 299 | #elif defined(__FUNCSIG__) 300 | constexpr unsigned int size = sizeof(__FUNCSIG__); 301 | #elif defined(__PRETTY_FUNCTION__) \ 302 | || defined(__GNUC__) \ 303 | || (defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x5130)) \ 304 | || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) \ 305 | || (defined(__ICC) && (__ICC >= 600)) \ 306 | || defined(__ghs__) \ 307 | || defined(__DMC__) 308 | constexpr unsigned int size = sizeof(__PRETTY_FUNCTION__); 309 | #else 310 | boost::typeindex::detail::failed_to_get_function_name(); 311 | #endif 312 | 313 | boost::typeindex::detail::assert_compile_time_legths< 314 | (size > boost::typeindex::detail::skip().size_at_begin + boost::typeindex::detail::skip().size_at_end + sizeof("const *") - 1) 315 | >(); 316 | static_assert(!boost::typeindex::detail::skip().until_runtime_length, "Skipping for GCC in C++14 mode is unsupported"); 317 | 318 | using idx_seq = typename boost::typeindex::detail::make_index_seq_impl< 319 | boost::typeindex::detail::skip().size_at_begin, 320 | size - sizeof("const *") + 1 - boost::typeindex::detail::skip().size_at_begin 321 | >::type; 322 | return impl(idx_seq()); 323 | } 324 | #else 325 | /// Returns raw name. Must be as short, as possible, to avoid code bloat 326 | BOOST_CXX14_CONSTEXPR static const char* n() noexcept { 327 | #if defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE) 328 | return boost::typeindex::detail::skip_begining< sizeof(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE) >(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE); 329 | #elif defined(__FUNCSIG__) 330 | return boost::typeindex::detail::skip_begining< sizeof(__FUNCSIG__) >(__FUNCSIG__); 331 | #elif defined(__PRETTY_FUNCTION__) \ 332 | || defined(__GNUC__) \ 333 | || (defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x5130)) \ 334 | || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) \ 335 | || (defined(__ICC) && (__ICC >= 600)) \ 336 | || defined(__ghs__) \ 337 | || defined(__DMC__) \ 338 | || defined(__clang__) 339 | return boost::typeindex::detail::skip_begining< sizeof(__PRETTY_FUNCTION__) >(__PRETTY_FUNCTION__); 340 | #else 341 | boost::typeindex::detail::failed_to_get_function_name(); 342 | return ""; 343 | #endif 344 | } 345 | #endif 346 | }; 347 | 348 | }} // namespace boost::detail 349 | 350 | 351 | 352 | #endif // BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP 353 | --------------------------------------------------------------------------------