Compare commits

...

245 Commits

Author SHA1 Message Date
bdfd7b91c2 Rework as esp-idf component 2023-11-23 17:17:05 +01:00
cca370a918 update copyright years 2022-01-30 15:01:13 +03:00
97fc5b9838 do not use depth 1 for checkouts in CI 2021-09-20 21:56:00 +03:00
0cc169ecd6 modernize CI setup 2021-09-11 18:18:54 +03:00
a3c6a957ee Update CMakeLists.txt 2021-06-10 00:48:35 +03:00
04cc1734ef use HTTPS links in Readme 2021-04-27 11:22:44 +03:00
f395836779 gather coverage in CI from more platforms 2021-04-24 21:53:20 +03:00
4f51b1f4eb update Readme with new CI links and new doc links, do not gather coverage twice, remove drone 2021-04-24 18:53:27 +03:00
a2ef72c907 CI updates: proper setup of clang-7 and restore sanitizers for gcc-10 2021-04-24 14:28:28 +03:00
331c26760e Use clang-7 in CI instead of clang-3.8; do not sanitize with GCC-10 2021-04-24 14:20:46 +03:00
d6d07a8ce8 add missing include and do not tests on clang-3.7 2021-04-24 13:49:52 +03:00
4468903f8f modernize CI 2021-04-24 12:47:19 +03:00
88c5d9a998 fix broken link 2021-04-24 12:46:59 +03:00
f0b87ea7d3 Merge pull request #35 from sdarwin/githubactions
GitHub Actions config
2021-04-18 14:10:35 +03:00
03794d6144 Add GitHub Actions config [ci skip] 2021-03-04 18:22:58 +00:00
62154d3b19 Merge pull request #33 from sdarwin/drone
Drone config
2021-01-27 10:29:41 +03:00
b4014f385d Merge pull request #32 from eldiener/develop
[skip ci] Add "cxxstd" json field
2021-01-27 10:25:31 +03:00
0dc42bab8f add drone config [ci skip] 2021-01-26 15:29:49 +00:00
a4726d239f [skip ci] Add "cxxstd" json field. The "cxxstd" json field is being added to each Boost library's meta json information for libraries in order to specify the minumum C++ standard compilation level. The value of this field matches one of the values for 'cxxstd' in Boost.Build. The purpose of doing this is to provide information for the Boost website documentation for each library which will specify the minimum C++ standard compilation that an end-user must employ in order to use the particular library. This will aid end-users who want to know if they can successfully use a Boost library based on their C++ compiler's compilation level, without having to search the library's documentation to find this out. 2021-01-21 16:26:02 -05:00
f40f4731e1 Merge github.com:apolukhin/type_index into develop 2021-01-04 18:29:36 +03:00
754fb0f348 CI fix attempt (1) 2021-01-04 13:32:09 +03:00
6fa4f57e7d CI fix attempt 2021-01-04 13:23:42 +03:00
c79f1c8d5d Specify address model for MSVC
Relates boostorg/build#659
2021-01-04 11:04:54 +03:00
843ee6848b update copyright years 2021-01-03 20:01:31 +03:00
6fc5b35b00 Merge pull request #31 from sdarwin/lcov
update .travis.yml to correct lcov error messages
2021-01-03 12:49:28 +03:00
84d68f32e2 update lcov in .travis.yml 2020-12-31 00:51:49 +00:00
1dacdb561e Merge pull request #29 from Kojoley/cease-dependence-on-smart_ptr
Cease dependence on SmartPtr
2020-08-27 12:03:36 +03:00
9862011b6b CI fixes 2020-07-06 11:36:48 +03:00
321749796e Cease dependence on SmartPtr
by forward declaring `boost::shared_ptr`
2020-05-26 02:56:12 +03:00
f2e395a7f3 update copyright years 2020-01-22 23:26:24 +03:00
9936c31851 Attempt to fix CI 2019-11-12 09:00:57 +03:00
560c7d2ef6 Change header file to include 2019-11-11 20:56:04 +03:00
bf33e63feb CI fixes 2019-11-11 18:47:46 +03:00
2152466531 CI fixes 2019-08-29 19:12:02 +03:00
389f621450 CI + inspect tool fixes 2019-08-29 16:00:48 +03:00
0b65c1a8d8 Disable some of the inspect tool checks 2019-08-28 20:59:16 +03:00
216c21b728 Fix issues found by inspect too and add it to CI 2019-08-28 17:54:46 +03:00
afd1b6cdc8 Merge pull request #28 from Breakthrough/develop
Add CTTI name prettifying for GHS C++ compiler.
2019-03-02 11:33:11 +03:00
d69a8a211b Add CTTI name prettifying for GHS C++ compiler. 2019-02-28 12:33:14 -05:00
ebe74ba4ba Merge pull request #27 from Mike-Devel/min_cmake
[CMake] Add minimal cmake file
2019-02-20 21:27:23 -10:00
ac4fec435f [CMake] Add minimal cmake support
CMake file only supports add_subdirectory workflow.
No installation and no unit tests.
2019-02-14 17:32:53 +01:00
f68d6dc073 update copyrights 2019-01-17 22:45:35 +03:00
85f43ece0d Merge remote-tracking branch 'lastique/optimize_ctti_strcmp' into develop 2018-12-23 12:24:16 +03:00
a2de6a56f3 Merge pull request #26 from boostorg/feature/ci-update
CI update: Better CI with many new platforms
2018-12-16 20:15:14 +03:00
c585d74669 Disable part of the tests for _MSC_VER == 1916 and below 2018-12-16 11:55:04 +03:00
32909cb25a fixes for tests 2018-12-16 11:30:59 +03:00
7af1661709 Fixes for travis CI 2018-12-15 22:06:18 +03:00
351cedf404 ADjust sanitizers in CI builds 2018-12-15 21:26:25 +03:00
098c84481e Merge branch 'develop' into feature/ci-update 2018-12-15 16:33:40 +03:00
d9d13b9574 ci update 2018-12-14 11:56:02 +03:00
44ca756e32 Merge pull request #25 from boostorg/pr/ctti-clang-win
Fix compile_time_type_info for clang-cl
2018-11-16 11:15:15 +03:00
acb536a67e Fix compile_time_type_info for clang-cl 2018-11-16 02:06:10 +02:00
7654c26594 Increase MSVC requirements for constexpr sorted test (refs #24) 2018-11-16 01:58:18 +03:00
075b3682ae Disable constexpr sort test for MSVC <= 1914 (refs #24) 2018-11-15 21:58:17 +03:00
a60e25a74d Better diagnostics for missing PRETTY_FUNCTION macro (refs #24) 2018-11-14 09:09:37 +03:00
cd1c905f87 Optimize string comparison used to implement CTTI comparison.
When the strings are known to be runtime objects, use compiler builtin
for strcmp for comparing strings. The compiler will generate a runtime
call for the (presumably, well-optimized) strcmp instead of rolling
a local per-character comparison loop. When the builtin is not available
or we cannot detect compile-time strings, use the local loop as before.

Also, when C++14 constexpr is not available, use strcmp right away,
since there is no use for the local loop in this case.
2018-10-28 02:56:30 +03:00
f3da852bca Update stl_type_index.hpp 2018-10-20 20:19:04 +03:00
a8fafd93f9 Merge pull request #21 from Kojoley/do-not-include-container-hash-if-possible
Do not include container_hash if possible
2018-10-20 20:12:07 +03:00
01944bf377 Do not include container_hash if possible
The `boost/container_hash/hash.hpp` has significant inclusion times.
Not including it results in 30% faster `boost/type_traits.hpp` parsing.
(kind of regression introduced in 82ed016577)
2018-10-20 19:59:20 +03:00
09f0bc23c5 fix b2 warnings 2018-09-22 22:13:42 +03:00
718af3e8dc Fix tests which did not return report_errors() 2018-09-17 07:43:19 -04:00
c9c1412a05 Tests to reproduce the track issue 13621 2018-07-28 17:44:17 +03:00
c2caa340ab Merge pull request #19 from jlapolla-cray/edg-ctti-support
CTTI parameters for EDG based compilers
2018-04-15 12:48:26 +03:00
da0a181117 ctti parameters for EDG based compilers
- Needed for Cray Compiling Environment to work with Boost.TypeIndex.
2018-04-10 09:19:22 -05:00
be9f5a4b9b Droped dependency on MPL 2018-03-24 09:50:37 +03:00
bd19ed1a87 Disable link-fail tests and restore MinGW CI 2018-01-23 10:40:56 +03:00
727cdadc86 Restore link-fail 2018-01-16 01:21:20 +03:00
5bc4f54183 Dropped -fail to check the MSVC builds 2018-01-16 01:10:28 +03:00
918e59c109 One more fix in tests for /GR- flag 2018-01-16 00:44:11 +03:00
cd659212aa Workaround for /GR- override in tests 2018-01-16 00:28:48 +03:00
70e51a62e9 Workaround for /GR- override that disables link time assertions 2018-01-15 23:21:34 +03:00
05feacf14b Relax comparing_anonymous_types_between_modules test as it was failing to too many builds (fixes #17) 2018-01-15 00:14:47 +03:00
82ed016577 Use hash_fwd header and use new paths to boost::hash* 2018-01-14 23:41:33 +03:00
1a7226bc0f Do not define BOOST_TEST_*E macros, as they are now defined in boost/core/lightweight_test.hpp 2017-10-01 22:30:59 +03:00
be08eda196 Do not suppress already suppressed warnings 2017-09-26 22:05:57 +03:00
baa5019c90 Merge pull request #16 from bebuch/develop
fix ctti_type_index for GCC 7
2017-07-29 20:13:04 +03:00
4585bab3c3 __PRETTY_FUNCTION__ is slightly different in GCC 7
The output of an unsigned int literal dosn't contain the u anymore.

	#include <iostream>

	template < typename T >
	struct ctti{
		template < unsigned int D = 1 >
		static constexpr auto name()noexcept{
			return __PRETTY_FUNCTION__;
		}
	};

	int main(){
		using ctti = ctti< int >;
		std::cout << ctti::name() << '\n';
	}
2017-07-28 15:07:19 +02:00
93e7b2458b Fixed some warnings 2017-06-25 14:05:08 +03:00
09ac338acc Fix compiler warnings about unused initialized variables, and unused formal parameters
Signed-off-by: Daniela Engert <dani@ngrt.de>
2017-06-08 19:05:02 +02:00
b0737f4169 Fix formatting in README 2017-05-18 22:51:47 +03:00
be74716251 Use native hash_code() when possible on GCC-like compilers 2017-05-18 22:50:25 +03:00
f82eab8882 Merge pull request #15 from ecatmur/ecatmur-stl-hash
Include <boost/functional/hash.hpp> if required
2017-05-06 10:26:30 +03:00
af61d6b8ed Merge pull request #13 from cdglove/split_register_and_implement
Add support for using runtime_cast without requiring type_id_runtime.
2017-02-28 05:33:07 +04:00
d3d4e8d18a Change runtime cast test to use the separated macro (BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST) and add a new test that ensures BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS does indeed supply both functions. 2017-02-25 15:35:34 -05:00
7f8af2a6e9 Merge branch 'develop' into split_register_and_implement 2017-02-25 13:19:16 -05:00
342d835289 Run MinGW tests too (thanks to Pavel Filinov for showing that appveyor apability) 2017-02-23 21:35:40 +03:00
5cacb67510 Make it derived class responsibility to include <boost/functional/hash.hpp> 2017-02-16 21:55:12 +00:00
f2616bcd17 Correct preprocessor condition to match below 2017-02-16 16:30:52 +00:00
8c582362d0 Include <boost/functional/hash.hpp> if required 2017-02-16 16:18:48 +00:00
f71d9eb3f2 Fix undefined macro warning (trac 12739) 2017-01-18 22:33:13 +03:00
cfcdcd647d Update CI script version 2016-12-04 02:39:22 +03:00
8bee2f6939 Fix coverage info gathering in travisCI script for GCC-6 2016-12-04 02:29:02 +03:00
40985de221 Update CI scripts and tests 2016-11-18 22:31:01 +03:00
d8bdbad2ec Add BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST, which implementes the functionality for runtime_cast to function, but does not include the BOOST_TYPE_INDEX_REGISTER_CLASS macro.
Reimplement BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS to simply call BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST and BOOST_TYPE_INDEX_REGISTER_CLASS.

This allows users to opt-in to one or the other, instead of forcing them to generate both virtual functions.
2016-11-05 16:04:13 -04:00
c52fdfe30c Add, and update, documentation build targets. 2016-10-07 23:07:37 -05:00
7f840c882e Fix build in C++98 mode 2016-10-02 10:39:54 +03:00
b669f0244e Changed std::size_t to unsigned int in compile_time_type_infohelpers. Now the code is more platform independant. 2016-10-02 10:32:50 +03:00
d656e1879a Merge pull request #12 from cdglove/runtime_cast_test_fixes
Cleanup of shared_ptr ifdef.
2016-10-02 10:58:49 +04:00
b1ed011b6e Cleaner removal of std::shared_ptr tests on compilers without C++11 shared_ptr 2016-10-01 14:49:28 -04:00
4d1cf425e0 Merge pull request #11 from cdglove/runtime_cast_test_fixes
Runtime cast test fixes
2016-09-30 21:34:10 +04:00
d6ca24ff3c Merge branch 'runtime_cast' into runtime_cast_test_fixes 2016-09-29 22:31:07 -04:00
4459af9532 FIx a unit test so that the NULL check happens before the dereference. 2016-09-29 22:29:35 -04:00
b61a7423b7 Update unit test to remove shared_ptr on compilers less than C++11. 2016-09-29 22:29:10 -04:00
1a918009fd Fix comment. 2016-09-29 22:27:10 -04:00
045ab1d779 Merge pull request #8 from cdglove/runtime_cast
Add the concept of runtime_cast to type index as an emulation of dynamic_cast..
2016-09-29 00:45:39 +04:00
6cf5288a8c Merge pull request #9 from efcs/clang-4-fix
Support Clang version 4.0.
2016-08-30 22:43:14 +04:00
4453acf867 Support Clang 4.0 and newer 2016-08-29 22:10:34 -06:00
b6b23bad3a Cleanup line endings, file endings, some spacing etc. 2016-08-21 12:47:44 -04:00
3bb646d19b - Use boost::addressof instead of &
- Remove nullptr from test
- add boost::typeindex::bad_runtime_cast, remove std::bad_cast
2016-08-21 11:01:26 -04:00
9cd218bbc4 Add missing include to example. 2016-08-19 18:42:22 -04:00
ad26256d09 Initial documentation. 2016-08-11 10:31:16 -04:00
5af925602e Invoke smart_ptr tests. 2016-08-10 10:06:41 -04:00
2fb667a6a0 Experiment with a version of runtime_cast that has only a single registration macro. 2016-08-09 23:13:54 -04:00
12751e0f83 Split runtime_cast into several files so clients can selectively include only what they use.
Add support for shared_ptrs.
2016-08-09 14:51:36 -04:00
0b006b6af6 Remove all references to std::type_traits
Replace variadic template with boost preprocessor.
2016-08-08 12:16:58 -04:00
76cae485cb Merge branch 'runtime_cast' of github.com:cdglove/type_index into runtime_cast
# Conflicts:
#	include/boost/type_index/runtime_cast.hpp
#	test/runtime_cast_test.cpp
2016-07-15 17:18:42 -04:00
ee7b15a493 First version.
TODO: Error messages when using mismatched types are not clear. Needs consideration.
2016-07-15 16:30:16 -04:00
1dc8310826 Optimization: Don't check all bases. 2016-07-15 10:10:07 -04:00
b230140529 First version. 2016-07-15 08:49:54 -04:00
31ec1d2524 Fix link in README 2016-06-05 13:02:56 +03:00
40e9bd336a Test on same Boost branch when running Appveyor 2016-06-04 21:10:20 +03:00
767c724983 README now shows build status on Windows platform 2016-06-04 15:59:29 +03:00
24708cc109 One more example and integrate examples into the docs 2016-03-30 23:24:53 +03:00
57205874ae Added namespace detection example 2016-03-30 22:28:53 +03:00
1b4a85764f Fixing test under Windows 2016-03-29 23:16:17 +03:00
1976355e8f appveyor update 1 2016-03-29 22:36:12 +03:00
0efc48e16c Add appveyor integration and increment minor version of the library 2016-03-29 21:45:50 +03:00
e96a6e8f80 Use constexpr in documentation 2016-03-29 21:38:46 +03:00
8e3466ece5 Log(N) complexity and templates depth in make_index_seq_impl, avoid usage of slow sizeof...(I), workaround GCC ICE in constexpr tests 2016-03-29 21:21:04 +03:00
8b6c3facb3 Fixes and GCC related improvements 2016-03-28 22:42:39 +03:00
ffb98af0dd Attempt to use libc++ in TravisCi tests no. 6 2016-03-27 22:05:40 +03:00
9122022faf Attempt to use libc++ in TravisCi tests no. 5 2016-03-27 21:50:33 +03:00
18dbaea6ee Attempt to use libc++ in TravisCi tests no. 4 2016-03-27 21:42:08 +03:00
6dabf11504 Third attempt to use libc++ in TravisCi tests 2016-03-27 21:32:18 +03:00
7bd788c5d7 Second attempt to use libc++ in TravisCi tests 2016-03-27 21:27:10 +03:00
2d87bc6194 Attempt to use libc++ in travisCi tests 2016-03-27 18:38:08 +03:00
36efa3969b Use the cstring workaround only for GCC 2016-03-27 14:46:27 +03:00
551535f8cf Dropped the using syntax 2016-03-26 16:43:22 +03:00
3f004511a2 Do not use decltype 2016-03-26 16:24:51 +03:00
30bb93bd23 Test on clang too 2016-03-26 16:01:42 +03:00
7f2b9fd31a Combine klemens-morgenstern ideas with mine. Must compile and work at least on GCC-5 2016-03-26 15:49:09 +03:00
c9f1370d0c Merge tests from klemens-morgenstern 2016-03-25 21:34:30 +03:00
1ec4460244 Merge .travis.yml from klemens-morgenstern 2016-03-25 21:26:47 +03:00
1ed55a2f12 Merge branch 'constexpr14' of github.com:boostorg/type_index into constexpr14 2016-03-25 21:16:21 +03:00
1c685fa119 Initial C++14 constexpr version of ctti_type_index. No ABI breakage 2016-03-25 21:15:52 +03:00
37484c19ec Merge pull request #5 from klemens-morgenstern/develop
FIxed space removal
2016-02-13 23:50:45 +03:00
bb02f97414 Merge remote-tracking branch 'remotes/fork/develop' into develop 2016-02-13 19:12:19 +01:00
b9db462091 fixed length with noexcept 2016-02-13 19:11:04 +01:00
cf4f09b520 Merge branch 'develop' of https://github.com/boostorg/type_index into develop 2016-02-13 19:09:13 +01:00
5de7f5def6 added comparison test 2016-02-13 19:08:59 +01:00
1c8190cc62 FIxed space removal
I only tested that with templates, the space removal was too much.

I'll add a test for that, sry.
2016-02-13 18:52:29 +01:00
6ff2a75da3 Merge pull request #4 from klemens-morgenstern/develop
added in variant for MSVC with noexcept
2016-02-13 19:48:26 +03:00
58b0f69e52 added in variant for MSVC with noexcept 2016-02-12 10:00:44 +01:00
478da3512a Merge pull request #7 from norbertwenzel/develop
fixed two typos in documentation
2016-01-28 22:51:50 +03:00
a373a4c7ed fixed two typos in documentation 2016-01-27 20:13:40 +01:00
34835b90e3 Ignore tests coverage for unrelated libraries 2016-01-05 16:49:41 +03:00
236fdc8dba Update .travisci to use non-sudo approach 2016-01-05 16:39:43 +03:00
1ff942f329 Fix old MSVC warning 2015-12-10 20:55:45 +03:00
f58844637c travis fixes 2015-08-22 21:21:46 +03:00
9fede62a7c Fix travis build 2015-08-22 12:55:55 +03:00
48d50ae178 Run TravisCI tests using valgrind 2015-08-22 11:44:54 +03:00
743b2a8851 Initial C++14 constexpr version of ctti_type_index. No ABI breakage 2015-08-01 20:13:38 +03:00
7e2a538eb5 Fixed semicolon warnings 2015-07-30 23:00:41 +03:00
e5e105013a Fix shadow warning for name variable (svn #11503) 2015-07-28 22:53:24 +03:00
d7ec25e56b Use lightweight tests to avoid Boost.Test warnings, RTTI issues and minimize compilation times 2015-06-21 23:16:46 +03:00
c0f75c27fa Avoid warnings in some tests and do more checks 2015-06-18 22:01:45 +03:00
3e6695971d Removed applied patches 2015-06-17 21:54:04 +03:00
8d3127935d Drop dependency to Boost.Functional 2015-04-25 12:44:27 +03:00
d585fc3673 Merge pull request #6 from akumta/patch-1
Update compile_time_type_info.hpp
2015-03-12 16:20:12 +04:00
6b5d2743c5 Update compile_time_type_info.hpp
Update for ticket 11099
2015-03-10 13:44:18 -07:00
8558fd66ef remove the always failing testing_crossmodule_anonymous_no_rtti test from test suite and add notes for users about emulation limitations testing 2014-12-29 16:27:08 +03:00
8ddc5feac4 Updated README.md and added .travis.yml 2014-12-23 14:33:20 +03:00
8b7534889b Merge pull request #5 from MarcelRaad/patch-1
Allow BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY for MSVC
2014-12-17 23:04:38 +03:00
697e09bda9 Allow BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY for MSVC
BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY had no effect for MSVC. With this change, it is treated like BOOST_NO_RTTI also for MSVC.
2014-12-08 18:31:09 +01:00
242d9a0bed Use detect_mismatch pragma when possible (refs #10404 in track) 2014-08-26 14:41:54 +04:00
99f58714d1 Fix a lot of typos [refs #10294](https://svn.boost.org/trac/boost/ticket/10294) 2014-08-02 16:15:00 +04:00
7b04caa160 Fixed problems reported by inspection program 2014-08-01 12:34:34 +04:00
4d221d4f71 Minor changes: added consts and replaced BOOST_THROW_EXCEPTION with throw_exception 2014-06-16 09:42:21 +04:00
806a192df1 Merge pull request #4 from Lastique/patch-1
Thanks a lot!
2014-06-16 09:31:49 +04:00
1633adfee4 Changed implementation to use the low level interface for demangling.
Added a check for demangling errors, an exception is thrown in this case. The new implementation also does not allocate std::string until the parsing completes.
2014-06-12 22:23:48 +04:00
c3a26dff9a Port to Boost.Core demangle()
The port removes some conditional code from pretty_name() implementation. As a side effect, this improves portability (AFAICT, the previous version wouldn't do demangling on clang).

Additionally, the commit fixes a possible buffer overrun if demangle() returns a string equal to cvr_saver_name or cvr_saver_name with trailing spaces.
2014-06-11 23:41:04 +04:00
436ecd0b3e Added Configuration section to the docs and fixed minor issues 2014-06-02 15:56:12 +04:00
9fcbfd18ce Add more -DBOOST_NO_RTTI to Jamfile 2014-05-24 11:42:14 +04:00
1916e2b42f Fixes for Clang+Apple 2014-05-22 17:03:02 +04:00
56bd9b401a Gix a Boost.test another chance, more macro definitions in build scripts 2014-05-22 12:38:32 +04:00
e2c227d4aa Fix a typo and improve macro definitionas in Jamfile 2014-05-21 10:47:30 +04:00
80086cbc4f Do not use Boost.Test at all 2014-05-21 10:33:22 +04:00
0f0902d11c Explicitly define BOOSTNO_RTTI: do not rely on ability of Boost.Config to detect RTTI 2014-05-20 21:26:33 +04:00
6857f23e6f Use minimal subset of Boost.Test and do not depend on ability of Boost.Test to work with rtti off 2014-05-20 21:22:40 +04:00
ce103443fd Merge pull request #3 from danieljames/redirect-fix
Redirect fix
2014-05-20 17:04:45 +04:00
b34d4d466d Fix the documentation redirect location. 2014-05-20 09:01:59 +01:00
441a71c3d1 Merge pull request #2 from danieljames/doc-build-fix
Put the doxygen dependency on the quickbook file, rather than boostbook.
2014-05-20 08:45:39 +04:00
ae946ee496 Put the doxygen dependency on the quickbook file, rather than boostbook.
Because when building the main documentation, the docbook target isn't
being triggered, which is breaking the build. Hopefully this will fix
it.
2014-05-19 23:11:59 +01:00
76dc3d1053 Added index.html 2014-05-19 11:28:27 +04:00
28c77f4036 Merge pull request #1 from danieljames/metadata
Add metadata file
2014-05-19 08:41:15 +04:00
631e592b7a Add metadata file 2014-05-18 23:30:16 +01:00
fa2fa1805c Added always_show_run_output to ctti_print_name test rule 2014-05-14 09:32:34 +04:00
0744f86a2c Simplify the ctti_print_name.cpp 2014-05-13 14:17:42 +04:00
61594ba1da Fix nortti builds on Intel compiler 2014-05-13 12:03:15 +04:00
e2ceb6cf36 Log to std::cerr in ctti_print_name test and implicitly include ctti. Define BOOST_NO_RTTI for nortti test, so that even old compilers could compile tests 2014-05-12 20:11:51 +04:00
a397391b0e Added ctti_print_name.cpp to ensure that BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING macro works 2014-05-11 16:13:12 +04:00
8c8d9c6c69 Simplify redefinition of parsing rules 2014-05-11 03:11:34 +04:00
eac9c8af2f Another attempt to disable table_of_names_no_rtti test 2014-05-08 11:37:09 +04:00
4cc0272bd2 Polished the docs and removed BOOST_TYPE_INDEX_REGISTER_CTTI_CLASS and BOOST_TYPE_INDEX_REGISTER_STL_CLASS as was recommended during review. Moved helper headers to the detail folder. 2014-05-07 20:12:27 +04:00
ecac9ac83c Tune CTTI for different versions of Clang 2014-05-07 16:46:07 +04:00
8a8a3ec639 Fix build script 2014-05-07 16:37:57 +04:00
6931c1de4c Updated docs and removed applied patch 2014-05-07 15:29:52 +04:00
7ba3f29da1 Add ability to do runtime searches in CTTI and fix pretty_name() on clang-3.4 2014-05-07 12:14:00 +04:00
a184f3969f Fixed almost all the notes by Andrey Semashev except link-time assertions and ctti type name assertions 2014-05-06 18:23:26 +04:00
f7388d59b5 Fix some of the notes mentioned by Andrey Semashev (more to come) 2014-05-06 16:27:03 +04:00
2602569bc4 Fixed issueas mentioned by Mathieu Champlon during Boost review 2014-05-06 13:03:59 +04:00
172d4a25ca Fixed issues mentioned by Dominique Devienne during Boost review 2014-05-05 19:49:56 +04:00
6af608a827 Fixed notes mentioned by Klaim - Joël Lamotte during review 2014-05-04 20:28:45 +04:00
5ed8543025 Changed namespace to boost::typeindex 2014-05-04 14:42:12 +04:00
a66ffcfa50 Fixed issues noted by Paul A. Bristow during review 2014-05-04 14:22:25 +04:00
2e11dc75d4 Fix a typo 2014-04-14 18:00:01 +04:00
a2a934dde8 Added test to ensure that alignments of ctti_data and char are same 2014-03-06 11:39:10 +04:00
3f51425f3c Fixed possible UB 2014-03-06 10:32:23 +04:00
501a0a992e Fix typos in docs 2014-03-05 15:12:25 +04:00
b8265cdb4f Minor changes to docs 2014-02-21 17:49:32 +04:00
89398ac07c Added .gitignore 2014-02-21 13:01:05 +04:00
40f6ae1ede Make code thread safe even on antique/broken compilers. Improve examples and add more tests 2014-02-21 12:52:07 +04:00
2ebd172f4e Final cleanup of directory. Patches were updated. Minor bugfixes. 2014-02-20 18:53:05 +04:00
70fdaa633e Fix typo 2014-02-20 16:38:55 +04:00
7ddb306c65 Some MSVC related updates and docs improvements 2014-02-20 16:30:13 +04:00
7488e75a9c Finished example with user defined type_index, improved doocs and refactored some of the functions 2014-02-20 15:36:23 +04:00
b44845b46d Started documenting the user_defined_typeinfo example and embedding it into the docs 2014-02-19 18:54:28 +04:00
0d8c6f36ad Fix typo 2014-02-19 17:31:54 +04:00
98e5bbe6ac Docs improved 2014-02-19 17:22:37 +04:00
276101f1b3 Added example of user defined type index class 2014-02-19 16:20:19 +04:00
ea2e5beabb Allow runtime type info even when RTTI is off. Improve tests and examples 2014-02-19 13:03:12 +04:00
c99b7b26da Sources cleanup and some typo fixes 2014-02-14 16:00:32 +04:00
78824176ea Minor change of interface. Added default constructors. More tests added. Documentation improved 2014-02-14 14:39:09 +04:00
de0d90eca1 More functionality moved to type_index_facade and better documentation for facade. 2014-02-09 14:16:36 +04:00
2ef8924510 Documented some of the classes and features 2014-02-07 17:10:36 +04:00
beaa53f460 Add some examples of how to create type_indexes 2014-02-07 15:08:14 +04:00
0137b9b43f Moved some of the classes from boost::typeind::detail namespace to boost::typeind namespace 2014-02-07 13:41:17 +04:00
683dab93a2 Reimplement and simplify design using type_index_facade class 2014-02-07 13:32:24 +04:00
496ab93589 Reduced header dependencies 2014-02-06 19:00:14 +04:00
c0871ef714 Removed old unused files 2014-02-06 18:46:01 +04:00
2f9c4b7834 Restored all the tests and examples, fixed some issues 2014-02-06 18:42:08 +04:00
c43f8c1cfa Restore some of the tests and fix a bunch of bugs 2014-02-06 17:52:18 +04:00
50d496288f Compile time type info implementation added 2014-02-06 16:53:10 +04:00
3daeab38fa Started the work on new interface 2014-02-06 16:00:27 +04:00
5f97225a18 New project structure to satisfy Modular Boost requirements. 2014-01-11 19:02:05 +04:00
89 changed files with 5207 additions and 3228 deletions

178
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,178 @@
name: CI
on:
pull_request:
push:
branches:
- master
- develop
- feature/**
env:
UBSAN_OPTIONS: print_stacktrace=1
jobs:
posix:
strategy:
fail-fast: false
matrix:
include:
- toolset: gcc-7
cxxstd: "03,11,14,17"
os: ubuntu-18.04
cxxflags: "cxxflags=--coverage"
linkflags: "linkflags=--coverage"
gcov_tool: "gcov-7"
- toolset: gcc-9
cxxstd: "03,11,14,17,2a"
os: ubuntu-18.04
- toolset: gcc-10
cxxstd: "03,11,14,17,2a"
os: ubuntu-18.04
cxxflags: "cxxflags=--coverage -fsanitize=address,leak,undefined -fno-sanitize-recover=undefined"
linkflags: "linkflags=--coverage -lasan -lubsan"
launcher: "testing.launcher=LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libasan.so.6"
gcov_tool: "gcov-10"
- toolset: clang
compiler: clang++-7
cxxstd: "03,11,14,17"
os: ubuntu-18.04
install: clang-7
- toolset: clang
compiler: clang++-10
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
- toolset: clang
cxxstd: "03,11,14,17,2a"
os: macos-10.15
cxxflags: "cxxflags=-fsanitize=address,undefined -fno-sanitize-recover=undefined"
linkflags: "linkflags=-fsanitize=address,undefined"
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v2
- name: Install packages
if: matrix.install
run: sudo apt install ${{matrix.install}}
- name: Setup Boost
run: |
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
LIBRARY=${GITHUB_REPOSITORY#*/}
echo LIBRARY: $LIBRARY
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
echo GITHUB_REF: $GITHUB_REF
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
REF=${REF#refs/heads/}
echo REF: $REF
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
echo BOOST_BRANCH: $BOOST_BRANCH
cd ..
git clone -b $BOOST_BRANCH --depth 10 https://github.com/boostorg/boost.git boost-root
cd boost-root
git submodule update --init --depth 10 --jobs 2 tools/boostdep tools/inspect libs/filesystem
python tools/boostdep/depinst/depinst.py --git_args "--depth 10 --jobs 3" filesystem
rm -rf libs/$LIBRARY/*
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
python tools/boostdep/depinst/depinst.py --include benchmark --include example --include examples --include tools --git_args "--depth 10 --jobs 3" $LIBRARY
./bootstrap.sh
./b2 -d0 headers
./b2 -j4 variant=debug tools/inspect/build
- name: Run tests
run: |
cd ../boost-root
./b2 -j3 libs/$LIBRARY/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} variant=debug,release "${{matrix.cxxflags}}" "${{matrix.linkflags}}" "${{matrix.launcher}}"
dist/bin/inspect libs/$LIBRARY
- name: Prepare coverage data
if: matrix.gcov_tool
run: |
mkdir -p $GITHUB_WORKSPACE/coveralls
echo -e "#!/bin/bash\nexec ${{matrix.gcov_tool}} \"\$@\"" > $GITHUB_WORKSPACE/coveralls/gcov_wrapper.sh
chmod +x $GITHUB_WORKSPACE/coveralls/gcov_wrapper.sh
wget https://github.com/linux-test-project/lcov/archive/v1.15.zip
unzip v1.15.zip
LCOV="`pwd`/lcov-1.15/bin/lcov --gcov-tool $GITHUB_WORKSPACE/coveralls/gcov_wrapper.sh"
echo "$LCOV --directory ../boost-root/bin.v2/libs/$LIBRARY/ --base-directory `pwd`/libs/$LIBRARY/test --capture --output-file $GITHUB_WORKSPACE/coveralls/coverage.info"
$LCOV --directory ../boost-root/bin.v2/libs/$LIBRARY/ --base-directory ../boost-root/ --capture --output-file $GITHUB_WORKSPACE/coveralls/coverage.info
$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
cd ../boost-root
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'`
echo $OTHER_LIBS
eval "$LCOV --remove $GITHUB_WORKSPACE/coveralls/coverage.info $OTHER_LIBS -o $GITHUB_WORKSPACE/coveralls/coverage.info"
- name: Coveralls
uses: coverallsapp/github-action@master
if: matrix.gcov_tool
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: ./coveralls/coverage.info
parallel: true
windows:
strategy:
fail-fast: false
matrix:
include:
- toolset: msvc-14.1
cxxstd: "14,17,latest"
addrmd: 32,64
os: windows-2016
- toolset: msvc-14.2
cxxstd: "14,17,latest"
addrmd: 32,64
os: windows-2019
- toolset: gcc
cxxstd: "03,11,14,17,2a"
addrmd: 64
os: windows-2019
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v2
- name: Setup Boost
shell: cmd
run: |
echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY%
for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi
echo LIBRARY: %LIBRARY%
echo LIBRARY=%LIBRARY%>>%GITHUB_ENV%
echo GITHUB_BASE_REF: %GITHUB_BASE_REF%
echo GITHUB_REF: %GITHUB_REF%
if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF%
set BOOST_BRANCH=develop
for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master
echo BOOST_BRANCH: %BOOST_BRANCH%
cd ..
git clone -b %BOOST_BRANCH% --depth 10 https://github.com/boostorg/boost.git boost-root
cd boost-root
xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\
git submodule update --init tools/boostdep
python tools/boostdep/depinst/depinst.py --include benchmark --include example --include examples --include tools --git_args "--jobs 3" %LIBRARY%
cmd /c bootstrap
b2 -d0 headers
- name: Run tests
shell: cmd
run: |
cd ../boost-root
b2 -j3 libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release
finish:
needs: posix
runs-on: ubuntu-latest
steps:
- name: Coveralls Finished
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.github_token }}
parallel-finished: true

379
.gitignore vendored
View File

@ -1,377 +1,2 @@
# Ignore docs/html directory, that is actually a `gh-pages` branch
/libs/type_index/doc/autodoc.xml
/libs/type_index/doc/html/
# While testing I use this project inside the SVN's /boost/trunk folders
# Follwoing rules ignore all the /boost's files, without ignorng the TypeIndex library
*~
*.svn
/boost/.svn/
/boost/accumulators
/boost/algorithm
/boost/aligned_storage.hpp
/boost/any.hpp
/boost/any.hpp~
/boost/archive
/boost/array.hpp
/boost/asio
/boost/asio.hpp
/boost/assert.hpp
/boost/assign
/boost/assign.hpp
/boost/atomic
/boost/atomic.hpp
/boost/bimap
/boost/bimap.hpp
/boost/bind
/boost/bind.hpp
/boost/blank_fwd.hpp
/boost/blank.hpp
/boost/call_traits.hpp
/boost/cast.hpp
/boost/cerrno.hpp
/boost/checked_delete.hpp
/boost/chrono
/boost/chrono.hpp
/boost/circular_buffer
/boost/circular_buffer_fwd.hpp
/boost/circular_buffer.hpp
/boost/compatibility
/boost/compressed_pair.hpp
/boost/concept
/boost/concept_archetype.hpp
/boost/concept_check
/boost/concept_check.hpp
/boost/config
/boost/config.hpp
/boost/container
/boost/context
/boost/coroutine
/boost/crc.hpp
/boost/cregex.hpp
/boost/cstdint.hpp
/boost/cstdlib.hpp
/boost/current_function.hpp
/boost/date_time
/boost/date_time.hpp
/boost/detail
/boost/dynamic_bitset
/boost/dynamic_bitset_fwd.hpp
/boost/dynamic_bitset.hpp
/boost/enable_shared_from_this.hpp
/boost/exception
/boost/exception_ptr.hpp
/boost/filesystem
/boost/filesystem.hpp
/boost/flyweight
/boost/flyweight.hpp
/boost/foreach_fwd.hpp
/boost/foreach.hpp
/boost/format
/boost/format.hpp
/boost/function
/boost/functional
/boost/functional.hpp
/boost/function_equal.hpp
/boost/function.hpp
/boost/function_output_iterator.hpp
/boost/function_types
/boost/fusion
/boost/generator_iterator.hpp
/boost/geometry
/boost/geometry.hpp
/boost/get_pointer.hpp
/boost/gil
/boost/graph
/boost/heap
/boost/icl
/boost/implicit_cast.hpp
/boost/indirect_reference.hpp
/boost/integer
/boost/integer_fwd.hpp
/boost/integer.hpp
/boost/integer_traits.hpp
/boost/interprocess
/boost/intrusive
/boost/intrusive_ptr.hpp
/boost/io
/boost/io_fwd.hpp
/boost/iostreams
/boost/is_placeholder.hpp
/boost/iterator
/boost/iterator_adaptors.hpp
/boost/iterator.hpp
/boost/lambda
/boost/last_value.hpp
/boost/lexical_cast.hpp
/boost/lexical_cast.hpp~
/boost/limits.hpp
/boost/locale
/boost/locale.hpp
/boost/local_function
/boost/local_function.hpp
/boost/lockfree
/boost/log
/boost/logic
/boost/make_shared.hpp
/boost/math
/boost/math_fwd.hpp
/boost/mem_fn.hpp
/boost/memory_order.hpp
/boost/move
/boost/mpi
/boost/mpi.hpp
/boost/mpl
/boost/msm
/boost/multi_array
/boost/multi_array.hpp
/boost/multi_index
/boost/multi_index_container_fwd.hpp
/boost/multi_index_container.hpp
/boost/multiprecision
/boost/next_prior.hpp
/boost/noncopyable.hpp
/boost/nondet_random.hpp
/boost/none.hpp
/boost/none_t.hpp
/boost/non_type.hpp
/boost/numeric
/boost/operators.hpp
/boost/optional
/boost/optional.hpp
/boost/parameter
/boost/parameter.hpp
/boost/pending
/boost/phoenix
/boost/phoenix.hpp
/boost/pointee.hpp
/boost/pointer_cast.hpp
/boost/pointer_to_other.hpp
/boost/polygon
/boost/pool
/boost/predef
/boost/predef.h
/boost/preprocessor
/boost/preprocessor.hpp
/boost/program_options
/boost/program_options.hpp
/boost/progress.hpp
/boost/progress.hpp~
/boost/property_map
/boost/property_tree
/boost/proto
/boost/ptr_container
/boost/python
/boost/python.hpp
/boost/random
/boost/random.hpp
/boost/range
/boost/range.hpp
/boost/ratio
/boost/ratio.hpp
/boost/rational.hpp
/boost/rational.hpp.htm
/boost/ref.hpp
/boost/regex
/boost/regex_fwd.hpp
/boost/regex.h
/boost/regex.hpp
/boost/scoped_array.hpp
/boost/scoped_ptr.hpp
/boost/scope_exit.hpp
/boost/serialization
/boost/shared_array.hpp
/boost/shared_container_iterator.hpp
/boost/shared_ptr.hpp
/boost/signal.hpp
/boost/signals
/boost/signals2
/boost/signals2.hpp
/boost/signals.hpp
/boost/smart_ptr
/boost/smart_ptr.hpp
/boost/spirit
/boost/spirit.hpp
/boost/statechart
/boost/static_assert.hpp
/boost/strong_typedef.hpp
/boost/swap.hpp
/boost/sync
/boost/system
/boost/test
/boost/thread
/boost/thread.hpp
/boost/throw_exception.hpp
/boost/timer
/boost/timer.hpp
/boost/token_functions.hpp
/boost/token_iterator.hpp
/boost/tokenizer.hpp
/boost/tr1
/boost/tti
/boost/tuple
/boost/type_erasure
/boost/type.hpp
/boost/typeof
/boost/type_traits
/boost/type_traits.hpp
/boost/type_traits.hpp~
/boost/units
/boost/unordered
/boost/unordered_map.hpp
/boost/unordered_set.hpp
/boost/utility
/boost/utility.hpp
/boost/uuid
/boost/variant
/boost/variant.hpp
/boost/version.hpp
/boost/visit_each.hpp
/boost/wave
/boost/wave.hpp
/boost/weak_ptr.hpp
/boost/xpressive
/libs/accumulators
/libs/algorithm
/libs/any
/libs/array
/libs/asio
/libs/assign
/libs/atomic
/libs/bimap
/libs/bind
/libs/chrono
/libs/circular_buffer
/libs/compatibility
/libs/compose
/libs/concept_check
/libs/config
/libs/container
/libs/context
/libs/conversion
/libs/coroutine
/libs/crc
/libs/date_time
/libs/detail
/libs/disjoint_sets
/libs/dynamic_bitset
/libs/exception
/libs/filesystem
/libs/flyweight
/libs/foreach
/libs/format
/libs/function
/libs/functional
/libs/function_types
/libs/fusion
/libs/geometry
/libs/gil
/libs/graph
/libs/graph_parallel
/libs/heap
/libs/icl
/libs/index.html
/libs/integer
/libs/interprocess
/libs/intrusive
/libs/io
/libs/iostreams
/libs/iterator
/libs/lambda
/libs/libraries.htm
/libs/locale
/libs/local_function
/libs/lockfree
/libs/log
/libs/logic
/libs/maintainers.txt
/libs/math
/libs/mem_fn
/libs/move
/libs/mpi
/libs/mpl
/libs/msm
/libs/multi_array
/libs/multi_index
/libs/multiprecision
/libs/numeric
/libs/optional
/libs/parameter
/libs/phoenix
/libs/platform_maintainers.txt
/libs/polygon
/libs/pool
/libs/predef
/libs/preprocessor
/libs/program_options
/libs/property_map
/libs/property_tree
/libs/proto
/libs/ptr_container
/libs/python
/libs/random
/libs/range
/libs/ratio
/libs/rational
/libs/regex
/libs/scope_exit
/libs/serialization
/libs/signals
/libs/signals2
/libs/smart_ptr
/libs/spirit
/libs/statechart
/libs/static_assert
/libs/sync
/libs/system
/libs/test
/libs/thread
/libs/timer
/libs/tokenizer
/libs/tr1
/libs/tti
/libs/tuple
/libs/type_erasure
/libs/typeof
/libs/type_traits
/libs/units
/libs/unordered
/libs/utility
/libs/uuid
/libs/variant
/libs/wave
/libs/xpressive
/libs/Jamfile.v2
/boost.css
/b2
/boost-build.jam
/rst.css
/boost.png
/bootstrap.sh
/project-config.jam
/Jamroot
/.gitignore~
/index.htm
/README.md
/boostcpp.jam
/INSTALL
/LICENSE_1_0.txt
/index.html
/bjam
/bootstrap.bat
/bootstrap.log
/boostcpp.py
/bin.v2/
/doc/
/more/
/status/
/tools/
/stage/
doc/autodoc.xml
doc/html

47
CMakeLists.txt Normal file
View File

@ -0,0 +1,47 @@
# Copyright 2019 Mike Dev
# Distributed under the Boost Software License, Version 1.0.
# See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
if(NOT DEFINED IDF_TARGET)
cmake_minimum_required(VERSION 3.5...3.20)
project(boost_type_index VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
add_library(boost_type_index INTERFACE)
add_library(Boost::type_index ALIAS boost_type_index)
target_include_directories(boost_type_index INTERFACE include)
target_link_libraries(boost_type_index
INTERFACE
Boost::config
Boost::container_hash
Boost::core
Boost::preprocessor
Boost::smart_ptr
Boost::static_assert
Boost::throw_exception
Boost::type_traits
)
else()
FILE(GLOB_RECURSE headers include/*.h include/*.hpp)
idf_component_register(
SRCS
${headers}
INCLUDE_DIRS
include
REQUIRES
boost_config
boost_container_hash
boost_core
boost_preprocessor
boost_smart_ptr
boost_static_assert
boost_throw_exception
boost_type_traits
)
endif()

View File

@ -1,9 +1,16 @@
type_index
==========
# [Boost.TypeIndex](https://boost.org/libs/type_index)
Boost.TypeIndex is a part of the [Boost C++ Libraries](https://github.com/boostorg). It is a runtime/compile time copyable type info.
Runtime/Compile time copyable type info. Library is waiting for boost reiew.
Documantation available at: http://apolukhin.github.com/type_index/index.html
### Test results
Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt).
@ | Build | Tests coverage | More info
----------------|-------------- | -------------- |-----------
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://www.boost.org/development/tests/develop/developer/type_index.html)
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://www.boost.org/development/tests/master/developer/type_index.html)
While ticket #9228 is not solved, use boost_test_no_rtti.patch to make the tests compile.
[Latest developer documentation](https://www.boost.org/doc/libs/develop/doc/html/boost_typeindex.html)
### License
Distributed under the [Boost Software License, Version 1.0](https://boost.org/LICENSE_1_0.txt).

View File

@ -1,34 +0,0 @@
//
// Copyright (c) Antony Polukhin, 2012-2013.
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_TYPE_INDEX_HPP
#define BOOST_TYPE_INDEX_HPP
/// \file boost/type_index.hpp
/// \brief Includes all the headers of the Boost.TypeIndex library.
///
/// By inclusion of this file all classes (boost::type_info + boost::type_index if RTTI is on
/// and boost::template_info + boost::template_index) will be available.
///
/// Consider including <boost/type_index/type_index.hpp> if you do not want to include
/// boost::template_info and boost::template_index class while RTTI is available.
///
/// Consider including <boost/type_index/type_info.hpp> if you need only boost::type_info class
/// and boost::type_id* functions.
// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/type_index/type_info.hpp>
#include <boost/type_index/type_index.hpp>
#include <boost/type_index/template_info.hpp>
#include <boost/type_index/template_index.hpp>
#endif // BOOST_TYPE_INDEX_HPP

View File

@ -1,35 +0,0 @@
//
// Copyright (c) Antony Polukhin, 2012-2013.
//
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_TYPE_INDEX_TEMPLATE_INDEX_HPP
#define BOOST_TYPE_INDEX_TEMPLATE_INDEX_HPP
// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
# pragma once
#endif
/// \file template_index.hpp
/// \brief Contains implementation of boost::template_index class.
///
/// boost::template_index is just a typedef of boost::template_info, that combines functionality
/// of boost::type_info and boost::type_index but can work with RTTI disabled.
#include <boost/type_index/template_info.hpp>
namespace boost {
/// boost::template_index is just a typedef of boost::template_info, that combines functionality
/// of boost::type_info and boost::type_index but can work with RTTI disabled.
typedef template_info template_index;
} // namespace boost
#endif // BOOST_TYPE_INDEX_TEMPLATE_INDEX_HPP

View File

@ -1,317 +0,0 @@
//
// Copyright (c) Antony Polukhin, 2012-2013.
//
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_TYPE_INDEX_TEMPLATE_INFO_HPP
#define BOOST_TYPE_INDEX_TEMPLATE_INFO_HPP
// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
# pragma once
#endif
/// \file template_info.hpp
/// \brief Contains implementation of boost::template_info class.
///
/// boost::template_info class is used instead of boost::type_info and boost::type_index classes
/// in situations when RTTI is disabled.
///
/// It combines functionality of std::type_info and std::type_index.
#include <cstring>
#include <string>
#include <boost/config.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/functional/hash_fwd.hpp>
#if !defined(BOOST_NO_IOSTREAM)
#if !defined(BOOST_NO_IOSFWD)
#include <iosfwd> // for std::basic_ostream
#else
#include <ostream>
#endif
#endif
namespace boost {
namespace detail {
#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
/// \def BOOST_TYPE_INDEX_FUNCTION_SIGNATURE
/// BOOST_TYPE_INDEX_FUNCTION_SIGNATURE is used by boost::template_info class to
/// deduce the name of a template parameter. If your compiler is not recognized
/// by the TypeIndex library and you wish to work with boost::template_info, you may
/// define this macro by yourself.
///
/// BOOST_TYPE_INDEX_FUNCTION_SIGNATURE must be defined to a compiler specific macro,
/// that outputs the WHOLE function signature, including template parameters.
///
/// If your compiler is not recognised and BOOST_TYPE_INDEX_FUNCTION_SIGNATURE is not defined,
/// then a compile-time error will arise at any attempt to use boost::template_info or
/// boost::template_index classes.
#define BOOST_TYPE_INDEX_FUNCTION_SIGNATURE BOOST_CURRENT_FUNCTION
#elif defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE)
template <class T>
inline void lazy_function_signature_assert(){}
#elif defined(__FUNCSIG__)
template <class T>
inline void lazy_function_signature_assert(){}
#define BOOST_TYPE_INDEX_FUNCTION_SIGNATURE __FUNCSIG__
#elif defined(__PRETTY_FUNCTION__) \
|| defined(__GNUC__) \
|| (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) \
|| (defined(__ICC) && (__ICC >= 600)) \
|| defined(__ghs__) \
|| defined(__DMC__)
template <class T>
inline void lazy_function_signature_assert(){}
#define BOOST_TYPE_INDEX_FUNCTION_SIGNATURE __PRETTY_FUNCTION__
#else
template <class T>
inline void lazy_function_signature_assert() {
BOOST_STATIC_ASSERT_MSG(
sizeof(T) && false,
"TypeIndex library could not detect your compiler. "
"Please make the BOOST_TYPE_INDEX_FUNCTION_SIGNATURE macro use "
"correct compiler macro for getting the whole function name. "
"Do not forget to also define BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP and "
"BOOST_TYPE_INDEX_CTTI_END_SKIP."
);
}
#endif
#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
/// \def BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP
///
/// BOOST_TYPE_INDEX_FUNCTION_SIGNATURE, BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP
/// and BOOST_TYPE_INDEX_CTTI_END_SKIP macroses are used for adding a
/// support for compilers, that by default are not recognized by TypeIndex library.
///
/// See Compiler support for more info
#define BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP 0
/// \def BOOST_TYPE_INDEX_CTTI_END_SKIP
///
/// BOOST_TYPE_INDEX_FUNCTION_SIGNATURE, BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP
/// and BOOST_TYPE_INDEX_CTTI_END_SKIP macroses are used for adding a
/// support for compilers, that by default are not recognized by TypeIndex library.
///
/// See Compiler support for more info
#define BOOST_TYPE_INDEX_CTTI_END_SKIP 0
#elif defined(BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP) && defined(BOOST_TYPE_INDEX_CTTI_END_SKIP)
// skip user specified bytes count
BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_begin = BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP);
// skip user specified bytes count
BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_end = BOOST_TYPE_INDEX_CTTI_END_SKIP);
#elif defined _MSC_VER
// sizeof("const char *__cdecl boost::detail::ctti<") - 1
BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_begin = 40);
// sizeof(">::n(void)") - 1
BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_end = 10);
#elif defined __clang__
// sizeof("static const char *boost::detail::ctti<") - 1
BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_begin = 39);
// == sizeof(">::n()") - 1
BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_end = 6);
#elif defined __GNUC__
// sizeof("static const char* boost::detail::ctti<T>::n() [with T = ") - 1
BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_begin = 57);
// == sizeof("]") - 1
BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_end = 1);
#else
// TODO: Code for other platforms
BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_begin = 0); // skip nothing
BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_end = 0); // skip nothing
#endif
/// Noncopyable type_info that does not require RTTI
/// CTTI == Compile Time Type Info
/// This name must be as short as posible, to avoid code bloat
template <class T>
struct ctti {
typedef T template_type;
typedef ctti this_type;
/// Returns raw name. Must be as short, as possible, to avoid code bloat
static const char* n() BOOST_NOEXCEPT {
lazy_function_signature_assert<T>();
return BOOST_TYPE_INDEX_FUNCTION_SIGNATURE + detail::ctti_skip_size_at_begin;
}
/// Returns raw name
static const char* name() BOOST_NOEXCEPT {
return this_type::n();
}
};
} // namespace detail
/// Copyable type_info class that does not require RTTI.
/// When RTTI is disabled this class will be used instead of boost::type_info and boost::type_index.
class template_info {
private:
const char* name_;
/// @cond
explicit template_info(const char* name) BOOST_NOEXCEPT
: name_(name)
{}
/// @endcond
public:
/// Default constructor.
template_info() BOOST_NOEXCEPT
: name_(detail::ctti<void>::name())
{}
/// Factory method for constructing boost::template_info instance for type T.
/// Strips const, volatile and & modifiers from T.
///
/// Works exactly like boost::template_id().
template <class T>
static const template_info& construct(){
typedef BOOST_DEDUCED_TYPENAME boost::remove_reference<T>::type no_ref_t;
typedef BOOST_DEDUCED_TYPENAME boost::remove_cv<no_ref_t>::type no_cvr_t;
# if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \
|| (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744)
BOOST_STATIC_ASSERT_MSG( !boost::is_arithmetic<no_cvr_t>::type::value
, "Your EDG-based compiler seems to mistakenly distinguish 'int' from 'signed int', in typeid() expressions.");
#endif
static const template_info ret(detail::ctti<no_cvr_t>::name());
return ret;
}
/// Factory method for constructing template_info instance for type T.
/// Does not strip const, volatile and & modifiers from T.
///
/// Works exactly like boost::template_id_with_cvr().
template <class T>
static const template_info& construct_with_cvr() {
# if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \
|| (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744)
BOOST_STATIC_ASSERT_MSG( !boost::is_arithmetic<T>::type::value
, "Your EDG-based compiler seems to mistakenly distinguish 'int' from 'signed int', in typeid() expressions.");
#endif
static const template_info ret(detail::ctti<T>::name());
return ret;
}
/// Returns true if the type precedes the type of rhs in the collation order.
/// The collation order is just an internal order.
bool before(const template_info& rhs) const BOOST_NOEXCEPT {
return std::strcmp(name(), rhs.name()) < 0;
}
/// Returns raw name
const char* name() const BOOST_NOEXCEPT {
return name_;
}
/// Returns user-friendly name
std::string name_demangled() const {
std::size_t len = std::strlen(name_ + detail::ctti_skip_size_at_end);
while (name_[len - 1] == ' ') --len; // MSVC sometimes adds whitespaces
return std::string(name_, len);
}
bool operator == (const template_info& rhs) const BOOST_NOEXCEPT {
return name_ == rhs.name() || !std::strcmp(name_, rhs.name());
}
bool operator != (const template_info& rhs) const BOOST_NOEXCEPT {
return name_ != rhs.name() && !!std::strcmp(name_, rhs.name());
}
bool operator < (const template_info& rhs) const BOOST_NOEXCEPT {
return name_ != rhs.name() && std::strcmp(name_, rhs.name()) < 0;
}
bool operator > (const template_info& rhs) const BOOST_NOEXCEPT {
return name_ != rhs.name() && std::strcmp(name_, rhs.name()) > 0;
}
bool operator <= (const template_info& rhs) const BOOST_NOEXCEPT {
return name_ == rhs.name() || std::strcmp(name_, rhs.name()) <= 0;
}
bool operator >= (const template_info& rhs) const BOOST_NOEXCEPT {
return name_ == rhs.name() || std::strcmp(name_, rhs.name()) >= 0;
}
/// Function for getting hash value
std::size_t hash_code() const BOOST_NOEXCEPT {
return boost::hash_range(name_, name_ + std::strlen(name_ + detail::ctti_skip_size_at_end));
}
};
/// Method for constructing template_info instance for type T.
/// Strips const, volatile and & modifiers from T.
template <class T>
inline const template_info& template_id() BOOST_NOEXCEPT {
return template_info::construct<T>();
}
/// Method for constructing template_info instance for type T.
/// Does not strip const, volatile and & modifiers from T.
/// If T has no const, volatile, & and && modifiers, then returns exactly
/// the same result as in case of calling `template_id<T>()`.
template <class T>
inline const template_info& template_id_with_cvr() BOOST_NOEXCEPT {
return template_info::construct_with_cvr<T>();
}
/* *************** template_info free functions ******************* */
#ifndef BOOST_NO_IOSTREAM
#ifdef BOOST_NO_TEMPLATED_IOSTREAMS
/// Ostream operator that will output demangled name
inline std::ostream& operator<<(std::ostream& ostr, template_info const& ind) {
ostr << ind.name_demangled();
return ostr;
}
#else
/// Ostream operator that will output demangled name
template <class CharT, class TriatT>
inline std::basic_ostream<CharT, TriatT>& operator<<(std::basic_ostream<CharT, TriatT>& ostr, template_info const& ind) {
ostr << ind.name_demangled();
return ostr;
}
#endif // BOOST_NO_TEMPLATED_IOSTREAMS
#endif // BOOST_NO_IOSTREAM
/// hash_value function overload for template_info
inline std::size_t hash_value(template_info const& v) BOOST_NOEXCEPT {
return v.hash_code();
}
} // namespace boost
#endif // BOOST_TYPE_INDEX_TEMPLATE_INFO_HPP

View File

@ -1,221 +0,0 @@
//
// Copyright (c) Antony Polukhin, 2012-2013.
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_TYPE_INDEX_TYPE_INDEX_HPP
#define BOOST_TYPE_INDEX_TYPE_INDEX_HPP
// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
# pragma once
#endif
/// \file boost/type_index/type_index.hpp
/// \brief Contains implementation of boost::type_index class.
///
/// boost::type_index class is used in situations when RTTI is enabled, it is designed to be a drop-in
/// replacement for C++11 std::type_index class.
///
/// When RTTI is disabled boost::template_index will be usually (some compilers allow calling typeid(T)
/// even if RTTI is disabled) used instead of this class.
#include <boost/config.hpp>
#include <boost/type_index/type_info.hpp>
// MSVC is capable of calling typeid(T) even when RTTI is off
#if (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC)
#if !defined(BOOST_NO_IOSTREAM)
#if !defined(BOOST_NO_IOSFWD)
#include <iosfwd> // for std::basic_ostream
#else
#include <ostream>
#endif
#endif
namespace boost {
/// This class is designed to be a drop-in replacement for C++11 std::type_index class.
///
/// Copyable std::type_index class that requires RTTI.
/// When RTTI is disabled boost::template_index will be used instead of
/// this class.
class type_index {
private:
const type_info* pinfo_;
public:
typedef detail::stl_type_info stl_type_info;
/// Default constructor.
type_index() BOOST_NOEXCEPT
: pinfo_(static_cast<const type_info*>(&typeid(void)))
{}
/// Constructs type_index from an instance of boost::type_info.
type_index(const type_info& inf) BOOST_NOEXCEPT
: pinfo_(&inf)
{}
/// Constructs type_index from an instance of std::type_info.
type_index(const stl_type_info& inf) BOOST_NOEXCEPT
: pinfo_(static_cast<const type_info*>(&inf))
{}
/// Returns true if the type precedes the type of rhs in the collation order.
/// The collation order is just an internal order.
bool before(type_index const& rhs) const BOOST_NOEXCEPT {
return pinfo_->before(*rhs.pinfo_);
}
/// Returns raw name
const char* name() const BOOST_NOEXCEPT {
return pinfo_->name();
}
/// Returns user-friendly name
std::string name_demangled() const {
return pinfo_->name_demangled();
}
bool operator == (type_index const& rhs) const BOOST_NOEXCEPT {
return *pinfo_ == *rhs.pinfo_;
}
bool operator != (type_index const& rhs) const BOOST_NOEXCEPT {
return !(*pinfo_ == *rhs.pinfo_);
}
bool operator < (type_index const& rhs) const BOOST_NOEXCEPT {
return before(rhs);
}
bool operator > (type_index const& rhs) const BOOST_NOEXCEPT {
return (rhs < *this);
}
bool operator <= (type_index const& rhs) const BOOST_NOEXCEPT {
return !(*this > rhs);
}
bool operator >= (type_index const& rhs) const BOOST_NOEXCEPT {
return !(*this < rhs);
}
bool operator == (stl_type_info const& rhs) const BOOST_NOEXCEPT {
return *this == type_index(rhs);
}
bool operator != (stl_type_info const& rhs) const BOOST_NOEXCEPT {
return *this != type_index(rhs);
}
bool operator < (stl_type_info const& rhs) const BOOST_NOEXCEPT {
return *this < type_index(rhs);
}
bool operator > (stl_type_info const& rhs) const BOOST_NOEXCEPT {
return *this > type_index(rhs);
}
bool operator <= (stl_type_info const& rhs) const BOOST_NOEXCEPT {
return *this <= type_index(rhs);
}
bool operator >= (stl_type_info const& rhs) const BOOST_NOEXCEPT {
return *this >= type_index(rhs);
}
/// Function for getting hash value
std::size_t hash_code() const BOOST_NOEXCEPT {
return pinfo_->hash_code();
}
};
/* *************** type_index free functions ******************* */
#ifndef BOOST_TYPE_INDEX_DOXYGEN_INVOKED
inline bool operator == (detail::stl_type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT {
return rhs == lhs; // Operation is commutative
}
inline bool operator != (detail::stl_type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT {
return rhs != lhs; // Operation is commutative
}
inline bool operator < (detail::stl_type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT {
return rhs > lhs;
}
inline bool operator > (detail::stl_type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT {
return rhs < lhs;
}
inline bool operator <= (detail::stl_type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT {
return rhs >= lhs;
}
inline bool operator >= (detail::stl_type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT {
return rhs <= lhs;
}
#else // BOOST_TYPE_INDEX_DOXYGEN_INVOKED
inline bool operator == (std::type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT;
inline bool operator != (std::type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT;
inline bool operator < (std::type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT;
inline bool operator > (std::type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT;
inline bool operator <= (std::type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT;
inline bool operator >= (std::type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT;
#endif // BOOST_TYPE_INDEX_DOXYGEN_INVOKED
/* *************** type_index free functions ******************* */
#ifndef BOOST_NO_IOSTREAM
#ifdef BOOST_NO_TEMPLATED_IOSTREAMS
/// Ostream operator that will output demangled name.
inline std::ostream& operator<<(std::ostream& ostr, type_index const& ind) {
ostr << ind.name_demangled();
return ostr;
}
#else
/// Ostream operator that will output demangled name.
template <class CharT, class TriatT>
inline std::basic_ostream<CharT, TriatT>& operator<<(std::basic_ostream<CharT, TriatT>& ostr, type_index const& ind) {
ostr << ind.name_demangled();
return ostr;
}
#endif // BOOST_NO_TEMPLATED_IOSTREAMS
#endif // BOOST_NO_IOSTREAM
/// hash_value function overload for type_index.
inline std::size_t hash_value(type_index const& v) BOOST_NOEXCEPT {
return v.hash_code();
}
} // namespace boost
#else // (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC)
#include <boost/type_index/template_index.hpp>
namespace boost {
typedef template_index type_index;
}
#endif // (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC)
#endif // BOOST_TYPE_INDEX_TYPE_INDEX_HPP

View File

@ -1,373 +0,0 @@
//
// Copyright (c) Antony Polukhin, 2012-2013.
//
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_TYPE_INDEX_TYPE_INFO_HPP
#define BOOST_TYPE_INDEX_TYPE_INFO_HPP
// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
# pragma once
#endif
/// \file type_info.hpp
/// \brief Contains implementation of boost::type_info class.
///
/// boost::type_info class can be used as a drop-in replacement for std::type_info, but unlike std::type_info
/// this class has a name_demangled() function for getting human-readable type names.
///
/// boost::type_info class is used in situations when RTTI is enabled.
/// When RTTI is disabled or BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY macro is defined boost::template_info
/// is usually used instead of it (some compilers allow calling typeid(T)
/// even if RTTI is disabled, those copilers will continue to use boost::type_info class).
#include <boost/config.hpp>
// MSVC is capable of calling typeid(T) even when RTTI is off
#if (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC)
#include <cstring>
#include <string>
#include <boost/config.hpp>
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/is_reference.hpp>
#include <boost/type_traits/is_volatile.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/mpl/if.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/functional/hash_fwd.hpp>
#include <typeinfo>
#ifdef __GNUC__
#include <cxxabi.h>
#endif
namespace boost {
/// @cond
// for this compiler at least, cross-shared-library type_info
// comparisons don't work, so we are using typeid(x).name() instead.
# if (defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5))) \
|| defined(_AIX) \
|| (defined(__sgi) && defined(__host_mips)) \
|| (defined(__hpux) && defined(__HP_aCC)) \
|| (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC))
# define BOOST_CLASSINFO_COMPARE_BY_NAMES
# endif
/// @endcond
namespace detail {
#ifdef BOOST_NO_STD_TYPEINFO
typedef type_info stl_type_info;
#else
typedef std::type_info stl_type_info;
#endif
template <class T> class cvr_saver{};
}
/// boost::type_info is a class that can be used as a drop-in replacement for std::type_info.
///
/// boost::type_info class is used in situations when RTTI is enabled.
/// When RTTI is disabled or BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY macro is defined boost::template_info
/// is used instead of it.
///
/// Unlike std::type_info this class:
/// * has a name_demangled() function for getting human-readable type names
/// * name() function always noexcept and returns simple mangled name as character a character array
/// * contains workarounds for some compiler issues
///
/// boost::type_info is not copyable and is not default constructible. Use boost::type_id* functions
/// to get const references to instances of boost::type_info objects.
class type_info: public detail::stl_type_info {
#ifndef BOOST_NO_DELETED_FUNCTIONS
type_info() = delete;
type_info(const type_info&) = delete;
#else
type_info();
type_info(const type_info&);
#endif
public:
typedef detail::stl_type_info stl_type_info;
/// Factory method for constructing boost::type_info instance for type T.
/// Strips const, volatile and & modifiers from T.
///
/// Works exactly like boost::type_id().
template <class T>
static const boost::type_info& construct() BOOST_NOEXCEPT {
typedef BOOST_DEDUCED_TYPENAME boost::remove_reference<T>::type no_ref_t;
typedef BOOST_DEDUCED_TYPENAME boost::remove_cv<no_ref_t>::type no_cvr_t;
# if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \
|| (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744)
BOOST_STATIC_ASSERT_MSG( !boost::is_arithmetic<no_cvr_t>::type::value
, "Your EDG-based compiler seems to mistakenly distinguish 'int' from 'signed int', in typeid() expressions.");
#endif
return static_cast<const boost::type_info&>(typeid(no_cvr_t));
}
/// Factory method for constructing boost::type_info instance for type T.
/// Does not strip const, volatile, & and && modifiers from T.
/// If T has no const, volatile, & and && modifiers, then returns exactly
/// the same result as in case of calling `construct<T>()`.
///
/// Works exactly like boost::type_id_with_cvr().
template <class T>
static const boost::type_info& construct_with_cvr() BOOST_NOEXCEPT {
typedef typename boost::mpl::if_c<
boost::is_reference<T>::value
|| boost::is_const<T>::value
|| boost::is_volatile<T>::value,
detail::cvr_saver<T>,
T
>::type type;
return static_cast<const boost::type_info&>(typeid(type));
}
/// Factory function, that works exactly like C++ typeid(rtti_val) call, but returns boost::type_info.
/// This method available only with RTTI enabled.
///
/// Same as boost::type_id_rtti_only().
template <class T>
static const type_info& construct_rtti_only(T& rtti_val) BOOST_NOEXCEPT {
#ifdef BOOST_NO_RTTI
BOOST_STATIC_ASSERT_MSG(sizeof(T) && false,
"boost::type_id_rtti_only(T&) and boost::type_info::construct_rtti_only(T&) require RTTI");
#endif
return static_cast<const boost::type_info&>(typeid(rtti_val));
}
/// Factory function, that works exactly like C++ typeid(rtti_val) call, but returns boost::type_info.
/// This method available only with RTTI enabled.
///
/// Same as boost::type_id_rtti_only().
template <class T>
static const type_info& construct_rtti_only(T* rtti_val) {
#ifdef BOOST_NO_RTTI
BOOST_STATIC_ASSERT_MSG(sizeof(T) && false,
"boost::type_id_rtti_only(T*) and boost::type_info::construct_rtti_only(T*) require RTTI");
#endif
return static_cast<const boost::type_info&>(typeid(rtti_val));
}
/// Returns mangled type name.
const char* name() const BOOST_NOEXCEPT {
#ifdef _MSC_VER
return stl_type_info::raw_name();
#else
return stl_type_info::name();
#endif
}
/// Returns user-friendly name
std::string name_demangled() const {
#if defined(_MSC_VER)
std::string ret = stl_type_info::name();
#else
std::string ret;
int status = 0;
char* demang = abi::__cxa_demangle(name(), NULL, 0, &status);
BOOST_ASSERT(!status);
BOOST_TRY {
ret = demang; // may throw out of memory exception
} BOOST_CATCH (...) {
free(demang);
BOOST_RETHROW;
} BOOST_CATCH_END
free(demang);
#endif
std::string::size_type pos = ret.find("boost::detail::cvr_saver<");
if (pos == std::string::npos) {
return ret;
}
pos += sizeof("boost::detail::cvr_saver<") - 1;
while (ret[pos] == ' ') {
++ pos;
}
std::string::size_type end = ret.rfind(">");
BOOST_ASSERT(end != std::string::npos);
while (ret[end - 1] == ' ') {
-- end;
}
return ret.substr(pos, end - pos);
}
bool operator == (type_info const& rhs) const BOOST_NOEXCEPT {
#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
return name() == rhs.name() || !std::strcmp(name(), rhs.name());
#else
return static_cast<const stl_type_info&>(*this) == static_cast<const stl_type_info&>(rhs);
#endif
}
bool operator != (type_info const& rhs) const BOOST_NOEXCEPT {
return !(*this == rhs);
}
bool operator == (stl_type_info const& rhs) const BOOST_NOEXCEPT {
return *this == static_cast<const boost::type_info&>(rhs);
}
bool operator != (stl_type_info const& rhs) const BOOST_NOEXCEPT {
return !(*this == rhs);
}
/// Returns true if the type precedes the type of rhs in the collation order.
/// The collation order is just an internal order.
/// Works exactly like operator <
bool before(type_info const& rhs) const BOOST_NOEXCEPT {
#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
return name() != rhs.name() && std::strcmp(name(), rhs.name()) < 0;
#else
return !!stl_type_info::before(rhs);
#endif
}
/// Returns true if the type precedes the type of rhs in the collation order.
/// The collation order is just an internal order.
/// Works exactly like operator <
bool before(stl_type_info const& rhs) const BOOST_NOEXCEPT {
return before(static_cast<const boost::type_info&>(rhs));
}
/// Function for getting hash value
std::size_t hash_code() const BOOST_NOEXCEPT {
#if _MSC_VER > 1600 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5 && defined(__GXX_EXPERIMENTAL_CXX0X__))
return stl_type_info::hash_code();
#else
return boost::hash_range(name(), name() + std::strlen(name()));
#endif
}
};
#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
#undef BOOST_CLASSINFO_COMPARE_BY_NAMES
#endif
/// Function to get boost::type_info for a type T.
/// Strips const, volatile and & modifiers from T.
template <class T>
inline const type_info& type_id() BOOST_NOEXCEPT {
return type_info::construct<T>();
}
/// Function for constructing boost::type_info instance for type T.
/// Does not strip const, volatile, & and && modifiers from T.
/// If T has no const, volatile, & and && modifiers, then returns exactly
/// the same result as in case of calling `type_id<T>()`.
template <class T>
inline const type_info& type_id_with_cvr() BOOST_NOEXCEPT {
return type_info::construct_with_cvr<T>();
}
/// Function that works exactly like C++ typeid(rtti_val) call, but returns boost::type_info.
/// This method available only with RTTI enabled. Without RTTI support it won't compile,
/// producing a compile-time error with message: "boost::type_id_rtti_only(T&) requires RTTI"
template <class T>
inline const type_info& type_id_rtti_only(T& rtti_val) BOOST_NOEXCEPT {
#ifdef BOOST_NO_RTTI
BOOST_STATIC_ASSERT_MSG(sizeof(T) && false, "boost::type_id_rtti_only(T&) requires RTTI");
#endif
return static_cast<const type_info&>(typeid(rtti_val));
}
/// Function that works exactly like C++ typeid(rtti_val) call, but returns boost::type_info.
/// This method available only with RTTI enabled. Without RTTI support it won't compile,
/// producing a compile-time error with message: "boost::type_id_rtti_only(T*) requires RTTI"
template <class T>
inline const type_info& type_id_rtti_only(T* rtti_val) {
#ifdef BOOST_NO_RTTI
BOOST_STATIC_ASSERT_MSG(sizeof(T) && false, "boost::type_id_rtti_only(T*) requires RTTI");
#endif
return static_cast<const type_info&>(typeid(rtti_val));
}
/* *************** type_info free functions ******************* */
#ifndef BOOST_TYPE_INDEX_DOXYGEN_INVOKED
inline bool operator == (detail::stl_type_info const& lhs, type_info const& rhs) BOOST_NOEXCEPT {
return rhs == static_cast<const boost::type_info&>(lhs);
}
inline bool operator != (detail::stl_type_info const& lhs, type_info const& rhs) BOOST_NOEXCEPT {
return !(lhs == rhs);
}
#else // BOOST_TYPE_INDEX_DOXYGEN_INVOKED
inline bool operator == (std::type_info const& lhs, type_info const& rhs) BOOST_NOEXCEPT;
inline bool operator != (std::type_info const& lhs, type_info const& rhs) BOOST_NOEXCEPT;
#endif // BOOST_TYPE_INDEX_DOXYGEN_INVOKED
/// hash_value function overload for boost::type_info.
inline std::size_t hash_value(type_info const& v) BOOST_NOEXCEPT {
return v.hash_code();
}
} // namespace boost
#else // !defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)
# include <boost/type_index/template_info.hpp>
# include <boost/static_assert.hpp>
namespace boost {
typedef template_info type_info;
template <class T>
inline const type_info& type_id() BOOST_NOEXCEPT {
return template_info::construct<T>();
}
template <class T>
inline const type_info& type_id_with_cvr() BOOST_NOEXCEPT {
return template_info::construct_with_cvr<T>();
}
template <class T>
inline const type_info& type_id_rtti_only(T& rtti_val) BOOST_NOEXCEPT {
BOOST_STATIC_ASSERT_MSG(sizeof(T) && false, "boost::type_id_rtti_only(T&) requires RTTI");
return template_info::construct_with_cvr<void>();
}
template <class T>
inline const type_info& type_id_rtti_only(T* rtti_val) {
BOOST_STATIC_ASSERT_MSG(sizeof(T) && false, "boost::type_id_rtti_only(T*) requires RTTI");
return template_info::construct_with_cvr<void>();
}
} // namespace boost
#endif // (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined (BOOST_MSVC)
#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
/// \def BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY
/// Define the BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY macro if you are mixing objects
/// compiled with different RTTI flags. This will force the usage of boost::template_index
/// class instead of boost::type_index.
#define BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY
#endif // BOOST_TYPE_INDEX_DOXYGEN_INVOKED
#endif // BOOST_TYPE_INDEX_TYPE_INFO_HPP

View File

@ -1,44 +0,0 @@
Index: trunk/boost/test/execution_monitor.hpp
===================================================================
--- trunk/boost/test/execution_monitor.hpp (revision 86235)
+++ trunk/boost/test/execution_monitor.hpp (working copy)
@@ -261,7 +261,7 @@
template<typename ExceptionType>
void erase_exception_translator( boost::type<ExceptionType>* = 0 )
{
- m_custom_translators = m_custom_translators->erase<ExceptionType>( m_custom_translators );
+ m_custom_translators = m_custom_translators->template erase<ExceptionType>( m_custom_translators );
}
private:
Index: trunk/boost/test/tree/test_case_template.hpp
===================================================================
--- trunk/boost/test/tree/test_case_template.hpp (revision 86235)
+++ trunk/boost/test/tree/test_case_template.hpp (working copy)
@@ -34,8 +34,13 @@
#include <boost/type_traits/is_const.hpp>
#include <boost/function/function0.hpp>
+#ifndef BOOST_NO_RTTI
+#include <typeinfo> // for typeid
+#else
+#include <boost/current_function.hpp>
+#endif
+
// STL
-#include <typeinfo> // for typeid
#include <string> // for std::string
#include <list> // for std::list
@@ -77,7 +82,11 @@
std::string full_name;
assign_op( full_name, m_test_case_name, 0 );
full_name += '<';
+#ifndef BOOST_NO_RTTI
full_name += typeid(TestType).name();
+#else
+ full_name += BOOST_CURRENT_FUNCTION;
+#endif
if( boost::is_const<TestType>::value )
full_name += " const";
full_name += '>';

View File

@ -1,4 +1,4 @@
# Copyright Antony Polukhin 2011-2013.
# Copyright 2011-2022 Antony Polukhin.
# Use, modification, and distribution are
# subject to the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@ -11,6 +11,7 @@ doxygen autodoc
:
[ glob ../../../boost/type_index.hpp ]
[ glob ../../../boost/type_index/*.hpp ]
[ glob ../../../boost/type_index/runtime_cast/*.hpp ]
:
<doxygen:param>EXTRACT_ALL=NO
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
@ -20,11 +21,12 @@ doxygen autodoc
<doxygen:param>MACRO_EXPANSION=YES
<doxygen:param>"PREDEFINED=\"stl_type_info=std::type_info\" \\
\"BOOST_TYPE_INDEX_DOXYGEN_INVOKED\" \\
\"BOOST_CXX14_CONSTEXPR=constexpr\" \\
\"detail::stl_type_info=std::type_info\""
<xsl:param>"boost.doxygen.reftitle=Boost.TypeIndex Header Reference"
;
xml type_index : type_index.qbk ;
xml type_index : type_index.qbk : <dependency>autodoc ;
boostbook standalone
:
type_index
@ -32,6 +34,14 @@ boostbook standalone
<xsl:param>boost.root=http://www.boost.org/doc/libs/1_53_0
# <xsl:param>boost.root=../../../..
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html
<dependency>autodoc
;
###############################################################################
alias boostdoc
: type_index
:
: <dependency>autodoc
: ;
explicit boostdoc ;
alias boostrelease ;
explicit boostrelease ;

483
doc/type_index.qbk Normal file
View File

@ -0,0 +1,483 @@
[library Boost.TypeIndex
[quickbook 1.6]
[version 4.1]
[copyright 2012-2022 Antony Polukhin]
[category Language Features Emulation]
[license
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
[@http://www.boost.org/LICENSE_1_0.txt])
]
]
[section Motivation]
Sometimes getting and storing information about a type at runtime is required. For such cases a construction like `&typeid(T)` or C++11 class `std::type_index` is usually used, which is where problems start:
* `typeid(T)` and `std::type_index` require Run Time Type Info (RTTI)
* some implementations of `typeid(T)` erroneously do not strip const, volatile and references from type
* some compilers have bugs and do not correctly compare `std::type_info` objects across shared libraries
* only a few implementations of Standard Library currently provide `std::type_index`
* no easy way to store type info without stripping const, volatile and references
* no nice and portable way to get human readable type names
* no way to easily make your own type info class
Boost.TypeIndex library was designed to work around all those issues.
[note `T` means type here. Think of it as of `T` in `template <class T>` ]
[endsect]
[section Getting started]
[classref boost::typeindex::type_info boost::typeindex::type_info] is a drop-in replacement for `std::type_info` and
[classref boost::typeindex::type_index boost::typeindex::type_index]
is a drop-in replacement for `std::type_index`. Unlike Standard Library versions those classes can work without RTTI.
`type_index` provides the full set of comparison operators, hashing functions and ostream
operators, so it can be used with any container class.
[section How to use]
To start using Boost.TypeIndex:
[table:porting
[[Replace this:][With the following:][More Info]]
[[``
#include <typeinfo>
#include <typeindex>
``][``
#include <boost/type_index.hpp>
``][
[headerref boost/type_index.hpp more... ]
]]
[[``
std::type_index
``][``
boost::typeindex::type_index
``][
[classref boost::typeindex::type_index more... ]
]]
[[``
typeid(T)
typeid(T).name() // not human readable
typeid(variable)
``][``
boost::typeindex::type_id<T>()
boost::typeindex::type_id<T>().pretty_name() // human readable
boost::typeindex::type_id_runtime(variable)
``][
[funcref boost::typeindex::type_id more... ]
[classref boost::typeindex::type_index more... ]
[funcref boost::typeindex::type_id_runtime more... ]
]]
[[``
// attempt to save const, volatile, reference
typeid(please_save_modifiers<T>)
``][``
// cvr = const, volatile, reference
boost::typeindex::type_id_with_cvr<T>()
``][
[funcref boost::typeindex::type_id_with_cvr more... ]
]]
[[``
// when reference to `std::type_info` is required
const std::type_info& v1 = typeid(int);
// other cases
const std::type_info* v2 = &typeid(int);
``][``
const boost::typeindex::type_info& v1
= boost::typeindex::type_id<int>().type_info();
boost::typeindex::type_index v2
= boost::typeindex::type_id<int>();
``][
[classref boost::typeindex::type_index more... ]
[funcref boost::typeindex::type_id more... ]
]]
]
If you are using [funcref boost::typeindex::type_id_runtime type_id_runtime()] methods
and RTTI is disabled, make sure that classes that are passed to
`type_id_runtime()` are marked with
[macroref BOOST_TYPE_INDEX_REGISTER_CLASS BOOST_TYPE_INDEX_REGISTER_CLASS] macro.
[endsect]
[section Example with Boost.Any]
Here is how TypeIndex could be used in `boost/any.hpp`:
[table:any
[[Before] [With TypeIndex]]
[[``#include <typeinfo>``][``#include <boost/type_index.hpp>``]]
[[``
virtual const std::type_info & type() const BOOST_NOEXCEPT
{
// requires RTTI
return typeid(ValueType);
}
``] [``
virtual const boost::typeindex::type_info & type() const BOOST_NOEXCEPT
{
// now works even with RTTI disabled
return boost::typeindex::type_id<ValueType>().type_info();
}
``]]
]
[endsect]
[section Example with Boost.Variant]
Here is how TypeIndex could be used in `boost/variant/variant.hpp`:
[table:variant
[[Before] [With TypeIndex]]
[[``
#if !defined(BOOST_NO_TYPEID)
#include <typeinfo> // for typeid, std::type_info
#endif // BOOST_NO_TYPEID
``][``
#include <boost/type_index.hpp>
``]]
[[``
#if !defined(BOOST_NO_TYPEID)
class reflect
: public static_visitor<const std::type_info&>
{
public: // visitor interfaces
template <typename T>
const std::type_info& operator()(const T&) const BOOST_NOEXCEPT
{
return typeid(T);
}
};
#endif // BOOST_NO_TYPEID
``][``
class reflect
: public static_visitor<const boost::typeindex::type_info&>
{
public: // visitor interfaces
template <typename T>
const boost::typeindex::type_info& operator()(const T&) const BOOST_NOEXCEPT
{
return boost::typeindex::type_id<T>().type_info();
}
};
``]]
[[``
#if !defined(BOOST_NO_TYPEID)
const std::type_info& type() const
{
detail::variant::reflect visitor;
return this->apply_visitor(visitor);
}
#endif
``] [``
const boost::typeindex::type_info& type() const
{
detail::variant::reflect visitor;
return this->apply_visitor(visitor);
}
``]]
]
[endsect]
[endsect]
[section:config Configuring and building the library]
TypeIndex is a header only library and it does not use Boost libraries that require
building. You just need to `#include <boost/type_index.hpp>` to start using it.
The library supports a number of configuration macros, defining which require full
rebuild of all the projects that use TypeIndex:
[table Configuration macros
[[Macro name] [Short description]]
[[[macroref BOOST_TYPE_INDEX_USER_TYPEINDEX]] [ Macro that allows you to use your
own implementation of TypeIndex instead of the default all around the projects and libraries.]]
[[[macroref BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY]] [ Macro that must be defined
if you are mixing RTTI-on and RTTI-off.]]
[[[macroref BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING] and
[macroref BOOST_TYPE_INDEX_FUNCTION_SIGNATURE]] [ Macros that allow you to specify
parsing options and type name generating macro for RTTI-off cases. ]]
]
You can define configuration macros in the `bjam` command line using one of the following
approaches:
[pre
b2 variant=release define=BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY stage
]
[pre
b2 variant=release "define=BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING='(39, 1, true, \\"T = \\")'" stage
]
However, it may be more convenient to define configuration macros in the "boost/config/user.hpp"
file in order to automatically define them both for the library and user's projects.
[endsect]
[section How it works]
`type_index` is just a typedef for [classref boost::typeindex::stl_type_index]
or [classref boost::typeindex::ctti_type_index].
Depending on the `typeid()` availability TypeIndex library will choose an optimal class for
`type_index`. In cases when at least basic support for `typeid()` is available `stl_type_index` will be used.
[macroref BOOST_TYPE_INDEX_REGISTER_CLASS] macro is a helper macro that places some virtual helper functions or
expands to nothing.
[macroref BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS] macro is a helper macro that places the same
helpers as BOOST_TYPE_INDEX_REGISTER_CLASS plus some additional helpers for boost::typeindex::runtime_cast
to function.
Issues with cross module type comparison on a bugged compilers are bypassed by directly comparing strings with type
(latest versions of those compilers resolved that issue using exactly the same approach).
[endsect]
[section Examples]
[import ../examples/demangled_names.cpp]
[section Getting human readable and mangled type names] [type_index_names_example] [endsect]
[import ../examples/registry.cpp]
[section Storing information about a type in container ] [type_index_registry_example] [endsect]
[import ../examples/inheritance.cpp]
[section Getting through the inheritance to receive a real type name ] [type_index_derived_example] [endsect]
[import ../examples/runtime_cast.cpp]
[section Using runtime_cast where RTTI is unavailable or undesirable ] [type_index_runtime_cast_example] [endsect]
[import ../examples/exact_types_match.cpp]
[section Exact type matching: storing type with const, volatile and reference qualifiers] [type_index_exact_type_match_example] [endsect]
[import ../examples/table_of_names.cpp]
[section Table of raw_name() and pretty_name() outputs with and without RTTI ] [type_index_names_table] [endsect]
[import ../examples/constexpr14_namespace_check.cpp]
[section C++14: Checking namespace at compile time ] [type_index_constexpr14_namespace_example] [endsect]
[import ../examples/constexpr14_sort_check.cpp]
[section C++14: Checking lexigraphical order of provided types ] [type_index_constexpr14_sort_check_example] [endsect]
[endsect]
[xinclude autodoc.xml]
[section Making a custom type_index]
Sometimes there may be a need to create your own type info system. This may be useful if you wish to store some more info about types (PODness, size of a type, pointers to common functions...) or if you have an idea of a more compact types representations.
[import ../examples/user_defined_typeinfo.hpp]
[import ../examples/user_defined_typeinfo.cpp]
[section Basics]
[type_index_userdefined_usertypes]
[type_index_userdefined_enum]
[type_index_my_type_index]
[type_index_my_type_index_usage]
[endsect]
[section Getting type infos at runtime]
[type_index_my_type_index_register_class]
[type_index_my_type_index_type_id_runtime_implmentation]
[type_index_my_type_index_type_id_runtime_classes]
[type_index_my_type_index_type_id_runtime_test]
[endsect]
[section Using new type infos all around the code]
[type_index_my_type_index_worldwide_macro]
[type_index_my_type_index_worldwide_typedefs]
[type_index_my_type_index_worldwide_usage]
[endsect]
[endsect]
[section Space and Performance]
* `ctti_type_index` uses macro for getting full text representation of function name which could lead to code bloat,
so prefer using `stl_type_index` type when possible.
* All the type_index classes hold a single pointer and are fast to copy.
* Calls to `const char* raw_name()` do not require dynamic memory allocation and usually just return a pointer to an array of chars in a read-only section of the binary image.
* Comparison operators are optimized as much as possible and execute a single `std::strcmp` in worst case.
* Calls to `std::string pretty_name()` usually require dynamic memory allocation and some computations, so they are not recommended for usage in performance critical sections.
[endsect]
[section Code bloat]
Without RTTI TypeIndex library will switch from using `boost::typeindex::stl_type_index` class to
`boost::typeindex::ctti_type_index`. `boost::typeindex::ctti_type_index` uses macro for getting full
text representation of function name for each type that is passed to `type_id()` and
`type_id_with_cvr()` functions.
This leads to big strings in binary file:
```
static const char* boost::detail::ctti<T>::n() [with T = int]
static const char* boost::detail::ctti<T>::n() [with T = user_defined_type]
```
While using RTTI, you'll get the following (more compact) string in binary file:
```
i
17user_defined_type
```
[endsect]
[section RTTI emulation limitations]
TypeIndex has been tested and successfully work on many compilers.
[warning
With RTTI off classes with exactly the same names defined in different modules in anonymous namespaces may collapse:
```
// In A.cpp
namespace { struct user_defined{}; }
type_index foo_a() { return type_id<user_defined>(); }
// In B.cpp
namespace { struct user_defined{}; }
type_index foo_b() { return type_id<user_defined>(); }
// In main.cpp
assert(foo_a() != foo_b()); // will fail on some compilers
```
*Compilers that have that limitation:* GCC, CLANG, Intel.
*Test:* you can test this issue by runing the `testing_crossmodule_anonymous_no_rtti` that can be build if you run `../../../b2` in `type_index/test/` folder.
]
[section Define the BOOST_TYPE_INDEX_FUNCTION_SIGNATURE macro]
If you get the following error during compilation
``
TypeIndex library could not detect your compiler.
Please make the BOOST_TYPE_INDEX_FUNCTION_SIGNATURE macro use
correct compiler macro for getting the whole function name.
Define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING to correct value after that.
``
then you are using a compiler that was not tested with this library.
[macroref BOOST_TYPE_INDEX_FUNCTION_SIGNATURE] must be defined to a compiler specific macro, that outputs the *whole*
function signature including template parameters.
[endsect]
[section Fixing pretty_name() output]
If the output of `boost::typeindex::ctti_type_index::type_id<int>().name()`
* returns not just `int` but also a lot of text around the `int`
* or does not return type at all
then you are using a compiler that was not tested with this library and you need to setup the
[macroref BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING] macro.
Here is a short instruction:
# get the output of `boost::typeindex::ctti_type_index::type_id<int>().name()`
# define [macroref BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING] to
`(skip_at_begin, skip_at_end, false, "")`, where
* `skip_at_begin` is equal to characters count before the first occurrence of `int` in output
* `skip_at_end` is equal to characters count after last occurrence of `int` in output
# check that `boost::typeindex::ctti_type_index::type_id<int>().name_demangled()` returns "int"
# if it does not return `int`, then define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING to
`(skip_at_begin, skip_at_end, true, "T = ")`, where
* `skip_at_begin` is equal to `skip_at_begin` at step 2
* `skip_at_end` is equal to `skip_at_end` at step 2
* `"T = "` is equal to characters that are right before the `int` in output
# (optional, but highly recommended) [@http://www.boost.org/support/bugs.html create ticket] with
feature request to add your compiler to supported compilers list. Include
parameters provided to `BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING` macro.
Consider the following example:
`boost::typeindex::ctti_type_index::type_id<int>().raw_name()` returns
"const char *__cdecl boost::detail::ctti<int>::n(void)". Then you shall set
`skip_at_begin` to `sizeof("const char *__cdecl boost::detail::ctti<") - 1`
and `skip_at_end` to `sizeof(">::n(void)") - 1`.
``
#define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING (39, 6, false, "")
``
Another example:
`boost::typeindex::ctti_type_index::type_id<int>().raw_name()` returns
"static const char *boost::detail::ctti<int>::n() [T = int]"". Then you shall set
`skip_at_begin` to `sizeof("static const char *boost::detail::ctti<") - 1`
and `skip_at_end` to `sizeof("]") - 1` and last parameter of macro to "T = ".
``
#define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING (39, 1, true, "T = ")
``
[endsect]
[endsect]
[section Mixing sources with RTTI on and RTTI off]
Linking a binary from source files that were compiled with different RTTI flags is not a very good
idea and may lead to a lot of surprises. However if there is a very strong need, TypeIndex library
provides a solution for mixing sources: just define [macroref BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY]
macro. This would lead to usage of same type_index class (`boost::typeindex::ctti_type_index` or
`boost::typeindex::stl_type_index`) all around the project.
[note Do not forget to rebuild *all* the projects with `BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY` macro defined ]
You must know that linking RTTI on and RTTI off binaries may succeed even without defining the
`BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY` macro, but that does not mean that you'll get a
working binary. Such actions may break the One Definition Rule. Take a look at the table below,
that shows how the `boost::type_index get_integer();` function will look like with different
RTTI flags:
[table:diffs
[[RTTI on] [RTTI off]]
[[`boost::typeindex::stl_type_index get_integer();`] [`boost::typeindex::ctti_type_index get_integer();`]]
]
Such differences are usually not detected by linker and lead to errors at runtime.
[warning
Even with `BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY` defined there is no guarantee
that everything will be OK. Libraries that use their own workarounds for disabled RTTI
may fail to link or to work correctly.
]
[endsect]
[section Acknowledgements]
In order of helping and advising:
* Peter Dimov for writing source codes in late 2007, that gave me an idea of how to emulate RTTI.
* Agustín Bergé K-ballo for helping with docs and fixing a lot of typos.
* Niall Douglas for generating a lot of great ideas, reviewing the sources and being the review manager for the library.
* All the library reviewers, especially Andrey Semashev, for making good notes and proposing improvements to the library.
[endsect]

View File

@ -0,0 +1,99 @@
// Copyright 2013-2022 Antony Polukhin
// Distributed under the Boost Software License, Version 1.0.
// (See the accompanying file LICENSE_1_0.txt
// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
#include <boost/config.hpp>
#include <cstddef>
template <class T>
void do_something(const T&) {}
#if !defined(BOOST_NO_CXX14_CONSTEXPR) && !defined(BOOST_NO_CXX11_CONSTEXPR)
// Implementation of this function is not essential for the example
template <std::size_t N>
constexpr bool starts_with(const char* name, const char (&ns)[N]) noexcept {
for (std::size_t i = 0; i < N - 1; ++i)
if (name[i] != ns[i])
return false;
return true;
}
//[type_index_constexpr14_namespace_example
/*`
The following example shows that `boost::typeindex::ctti_type_index` is usable at compile time on
a C++14 compatible compilers.
In this example we'll create and use a constexpr function that checks namespace of the provided type.
*/
#include <boost/type_index/ctti_type_index.hpp>
// Helper function that returns true if `name` starts with `substr`
template <std::size_t N>
constexpr bool starts_with(const char* name, const char (&substr)[N]) noexcept;
// Function that returns true if `T` declared in namespace `ns`
template <class T, std::size_t N>
constexpr bool in_namespace(const char (&ns)[N]) noexcept {
const char* name = boost::typeindex::ctti_type_index::type_id<T>().raw_name();
// Some compilers add `class ` or `struct ` before the namespace, so we need to skip those words first
if (starts_with(name, "class ")) {
name += sizeof("class ") - 1;
} else if (starts_with(name, "struct ")) {
name += sizeof("struct ") - 1;
}
return starts_with(name, ns) && starts_with(name + N - 1, "::");
}
/*`
Now when we have that wonderfull function, we can do static assertions and other compile-time validations:
*/
namespace my_project {
struct serializer {
template <class T>
void serialize(const T& value) {
static_assert(
in_namespace<T>("my_project::types") || in_namespace<T>("my_project::types_ext"),
"Only types from namespaces `my_project::types` and `my_project::types_ext` are allowed to be serialized using `my_project::serializer`"
);
// Actual implementation of the serialization goes below
// ...
do_something(value);
}
};
namespace types {
struct foo{};
struct bar{};
}
} // namespace my_project
int main() {
my_project::serializer s;
my_project::types::foo f;
my_project::types::bar b;
s.serialize(f);
s.serialize(b);
// short sh = 0;
// s.serialize(sh); // Fails the static_assert!
}
//] [/type_index_constexpr14_namespace_example]
#else // #if !defined(BOOST_NO_CXX14_CONSTEXPR) && !defined(BOOST_NO_CXX11_CONSTEXPR)
int main() {}
#endif

View File

@ -0,0 +1,76 @@
// Copyright 2013-2022 Antony Polukhin
// Distributed under the Boost Software License, Version 1.0.
// (See the accompanying file LICENSE_1_0.txt
// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
#include <boost/config.hpp>
#if !defined(BOOST_NO_CXX14_CONSTEXPR) && !defined(BOOST_NO_CXX11_CONSTEXPR) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && (!defined(_MSC_VER) || (_MSC_VER > 1916))
//[type_index_constexpr14_sort_check_example
/*`
The following example shows that `boost::typeindex::ctti_type_index` is usable at compile time on
a C++14 compatible compilers to check order of template parameters.
Consider the situation when we have a function that accepts std::tuple, boost::variant or some other class that uses variadic templates:
*/
template <class... T> class types{};
template <class... T>
void do_something(const types<T...>& t) noexcept;
/*`
Such functions may be very usefull, however they may significantly increase the size of the resulting program. Each instantionation of such function with different templates order
consumes space in the resulting program:
// Types are same, but different order leads to new instantionation of do_something function.
types<bool, double, int>
types<bool, int, double>
types<int, bool, double>
types<int, double, bool>
types<double, int, bool>
types<double, bool, int>
One of the ways to reduce instantinations count is to force the types to have some order:
*/
#include <boost/type_index/ctti_type_index.hpp>
// Implementing type trait that returns true if the types are sorted lexographicaly
template <class... T>
constexpr bool is_asc_sorted(types<T...>) noexcept {
return true;
}
template <class Lhs, class Rhs, class... TN>
constexpr bool is_asc_sorted(types<Lhs, Rhs, TN...>) noexcept {
using namespace boost::typeindex;
return ctti_type_index::type_id<Lhs>() <= ctti_type_index::type_id<Rhs>()
&& is_asc_sorted(types<Rhs, TN...>());
}
// Using the newly created `is_asc_sorted` trait:
template <class... T>
void do_something(const types<T...>& /*value*/) noexcept {
static_assert(
is_asc_sorted( types<T...>() ),
"T... for do_something(const types<T...>& t) must be sorted ascending"
);
}
int main() {
do_something( types<bool, double, int>() );
// do_something( types<bool, int, double>() ); // Fails the static_assert!
}
//] [/type_index_constexpr14_sort_check_example]
#else // #if !defined(BOOST_NO_CXX14_CONSTEXPR) && !defined(BOOST_NO_CXX11_CONSTEXPR) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && (!defined(_MSC_VER) || (_MSC_VER > 1916))
int main() {}
#endif

View File

@ -0,0 +1,76 @@
// Copyright 2013-2022 Antony Polukhin
// Distributed under the Boost Software License, Version 1.0.
// (See the accompanying file LICENSE_1_0.txt
// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
//[type_index_names_example
/*`
The following example shows how short (mangled) and human readable type names could be obtained from a type.
Works with and without RTTI.
*/
#include <boost/type_index.hpp>
#include <iostream>
template <class T>
void foo(T) {
std::cout << "\n Short name: " << boost::typeindex::type_id<T>().raw_name();
std::cout << "\n Readable name: " << boost::typeindex::type_id<T>().pretty_name();
}
struct user_defined_type{};
namespace ns1 { namespace ns2 {
struct user_defined_type{};
}} // namespace ns1::ns2
namespace {
struct in_anon_type{};
} // anonymous namespace
int main() {
// Call to
foo(1);
// will output something like this:
//
// (RTTI on) (RTTI off)
// Short name: i Short name: int]
// Readable name: int Readable name: int
user_defined_type t;
foo(t);
// Will output:
//
// (RTTI on) (RTTI off)
// Short name: 17user_defined_type user_defined_type]
// Readable name: user_defined_type user_defined_type
ns1::ns2::user_defined_type t_in_ns;
foo(t_in_ns);
// Will output:
//
// (RTTI on) (RTTI off)
// Short name: N3ns13ns217user_defined_typeE ns1::ns2::user_defined_type]
// Readable name: ns1::ns2::user_defined_type ns1::ns2::user_defined_type
in_anon_type anon_t;
foo(anon_t);
// Will output:
//
// (RTTI on) (RTTI off)
// Short name: N12_GLOBAL__N_112in_anon_typeE {anonymous}::in_anon_type]
// Readable name: (anonymous namespace)::in_anon_type {anonymous}::in_anon_type
}
/*`
Short names are very compiler dependant: some compiler will output `.H`, others `i`.
Readable names may also differ between compilers: `struct user_defined_type`, `user_defined_type`.
[warning With RTTI off different classes with same names in anonymous namespace may collapse. See 'RTTI emulation limitations'. ]
*/
//] [/type_index_names_example]

View File

@ -1,4 +1,4 @@
// Copyright 2013 Antony Polukhin
// Copyright 2013-2022 Antony Polukhin
// Distributed under the Boost Software License, Version 1.0.
// (See the accompanying file LICENSE_1_0.txt
@ -6,33 +6,50 @@
//[type_index_exact_type_match_example
/*`
The following example shows that `boost::type_index` (and `boost::type_info`) is able to store the exact type,
The following example shows that `type_index` (and `type_info`) is able to store the exact type,
without stripping const, volatile and references. Example works with and without RTTI.
In this example we'll create a class, that stores pointer to function and remembers the exact type of a
parameter that function accepts. When an attempt to call the stored function will be made, type of input
parameter will be checked for exact match with initaily erased type of function.
In this example we'll create a class that stores a pointer to function and remembers the exact type of the
parameter the function accepts. When the call to the bound function is made, he actual input parameter
type is checked against the stored parameter type and an exception is thrown in case of mismatch.
*/
#include <boost/type_index/type_index.hpp>
#include <boost/type_index.hpp>
#include <iostream>
#include <stdexcept>
#include <cstdlib>
//<-
// Making `#include <cassert>` visible in docs, while actually using hand-made check
// instead of `assert`. This is required to verify correct behavior even if NDEBUG
// is defined and to avoid `unused local variable` warnings with defined NDEBUG.
//
// boost-no-inspect
#ifdef assert
# undef assert
#endif
#define assert(X) if (!(X)) std::exit(__LINE__)
/* !Comment block is not closed intentionaly!
//->
#include <cassert>
//<-
!Closing comment block! */
//->
class type_erased_unary_function {
void* function_ptr_;
boost::type_index exact_param_t_;
void* function_ptr_;
boost::typeindex::type_index exact_param_t_;
public:
template <class ParamT>
type_erased_unary_function(void(*ptr)(ParamT))
: function_ptr_(reinterpret_cast<void*>(ptr)) // ptr - is a pointer to function returning `void` and accepting parameter of type `ParamT`
, exact_param_t_(boost::type_id_with_cvr<ParamT>())
, exact_param_t_(boost::typeindex::type_id_with_cvr<ParamT>())
{}
template <class ParamT>
void call(ParamT v) {
if (exact_param_t_ != boost::type_id_with_cvr<ParamT>()) {
if (exact_param_t_ != boost::typeindex::type_id_with_cvr<ParamT>()) {
throw std::runtime_error("Incorrect `ParamT`");
}
@ -50,7 +67,7 @@ int main() {
int i = 100;
// An attempt to convert stored function to a function accepting reference
func.call<int&>(i); // Will throw, because types `int&` and `int` missmatch
func.call<int&>(i); // Will throw, because types `int&` and `int` mismatch
assert(false);
} catch (const std::runtime_error& /*e*/) {}

47
examples/inheritance.cpp Normal file
View File

@ -0,0 +1,47 @@
// Copyright 2013-2022 Antony Polukhin
// Distributed under the Boost Software License, Version 1.0.
// (See the accompanying file LICENSE_1_0.txt
// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
//[type_index_derived_example
/*`
The following example shows that `type_info` is able to store the real type, successfully getting through
all the inheritances.
Example works with and without RTTI."
*/
#include <boost/type_index.hpp>
#include <boost/type_index/runtime_cast/register_runtime_class.hpp>
#include <iostream>
struct A {
BOOST_TYPE_INDEX_REGISTER_CLASS
virtual ~A(){}
};
struct B: public A { BOOST_TYPE_INDEX_REGISTER_CLASS };
struct C: public B { BOOST_TYPE_INDEX_REGISTER_CLASS };
struct D: public C { BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(BOOST_TYPE_INDEX_NO_BASE_CLASS) };
void print_real_type(const A& a) {
std::cout << boost::typeindex::type_id_runtime(a).pretty_name() << '\n';
}
int main() {
C c;
const A& c_as_a = c;
print_real_type(c_as_a); // Outputs `struct C`
print_real_type(B()); // Outputs `struct B`
/*`
It's also possible to use type_id_runtime with the BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS, which adds additional
information for runtime_cast to work.
*/
D d;
const A& d_as_a = d;
print_real_type(d_as_a); // Outputs `struct D`
}
//] [/type_index_derived_example]

55
examples/registry.cpp Normal file
View File

@ -0,0 +1,55 @@
// Copyright 2013-2022 Antony Polukhin
// Distributed under the Boost Software License, Version 1.0.
// (See the accompanying file LICENSE_1_0.txt
// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
//[type_index_registry_example
/*`
The following example shows how an information about a type could be stored.
Example works with and without RTTI.
*/
#include <boost/type_index.hpp>
#include <boost/unordered/unordered_set.hpp>
//<-
// Making `#include <cassert>` visible in docs, while actually using `BOOST_TEST`
// instead of `assert`. This is required to verify correct behavior even if NDEBUG
// is defined and to avoid `unused local variable` warnings with defined NDEBUG.
//
// boost-no-inspect
#include <boost/core/lightweight_test.hpp>
#ifdef assert
# undef assert
#endif
#define assert(X) BOOST_TEST(X)
/* !Comment block is not closed intentionaly!
//->
#include <cassert>
//<-
!Closing comment block! */
//->
int main() {
boost::unordered_set<boost::typeindex::type_index> types;
// Storing some `boost::type_info`s
types.insert(boost::typeindex::type_id<int>());
types.insert(boost::typeindex::type_id<float>());
// `types` variable contains two `boost::type_index`es:
assert(types.size() == 2);
// Const, volatile and reference will be striped from the type:
bool is_inserted = types.insert(boost::typeindex::type_id<const int>()).second;
assert(!is_inserted);
assert(types.erase(boost::typeindex::type_id<float&>()) == 1);
// We have erased the `float` type, only `int` remains
assert(*types.begin() == boost::typeindex::type_id<int>());
//<-
return boost::report_errors();
//->
}
//] [/type_index_registry_example]

90
examples/runtime_cast.cpp Normal file
View File

@ -0,0 +1,90 @@
//
// Copyright (c) Chris Glover, 2016.
//
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
//[type_index_runtime_cast_example
/*`
The following example shows that `runtime_cast` is able to find a valid pointer
in various class hierarchies regardless of inheritance or type relation.
Example works with and without RTTI."
*/
#include <boost/type_index/runtime_cast.hpp>
#include <iostream>
struct A {
BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(BOOST_TYPE_INDEX_NO_BASE_CLASS)
virtual ~A()
{}
};
struct B {
BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(BOOST_TYPE_INDEX_NO_BASE_CLASS)
virtual ~B()
{}
};
struct C : A {
BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS((A))
};
struct D : B {
BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS((B))
};
struct E : C, D {
BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS((C)(D))
};
int main() {
C c;
A* a = &c;
if(C* cp = boost::typeindex::runtime_cast<C*>(a)) {
std::cout << "Yes, a points to a C: "
<< a << "->" << cp << '\n';
}
else {
std::cout << "Error: Expected a to point to a C" << '\n';
}
if(E* ce = boost::typeindex::runtime_cast<E*>(a)) {
std::cout << "Error: Expected a to not points to an E: "
<< a << "->" << ce << '\n';
}
else {
std::cout << "But, a does not point to an E" << '\n';
}
E e;
C* cp2 = &e;
if(D* dp = boost::typeindex::runtime_cast<D*>(cp2)) {
std::cout << "Yes, we can cross-cast from a C* to a D* when we actually have an E: "
<< cp2 << "->" << dp << '\n';
}
else {
std::cout << "Error: Expected cp to point to a D" << '\n';
}
/*`
Alternatively, we can use runtime_pointer_cast so we don't need to specity the target as a pointer.
This works for smart_ptr types too.
*/
A* ap = &e;
if(B* bp = boost::typeindex::runtime_pointer_cast<B>(ap)) {
std::cout << "Yes, we can cross-cast and up-cast at the same time."
<< ap << "->" << bp << '\n';
}
else {
std::cout << "Error: Expected ap to point to a B" << '\n';
}
return 0;
}
//] [/type_index_runtime_cast_example]

View File

@ -0,0 +1,90 @@
// Copyright 2013-2022 Antony Polukhin
// Distributed under the Boost Software License, Version 1.0.
// (See the accompanying file LICENSE_1_0.txt
// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
//[type_index_names_table
/*`
The following example shows how different type names look when we explicitly use classes for RTTI and RTT off.
This example requires RTTI. For a more portable example see 'Getting human readable and mangled type names':
*/
#include <boost/type_index/stl_type_index.hpp>
#include <boost/type_index/ctti_type_index.hpp>
#include <iostream>
template <class T>
void print(const char* name) {
boost::typeindex::stl_type_index sti = boost::typeindex::stl_type_index::type_id<T>();
boost::typeindex::ctti_type_index cti = boost::typeindex::ctti_type_index::type_id<T>();
std::cout << "\t[" /* start of the row */
<< "[" << name << "]"
<< "[`" << sti.raw_name() << "`] "
<< "[`" << sti.pretty_name() << "`] "
<< "[`" << cti.raw_name() << "`] "
<< "]\n" /* end of the row */ ;
}
struct user_defined_type{};
namespace ns1 { namespace ns2 {
struct user_defined_type{};
}} // namespace ns1::ns2
namespace {
struct in_anon_type{};
} // anonymous namespace
namespace ns3 { namespace { namespace ns4 {
struct in_anon_type{};
}}} // namespace ns3::{anonymous}::ns4
template <class T0, class T1>
class templ {};
template <>
class templ<int, int> {};
int main() {
std::cout << "[table:id Table of names\n";
std::cout << "\t[[Type] [RTTI & raw_name] [RTTI & pretty_name] [noRTTI & raw_name]]\n";
print<user_defined_type>("User defined type");
print<in_anon_type>("In anonymous namespace");
print<ns3::ns4::in_anon_type>("In ns3::{anonymous}::ns4 namespace");
print<templ<short, int> >("Template class");
print<templ<int, int> >("Template class (full specialization)");
print<templ<
templ<char, signed char>,
templ<int, user_defined_type>
> >("Template class with templae classes");
std::cout << "]\n";
}
/*`
Code from the example will produce the following table:
[table:id Table of names
[[Type] [RTTI & raw_name] [RTTI & pretty_name] [noRTTI & raw_name]]
[[User defined type][`17user_defined_type`] [`user_defined_type`] [`user_defined_type]`] ]
[[In anonymous namespace][`N12_GLOBAL__N_112in_anon_typeE`] [`(anonymous namespace)::in_anon_type`] [`{anonymous}::in_anon_type]`] ]
[[In ns3::{anonymous}::ns4 namespace][`N3ns312_GLOBAL__N_13ns412in_anon_typeE`] [`ns3::(anonymous namespace)::ns4::in_anon_type`] [`ns3::{anonymous}::ns4::in_anon_type]`] ]
[[Template class][`5templIsiE`] [`templ<short, int>`] [`templ<short int, int>]`] ]
[[Template class (full specialization)][`5templIiiE`] [`templ<int, int>`] [`templ<int, int>]`] ]
[[Template class with template classes][`5templIS_IcaES_Ii17user_defined_typeEE`] [`templ<templ<char, signed char>, templ<int, user_defined_type> >`] [`templ<templ<char, signed char>, templ<int, user_defined_type> >]`] ]
]
We have not show the "noRTTI & pretty_name" column in the table because it is almost equal
to "noRTTI & raw_name" column.
[warning With RTTI off different classes with same names in anonymous namespace may collapse. See 'RTTI emulation limitations'. ]
*/
//] [/type_index_names_table]

View File

@ -0,0 +1,73 @@
// Copyright 2013-2022 Antony Polukhin
// Distributed under the Boost Software License, Version 1.0.
// (See the accompanying file LICENSE_1_0.txt
// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
//[type_index_my_type_index_worldwide_macro
/*`
There is an easy way to force `boost::typeindex::type_id` to use your own type_index class.
All we need to do is just define `BOOST_TYPE_INDEX_USER_TYPEINDEX` to the full path to header file
of your type index class:
*/
// BOOST_TYPE_INDEX_USER_TYPEINDEX must be defined *BEFORE* first inclusion of <boost/type_index.hpp>
#define BOOST_TYPE_INDEX_USER_TYPEINDEX <boost/../libs/type_index/examples/user_defined_typeinfo.hpp>
#include <boost/type_index.hpp>
//] [/type_index_my_type_index_worldwide_macro]
// boost-no-inspect
#include <boost/core/lightweight_test.hpp>
#ifdef assert
# undef assert
#endif
#define assert(X) BOOST_TEST(X)
using namespace my_namespace;
int main() {
//[type_index_my_type_index_usage
/*`
Finally we can use the my_type_index class for getting type indexes:
*/
my_type_index
cl1 = my_type_index::type_id<my_class>(),
st1 = my_type_index::type_id<my_struct>(),
st2 = my_type_index::type_id<my_struct>(),
vec = my_type_index::type_id<my_classes>()
;
assert(cl1 != st1);
assert(st2 == st1);
assert(vec.pretty_name() == "my_classes");
assert(cl1.pretty_name() == "my_class");
//] [/type_index_my_type_index_usage]
//[type_index_my_type_index_type_id_runtime_test
/*`
Now the following example will compile and work.
*/
my_struct str;
my_class& reference = str;
assert(my_type_index::type_id<my_struct>() == my_type_index::type_id_runtime(reference));
//][/type_index_my_type_index_type_id_runtime_test]
//[type_index_my_type_index_worldwide_usage
/*`
That's it! Now all TypeIndex global methods and typedefs will be using your class:
*/
boost::typeindex::type_index worldwide = boost::typeindex::type_id<my_classes>();
assert(worldwide.pretty_name() == "my_classes");
assert(worldwide == my_type_index::type_id<my_classes>());
//][/type_index_my_type_index_worldwide_usage]
//<-
return boost::report_errors();
//->
}

View File

@ -0,0 +1,213 @@
// Copyright 2013-2022 Antony Polukhin
// Distributed under the Boost Software License, Version 1.0.
// (See the accompanying file LICENSE_1_0.txt
// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
#ifndef USER_DEFINED_TYPEINFO_HPP
#define USER_DEFINED_TYPEINFO_HPP
//[type_index_userdefined_usertypes
/*`
The following example shows how a user defined type_info can be created and used.
Example works with and without RTTI.
Consider situation when user uses only those types in `typeid()`:
*/
#include <vector>
#include <string>
namespace my_namespace {
class my_class;
struct my_struct;
typedef std::vector<my_class> my_classes;
typedef std::string my_string;
} // namespace my_namespace
//] [/type_index_userdefined_usertypes]
//[type_index_userdefined_enum
/*`
In that case user may wish to save space in binary and create it's own type system.
For that case `detail::typenum<>` meta function is added. Depending on the input type T
this function will return different numeric values.
*/
#include <boost/type_index/type_index_facade.hpp>
namespace my_namespace { namespace detail {
template <class T> struct typenum;
template <> struct typenum<void>{ enum {value = 0}; };
template <> struct typenum<my_class>{ enum {value = 1}; };
template <> struct typenum<my_struct>{ enum {value = 2}; };
template <> struct typenum<my_classes>{ enum {value = 3}; };
template <> struct typenum<my_string>{ enum {value = 4}; };
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable: 4510 4512 4610) // non-copyable non-constructable type
#endif
// my_typeinfo structure is used to save type number
struct my_typeinfo {
const char* const type_;
};
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
const my_typeinfo infos[5] = {
{"void"}, {"my_class"}, {"my_struct"}, {"my_classes"}, {"my_string"}
};
template <class T>
inline const my_typeinfo& my_typeinfo_construct() {
return infos[typenum<T>::value];
}
}} // my_namespace::detail
//] [/type_index_userdefined_usertypes]
//[type_index_my_type_index
/*`
`my_type_index` is a user created type_index class. If in doubt during this phase, you can always
take a look at the `<boost/type_index/ctti_type_index.hpp>` or `<boost/type_index/stl_type_index.hpp>`
files. Documentation for `type_index_facade` could be also useful.
*/
/*`
Since we are not going to override `type_index_facade::hash_code()` we must additionally include
`<boost/container_hash/hash.hpp>`.
*/
#include <boost/container_hash/hash.hpp>
/*`
See implementation of `my_type_index`:
*/
namespace my_namespace {
class my_type_index: public boost::typeindex::type_index_facade<my_type_index, detail::my_typeinfo> {
const detail::my_typeinfo* data_;
public:
typedef detail::my_typeinfo type_info_t;
inline my_type_index() BOOST_NOEXCEPT
: data_(&detail::my_typeinfo_construct<void>())
{}
inline my_type_index(const type_info_t& data) BOOST_NOEXCEPT
: data_(&data)
{}
inline const type_info_t& type_info() const BOOST_NOEXCEPT {
return *data_;
}
inline const char* raw_name() const BOOST_NOEXCEPT {
return data_->type_;
}
inline std::string pretty_name() const {
return data_->type_;
}
template <class T>
inline static my_type_index type_id() BOOST_NOEXCEPT {
return detail::my_typeinfo_construct<T>();
}
template <class T>
inline static my_type_index type_id_with_cvr() BOOST_NOEXCEPT {
return detail::my_typeinfo_construct<T>();
}
template <class T>
inline static my_type_index type_id_runtime(const T& variable) BOOST_NOEXCEPT;
};
} // namespace my_namespace
/*`
Note that we have used the boost::typeindex::type_index_facade class as base.
That class took care about all the helper function and operators (comparison, hashing, ostreaming and others).
*/
//] [/type_index_my_type_index]
//[type_index_my_type_index_register_class
/*`
Usually to allow runtime type info we need to register class with some macro.
Let's see how a `MY_TYPEINDEX_REGISTER_CLASS` macro could be implemented for our `my_type_index` class:
*/
namespace my_namespace { namespace detail {
template <class T>
inline const my_typeinfo& my_typeinfo_construct_ref(const T*) {
return my_typeinfo_construct<T>();
}
#define MY_TYPEINDEX_REGISTER_CLASS \
virtual const my_namespace::detail::my_typeinfo& type_id_runtime() const { \
return my_namespace::detail::my_typeinfo_construct_ref(this); \
}
}} // namespace my_namespace::detail
//] [/type_index_my_type_index_register_class]
//[type_index_my_type_index_type_id_runtime_implmentation
/*`
Now when we have a MY_TYPEINDEX_REGISTER_CLASS, let's implement a `my_type_index::type_id_runtime` method:
*/
namespace my_namespace {
template <class T>
my_type_index my_type_index::type_id_runtime(const T& variable) BOOST_NOEXCEPT {
// Classes that were marked with `MY_TYPEINDEX_REGISTER_CLASS` will have a
// `type_id_runtime()` method.
return variable.type_id_runtime();
}
}
//] [/type_index_my_type_index_type_id_runtime_implmentation]
//[type_index_my_type_index_type_id_runtime_classes
/*`
Consider the situation, when `my_class` and `my_struct` are polymorphic classes:
*/
namespace my_namespace {
class my_class {
public:
MY_TYPEINDEX_REGISTER_CLASS
virtual ~my_class() {}
};
struct my_struct: public my_class {
MY_TYPEINDEX_REGISTER_CLASS
};
} // namespace my_namespace
//] [/type_index_my_type_index_type_id_runtime_classes]
//[type_index_my_type_index_worldwide_typedefs
/*`
You'll also need to add some typedefs and macro to your "user_defined_typeinfo.hpp" header file:
*/
#define BOOST_TYPE_INDEX_REGISTER_CLASS MY_TYPEINDEX_REGISTER_CLASS
namespace boost { namespace typeindex {
typedef my_namespace::my_type_index type_index;
}}
//] [/type_index_my_type_index_worldwide_typedefs]
#endif // USER_DEFINED_TYPEINFO_HPP

View File

@ -0,0 +1,265 @@
//
// Copyright 2012-2022 Antony Polukhin.
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_TYPE_INDEX_HPP
#define BOOST_TYPE_INDEX_HPP
/// \file boost/type_index.hpp
/// \brief Includes minimal set of headers required to use the Boost.TypeIndex library.
///
/// By inclusion of this file most optimal type index classes will be included and used
/// as a boost::typeindex::type_index and boost::typeindex::type_info.
#include <boost/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif
#if defined(BOOST_TYPE_INDEX_USER_TYPEINDEX)
# include BOOST_TYPE_INDEX_USER_TYPEINDEX
# ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH
# pragma detect_mismatch( "boost__type_index__abi", "user defined type_index class is used: " BOOST_STRINGIZE(BOOST_TYPE_INDEX_USER_TYPEINDEX))
# endif
#elif (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC)
# include <boost/type_index/stl_type_index.hpp>
# if defined(BOOST_NO_RTTI) || defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)
# include <boost/type_index/detail/stl_register_class.hpp>
# ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH
# pragma detect_mismatch( "boost__type_index__abi", "RTTI is off - typeid() is used only for templates")
# endif
# else
# ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH
# pragma detect_mismatch( "boost__type_index__abi", "RTTI is used")
# endif
# endif
#else
# include <boost/type_index/ctti_type_index.hpp>
# include <boost/type_index/detail/ctti_register_class.hpp>
# ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH
# pragma detect_mismatch( "boost__type_index__abi", "RTTI is off - using CTTI")
# endif
#endif
#ifndef BOOST_TYPE_INDEX_REGISTER_CLASS
#define BOOST_TYPE_INDEX_REGISTER_CLASS
#endif
namespace boost { namespace typeindex {
#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
/// \def BOOST_TYPE_INDEX_FUNCTION_SIGNATURE
/// BOOST_TYPE_INDEX_FUNCTION_SIGNATURE is used by boost::typeindex::ctti_type_index class to
/// deduce the name of a type. If your compiler is not recognized
/// by the TypeIndex library and you wish to work with boost::typeindex::ctti_type_index, you may
/// define this macro by yourself.
///
/// BOOST_TYPE_INDEX_FUNCTION_SIGNATURE must be defined to a compiler specific macro
/// that outputs the \b whole function signature \b including \b template \b parameters.
///
/// If your compiler is not recognised and BOOST_TYPE_INDEX_FUNCTION_SIGNATURE is not defined,
/// then a compile-time error will arise at any attempt to use boost::typeindex::ctti_type_index classes.
///
/// See BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS and BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING
/// for an information of how to tune the implementation to make a nice pretty_name() output.
#define BOOST_TYPE_INDEX_FUNCTION_SIGNATURE BOOST_CURRENT_FUNCTION
/// \def BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING
/// This is a helper macro for making correct pretty_names() with RTTI off.
///
/// BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING macro may be defined to
/// '(begin_skip, end_skip, runtime_skip, runtime_skip_until)' with parameters for adding a
/// support for compilers, that by default are not recognized by TypeIndex library.
///
/// \b Example:
///
/// Imagine the situation when
/// \code boost::typeindex::ctti_type_index::type_id<int>().pretty_name() \endcode
/// returns the following string:
/// \code "static const char *boost::detail::ctti<int>::n() [T = int]" \endcode
/// and \code boost::typeindex::ctti_type_index::type_id<short>().pretty_name() \endcode returns the following:
/// \code "static const char *boost::detail::ctti<short>::n() [T = short]" \endcode
///
/// As we may see first 39 characters are "static const char *boost::detail::ctti<" and they do not depend on
/// the type T. After first 39 characters we have a human readable type name which is duplicated at the end
/// of a string. String always ends on ']', which consumes 1 character.
///
/// Now if we define `BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING` to
/// `(39, 1, false, "")` we'll be getting \code "int>::n() [T = int" \endcode
/// for `boost::typeindex::ctti_type_index::type_id<int>().pretty_name()` and \code "short>::n() [T = short" \endcode
/// for `boost::typeindex::ctti_type_index::type_id<short>().pretty_name()`.
///
/// Now we need to take additional care of the characters that go before the last mention of our type. We'll
/// do that by telling the macro that we need to cut off everything that goes before the "T = " including the "T = "
/// itself:
///
/// \code (39, 1, true, "T = ") \endcode
///
/// In case of GCC or Clang command line we need to add the following line while compiling all the sources:
///
/// \code
/// -DBOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING='(39, 1, true, "T = ")'
/// \endcode
/// \param begin_skip How many characters must be skipped at the beginning of the type holding string.
/// Must be a compile time constant.
/// \param end_skip How many characters must be skipped at the end of the type holding string.
/// Must be a compile time constant.
/// \param runtime_skip Do we need additional checks at runtime to cut off the more characters.
/// Must be `true` or `false`.
/// \param runtime_skip_until Skip all the characters before the following string (including the string itself).
/// Must be a compile time array of characters.
///
/// See [RTTI emulation limitations](boost_typeindex/rtti_emulation_limitations.html) for more info.
#define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING (0, 0, false, "")
/// Depending on a compiler flags, optimal implementation of type_index will be used
/// as a default boost::typeindex::type_index.
///
/// Could be a boost::typeindex::stl_type_index, boost::typeindex::ctti_type_index or
/// user defined type_index class.
///
/// \b See boost::typeindex::type_index_facade for a full description of type_index functions.
typedef platform_specific type_index;
#elif defined(BOOST_TYPE_INDEX_USER_TYPEINDEX)
// Nothing to do
#elif (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC)
typedef boost::typeindex::stl_type_index type_index;
#else
typedef boost::typeindex::ctti_type_index type_index;
#endif
/// Depending on a compiler flags, optimal implementation of type_info will be used
/// as a default boost::typeindex::type_info.
///
/// Could be a std::type_info, boost::typeindex::detail::ctti_data or
/// some user defined class.
///
/// type_info \b is \b not copyable or default constructible. It is \b not assignable too!
typedef type_index::type_info_t type_info;
#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
/// \def BOOST_TYPE_INDEX_USER_TYPEINDEX
/// BOOST_TYPE_INDEX_USER_TYPEINDEX can be defined to the path to header file
/// with user provided implementation of type_index.
///
/// See [Making a custom type_index](boost_typeindex/making_a_custom_type_index.html) section
/// of documentation for usage example.
#define BOOST_TYPE_INDEX_USER_TYPEINDEX <full/absolute/path/to/header/with/type_index.hpp>
/// \def BOOST_TYPE_INDEX_REGISTER_CLASS
/// BOOST_TYPE_INDEX_REGISTER_CLASS is used to help to emulate RTTI.
/// Put this macro into the public section of polymorphic class to allow runtime type detection.
///
/// Depending on the typeid() availability this macro will expand to nothing or to virtual helper function
/// `virtual const type_info& boost_type_info_type_id_runtime_() const noexcept`.
///
/// \b Example:
/// \code
/// class A {
/// public:
/// BOOST_TYPE_INDEX_REGISTER_CLASS
/// virtual ~A(){}
/// };
///
/// struct B: public A {
/// BOOST_TYPE_INDEX_REGISTER_CLASS
/// };
///
/// struct C: public B {
/// BOOST_TYPE_INDEX_REGISTER_CLASS
/// };
///
/// ...
///
/// C c1;
/// A* pc1 = &c1;
/// assert(boost::typeindex::type_id<C>() == boost::typeindex::type_id_runtime(*pc1));
/// \endcode
#define BOOST_TYPE_INDEX_REGISTER_CLASS nothing-or-some-virtual-functions
/// \def BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY
/// BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY is a helper macro that must be defined if mixing
/// RTTI on/off modules. See
/// [Mixing sources with RTTI on and RTTI off](boost_typeindex/mixing_sources_with_rtti_on_and_.html)
/// section of documentation for more info.
#define BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY
#endif // defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
/// Function to get boost::typeindex::type_index for a type T.
/// Removes const, volatile && and & modifiers from T.
///
/// \b Example:
/// \code
/// type_index ti = type_id<int&>();
/// std::cout << ti.pretty_name(); // Outputs 'int'
/// \endcode
///
/// \tparam T Type for which type_index must be created.
/// \throw Nothing.
/// \return boost::typeindex::type_index with information about the specified type T.
template <class T>
inline type_index type_id() BOOST_NOEXCEPT {
return type_index::type_id<T>();
}
/// Function for constructing boost::typeindex::type_index instance for type T.
/// Does not remove const, volatile, & and && modifiers from T.
///
/// If T has no const, volatile, & and && modifiers, then returns exactly
/// the same result as in case of calling `type_id<T>()`.
///
/// \b Example:
/// \code
/// type_index ti = type_id_with_cvr<int&>();
/// std::cout << ti.pretty_name(); // Outputs 'int&'
/// \endcode
///
/// \tparam T Type for which type_index must be created.
/// \throw Nothing.
/// \return boost::typeindex::type_index with information about the specified type T.
template <class T>
inline type_index type_id_with_cvr() BOOST_NOEXCEPT {
return type_index::type_id_with_cvr<T>();
}
/// Function that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index.
///
/// Returns runtime information about specified type.
///
/// \b Requirements: RTTI available or Base and Derived classes must be marked with BOOST_TYPE_INDEX_REGISTER_CLASS.
///
/// \b Example:
/// \code
/// struct Base { virtual ~Base(){} };
/// struct Derived: public Base {};
/// ...
/// Derived d;
/// Base& b = d;
/// type_index ti = type_id_runtime(b);
/// std::cout << ti.pretty_name(); // Outputs 'Derived'
/// \endcode
///
/// \param runtime_val Variable which runtime type must be returned.
/// \throw Nothing.
/// \return boost::typeindex::type_index with information about the specified variable.
template <class T>
inline type_index type_id_runtime(const T& runtime_val) BOOST_NOEXCEPT {
return type_index::type_id_runtime(runtime_val);
}
}} // namespace boost::typeindex
#endif // BOOST_TYPE_INDEX_HPP

View File

@ -0,0 +1,213 @@
//
// Copyright 2013-2022 Antony Polukhin.
//
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_TYPE_INDEX_CTTI_TYPE_INDEX_HPP
#define BOOST_TYPE_INDEX_CTTI_TYPE_INDEX_HPP
/// \file ctti_type_index.hpp
/// \brief Contains boost::typeindex::ctti_type_index class that is constexpr if C++14 constexpr is supported by compiler.
///
/// boost::typeindex::ctti_type_index class can be used as a drop-in replacement
/// for std::type_index.
///
/// It is used in situations when typeid() method is not available or
/// BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY macro is defined.
#include <boost/type_index/type_index_facade.hpp>
#include <boost/type_index/detail/compile_time_type_info.hpp>
#include <cstring>
#include <boost/container_hash/hash.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_reference.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif
namespace boost { namespace typeindex {
namespace detail {
// That's the most trickiest part of the TypeIndex library:
// 1) we do not want to give user ability to manually construct and compare `struct-that-represents-type`
// 2) we need to distinguish between `struct-that-represents-type` and `const char*`
// 3) we need a thread-safe way to have references to instances `struct-that-represents-type`
// 4) we need a compile-time control to make sure that user does not copy or
// default construct `struct-that-represents-type`
//
// Solution would be the following:
/// \class ctti_data
/// Standard-layout class with private constructors and assignment operators.
///
/// You can not work with this class directly. The purpose of this class is to hold type info
/// \b when \b RTTI \b is \b off and allow ctti_type_index construction from itself.
///
/// \b Example:
/// \code
/// const detail::ctti_data& foo();
/// ...
/// type_index ti = type_index(foo());
/// std::cout << ti.pretty_name();
/// \endcode
class ctti_data {
#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS
public:
ctti_data() = delete;
ctti_data(const ctti_data&) = delete;
ctti_data& operator=(const ctti_data&) = delete;
#else
private:
ctti_data();
ctti_data(const ctti_data&);
ctti_data& operator=(const ctti_data&);
#endif
};
} // namespace detail
/// Helper method for getting detail::ctti_data of a template parameter T.
template <class T>
inline const detail::ctti_data& ctti_construct() BOOST_NOEXCEPT {
// Standard C++11, 5.2.10 Reinterpret cast:
// An object pointer can be explicitly converted to an object pointer of a different type. When a prvalue
// v of type "pointer to T1" is converted to the type "pointer to cv T2", the result is static_cast<cv
// T2*>(static_cast<cv void*>(v)) if both T1 and T2 are standard-layout types (3.9) and the alignment
// requirements of T2 are no stricter than those of T1, or if either type is void. Converting a prvalue of type
// "pointer to T1" to the type "pointer to T2" (where T1 and T2 are object types and where the alignment
// requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer
// value.
//
// Alignments are checked in `type_index_test_ctti_alignment.cpp` test.
return *reinterpret_cast<const detail::ctti_data*>(boost::detail::ctti<T>::n());
}
/// \class ctti_type_index
/// This class is a wrapper that pretends to work exactly like stl_type_index, but does
/// not require RTTI support. \b For \b description \b of \b functions \b see type_index_facade.
///
/// This class on C++14 compatible compilers has following functions marked as constexpr:
/// * default constructor
/// * copy constructors and assignemnt operations
/// * class methods: name(), before(const ctti_type_index& rhs), equal(const ctti_type_index& rhs)
/// * static methods type_id<T>(), type_id_with_cvr<T>()
/// * comparison operators
///
/// This class produces slightly longer type names, so consider using stl_type_index
/// in situations when typeid() is working.
class ctti_type_index: public type_index_facade<ctti_type_index, detail::ctti_data> {
const char* data_;
inline std::size_t get_raw_name_length() const BOOST_NOEXCEPT;
BOOST_CXX14_CONSTEXPR inline explicit ctti_type_index(const char* data) BOOST_NOEXCEPT
: data_(data)
{}
public:
typedef detail::ctti_data type_info_t;
BOOST_CXX14_CONSTEXPR inline ctti_type_index() BOOST_NOEXCEPT
: data_(boost::detail::ctti<void>::n())
{}
inline ctti_type_index(const type_info_t& data) BOOST_NOEXCEPT
: data_(reinterpret_cast<const char*>(&data))
{}
inline const type_info_t& type_info() const BOOST_NOEXCEPT;
BOOST_CXX14_CONSTEXPR inline const char* raw_name() const BOOST_NOEXCEPT;
BOOST_CXX14_CONSTEXPR inline const char* name() const BOOST_NOEXCEPT;
inline std::string pretty_name() const;
inline std::size_t hash_code() const BOOST_NOEXCEPT;
BOOST_CXX14_CONSTEXPR inline bool equal(const ctti_type_index& rhs) const BOOST_NOEXCEPT;
BOOST_CXX14_CONSTEXPR inline bool before(const ctti_type_index& rhs) const BOOST_NOEXCEPT;
template <class T>
BOOST_CXX14_CONSTEXPR inline static ctti_type_index type_id() BOOST_NOEXCEPT;
template <class T>
BOOST_CXX14_CONSTEXPR inline static ctti_type_index type_id_with_cvr() BOOST_NOEXCEPT;
template <class T>
inline static ctti_type_index type_id_runtime(const T& variable) BOOST_NOEXCEPT;
};
inline const ctti_type_index::type_info_t& ctti_type_index::type_info() const BOOST_NOEXCEPT {
return *reinterpret_cast<const detail::ctti_data*>(data_);
}
BOOST_CXX14_CONSTEXPR inline bool ctti_type_index::equal(const ctti_type_index& rhs) const BOOST_NOEXCEPT {
const char* const left = raw_name();
const char* const right = rhs.raw_name();
return /*left == right ||*/ !boost::typeindex::detail::constexpr_strcmp(left, right);
}
BOOST_CXX14_CONSTEXPR inline bool ctti_type_index::before(const ctti_type_index& rhs) const BOOST_NOEXCEPT {
const char* const left = raw_name();
const char* const right = rhs.raw_name();
return /*left != right &&*/ boost::typeindex::detail::constexpr_strcmp(left, right) < 0;
}
template <class T>
BOOST_CXX14_CONSTEXPR inline ctti_type_index ctti_type_index::type_id() BOOST_NOEXCEPT {
typedef BOOST_DEDUCED_TYPENAME boost::remove_reference<T>::type no_ref_t;
typedef BOOST_DEDUCED_TYPENAME boost::remove_cv<no_ref_t>::type no_cvr_t;
return ctti_type_index(boost::detail::ctti<no_cvr_t>::n());
}
template <class T>
BOOST_CXX14_CONSTEXPR inline ctti_type_index ctti_type_index::type_id_with_cvr() BOOST_NOEXCEPT {
return ctti_type_index(boost::detail::ctti<T>::n());
}
template <class T>
inline ctti_type_index ctti_type_index::type_id_runtime(const T& variable) BOOST_NOEXCEPT {
return variable.boost_type_index_type_id_runtime_();
}
BOOST_CXX14_CONSTEXPR inline const char* ctti_type_index::raw_name() const BOOST_NOEXCEPT {
return data_;
}
BOOST_CXX14_CONSTEXPR inline const char* ctti_type_index::name() const BOOST_NOEXCEPT {
return data_;
}
inline std::size_t ctti_type_index::get_raw_name_length() const BOOST_NOEXCEPT {
return std::strlen(raw_name() + detail::ctti_skip_size_at_end);
}
inline std::string ctti_type_index::pretty_name() const {
std::size_t len = get_raw_name_length();
while (raw_name()[len - 1] == ' ') --len; // MSVC sometimes adds whitespaces
return std::string(raw_name(), len);
}
inline std::size_t ctti_type_index::hash_code() const BOOST_NOEXCEPT {
return boost::hash_range(raw_name(), raw_name() + get_raw_name_length());
}
}} // namespace boost::typeindex
#endif // BOOST_TYPE_INDEX_CTTI_TYPE_INDEX_HPP

View File

@ -0,0 +1,339 @@
//
// Copyright 2012-2022 Antony Polukhin.
//
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP
#define BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP
/// \file compile_time_type_info.hpp
/// \brief Contains helper macros and implementation details of boost::typeindex::ctti_type_index.
/// Not intended for inclusion from user's code.
#include <cstring>
#include <boost/config.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/integral_constant.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif
/// @cond
#if defined(__has_builtin)
#if __has_builtin(__builtin_constant_p)
#define BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT(x) __builtin_constant_p(x)
#endif
#if __has_builtin(__builtin_strcmp)
#define BOOST_TYPE_INDEX_DETAIL_BUILTIN_STRCMP(str1, str2) __builtin_strcmp(str1, str2)
#endif
#elif defined(__GNUC__)
#define BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT(x) __builtin_constant_p(x)
#define BOOST_TYPE_INDEX_DETAIL_BUILTIN_STRCMP(str1, str2) __builtin_strcmp(str1, str2)
#endif
#define BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(begin_skip, end_skip, runtime_skip, runtime_skip_until) \
namespace boost { namespace typeindex { namespace detail { \
BOOST_STATIC_CONSTEXPR std::size_t ctti_skip_size_at_begin = begin_skip; \
BOOST_STATIC_CONSTEXPR std::size_t ctti_skip_size_at_end = end_skip; \
BOOST_STATIC_CONSTEXPR bool ctti_skip_more_at_runtime = runtime_skip; \
BOOST_STATIC_CONSTEXPR char ctti_skip_until_runtime[] = runtime_skip_until; \
}}} /* namespace boost::typeindex::detail */ \
/**/
/// @endcond
#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
/* Nothing to document. All the macro docs are moved to <boost/type_index.hpp> */
#elif defined(BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING)
# include <boost/preprocessor/facilities/expand.hpp>
BOOST_PP_EXPAND( BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING )
#elif defined(_MSC_VER) && !defined(__clang__) && defined (BOOST_NO_CXX11_NOEXCEPT)
// sizeof("const char *__cdecl boost::detail::ctti<") - 1, sizeof(">::n(void)") - 1
BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(40, 10, false, "")
#elif defined(_MSC_VER) && !defined(__clang__) && !defined (BOOST_NO_CXX11_NOEXCEPT)
// sizeof("const char *__cdecl boost::detail::ctti<") - 1, sizeof(">::n(void) noexcept") - 1
BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(40, 19, false, "")
#elif defined(__clang__) && defined(__APPLE__)
// Someone made __clang_major__ equal to LLVM version rather than compiler version
// on APPLE platform.
//
// Using less efficient solution because there is no good way to detect real version of Clang.
// sizeof("static const char *boost::detail::ctti<") - 1, sizeof("]") - 1, true, "???????????>::n() [T = int"
BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(39, 1, true, "T = ")
#elif defined(__clang__) && (__clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ == 0))
// sizeof("static const char *boost::detail::ctti<") - 1, sizeof(">::n()") - 1
// note: checked on 3.0
BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(39, 6, false, "")
#elif defined(__clang__) && (__clang_major__ >= 4 || (__clang_major__ == 3 && __clang_minor__ > 0))
// sizeof("static const char *boost::detail::ctti<") - 1, sizeof("]") - 1, true, "int>::n() [T = int"
// note: checked on 3.1, 3.4
BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(39, 1, true, "T = ")
#elif defined(__EDG__) && !defined(BOOST_NO_CXX14_CONSTEXPR)
// sizeof("static cha boost::detail::ctti<T>::s() [with I = 40U, T = ") - 1, sizeof("]") - 1
// note: checked on 4.14
BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(58, 1, false, "")
#elif defined(__EDG__) && defined(BOOST_NO_CXX14_CONSTEXPR)
// sizeof("static const char *boost::detail::ctti<T>::n() [with T = ") - 1, sizeof("]") - 1
// note: checked on 4.14
BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(57, 1, false, "")
#elif defined(__GNUC__) && (__GNUC__ < 7) && !defined(BOOST_NO_CXX14_CONSTEXPR)
// sizeof("static constexpr char boost::detail::ctti<T>::s() [with unsigned int I = 0u; T = ") - 1, sizeof("]") - 1
BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(81, 1, false, "")
#elif defined(__GNUC__) && (__GNUC__ >= 7) && !defined(BOOST_NO_CXX14_CONSTEXPR)
// sizeof("static constexpr char boost::detail::ctti<T>::s() [with unsigned int I = 0; T = ") - 1, sizeof("]") - 1
BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(80, 1, false, "")
#elif defined(__GNUC__) && defined(BOOST_NO_CXX14_CONSTEXPR)
// sizeof("static const char* boost::detail::ctti<T>::n() [with T = ") - 1, sizeof("]") - 1
BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(57, 1, false, "")
#elif defined(__ghs__)
// sizeof("static const char *boost::detail::ctti<T>::n() [with T = ") - 1, sizeof("]") - 1
BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(57, 1, false, "")
#else
// Deafult code for other platforms... Just skip nothing!
BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(0, 0, false, "")
#endif
#undef BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS
namespace boost { namespace typeindex { namespace detail {
template <bool Condition>
BOOST_CXX14_CONSTEXPR inline void assert_compile_time_legths() BOOST_NOEXCEPT {
BOOST_STATIC_ASSERT_MSG(
Condition,
"TypeIndex library is misconfigured for your compiler. "
"Please define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING to correct values. See section "
"'RTTI emulation limitations' of the documentation for more information."
);
}
template <class T>
BOOST_CXX14_CONSTEXPR inline void failed_to_get_function_name() BOOST_NOEXCEPT {
BOOST_STATIC_ASSERT_MSG(
sizeof(T) && false,
"TypeIndex library could not detect your compiler. "
"Please make the BOOST_TYPE_INDEX_FUNCTION_SIGNATURE macro use "
"correct compiler macro for getting the whole function name. "
"Define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING to correct value after that."
);
}
#if defined(BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT)
BOOST_CXX14_CONSTEXPR BOOST_FORCEINLINE bool is_constant_string(const char* str) BOOST_NOEXCEPT {
while (BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT(*str)) {
if (*str == '\0')
return true;
++str;
}
return false;
}
#endif // defined(BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT)
template <unsigned int ArrayLength>
BOOST_CXX14_CONSTEXPR inline const char* skip_begining_runtime(const char* begin, boost::false_type) BOOST_NOEXCEPT {
return begin;
}
template<class ForwardIterator1, class ForwardIterator2>
BOOST_CXX14_CONSTEXPR inline ForwardIterator1 constexpr_search(
ForwardIterator1 first1,
ForwardIterator1 last1,
ForwardIterator2 first2,
ForwardIterator2 last2) BOOST_NOEXCEPT
{
if (first2 == last2) {
return first1; // specified in C++11
}
while (first1 != last1) {
ForwardIterator1 it1 = first1;
ForwardIterator2 it2 = first2;
while (*it1 == *it2) {
++it1;
++it2;
if (it2 == last2) return first1;
if (it1 == last1) return last1;
}
++first1;
}
return last1;
}
BOOST_CXX14_CONSTEXPR inline int constexpr_strcmp_loop(const char *v1, const char *v2) BOOST_NOEXCEPT {
while (*v1 != '\0' && *v1 == *v2) {
++v1;
++v2;
}
return static_cast<int>(*v1) - *v2;
}
BOOST_CXX14_CONSTEXPR inline int constexpr_strcmp(const char *v1, const char *v2) BOOST_NOEXCEPT {
#if !defined(BOOST_NO_CXX14_CONSTEXPR) && defined(BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT) && defined(BOOST_TYPE_INDEX_DETAIL_BUILTIN_STRCMP)
if (boost::typeindex::detail::is_constant_string(v1) && boost::typeindex::detail::is_constant_string(v2))
return boost::typeindex::detail::constexpr_strcmp_loop(v1, v2);
return BOOST_TYPE_INDEX_DETAIL_BUILTIN_STRCMP(v1, v2);
#elif !defined(BOOST_NO_CXX14_CONSTEXPR)
return boost::typeindex::detail::constexpr_strcmp_loop(v1, v2);
#else
return std::strcmp(v1, v2);
#endif
}
template <unsigned int ArrayLength>
BOOST_CXX14_CONSTEXPR inline const char* skip_begining_runtime(const char* begin, boost::true_type) BOOST_NOEXCEPT {
const char* const it = constexpr_search(
begin, begin + ArrayLength,
ctti_skip_until_runtime, ctti_skip_until_runtime + sizeof(ctti_skip_until_runtime) - 1
);
return (it == begin + ArrayLength ? begin : it + sizeof(ctti_skip_until_runtime) - 1);
}
template <unsigned int ArrayLength>
BOOST_CXX14_CONSTEXPR inline const char* skip_begining(const char* begin) BOOST_NOEXCEPT {
assert_compile_time_legths<(ArrayLength > ctti_skip_size_at_begin + ctti_skip_size_at_end)>();
return skip_begining_runtime<ArrayLength - ctti_skip_size_at_begin>(
begin + ctti_skip_size_at_begin,
boost::integral_constant<bool, ctti_skip_more_at_runtime>()
);
}
#if !defined(__clang__) && defined(__GNUC__) && !defined(BOOST_NO_CXX14_CONSTEXPR)
template <unsigned int... I>
struct index_seq {};
template <typename Left, typename Right>
struct make_index_sequence_join;
template <unsigned int... Left, unsigned int... Right>
struct make_index_sequence_join<index_seq<Left...>, index_seq<Right...> > {
typedef index_seq<Left..., Right...> type;
};
template <unsigned int C, unsigned int D>
struct make_index_seq_impl {
typedef typename make_index_sequence_join<
typename make_index_seq_impl<C, D / 2>::type,
typename make_index_seq_impl<C + D / 2, (D + 1) / 2>::type
>::type type;
};
template <unsigned int C>
struct make_index_seq_impl<C, 0> {
typedef index_seq<> type;
};
template <unsigned int C>
struct make_index_seq_impl<C, 1> {
typedef index_seq<C> type;
};
template <char... C>
struct cstring {
static constexpr unsigned int size_ = sizeof...(C);
static constexpr char data_[size_] = { C... };
};
template <char... C>
constexpr char cstring<C...>::data_[];
#endif
}}} // namespace boost::typeindex::detail
namespace boost { namespace detail {
/// Noncopyable type_info that does not require RTTI.
/// CTTI == Compile Time Type Info.
/// This name must be as short as possible, to avoid code bloat
template <class T>
struct ctti {
#if !defined(__clang__) && defined(__GNUC__) && !defined(BOOST_NO_CXX14_CONSTEXPR)
//helper functions
template <unsigned int I>
constexpr static char s() BOOST_NOEXCEPT { // step
constexpr unsigned int offset =
(I >= 10u ? 1u : 0u)
+ (I >= 100u ? 1u : 0u)
+ (I >= 1000u ? 1u : 0u)
+ (I >= 10000u ? 1u : 0u)
+ (I >= 100000u ? 1u : 0u)
+ (I >= 1000000u ? 1u : 0u)
;
#if defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE)
return BOOST_TYPE_INDEX_FUNCTION_SIGNATURE[I + offset];
#elif defined(__FUNCSIG__)
return __FUNCSIG__[I + offset];
#else
return __PRETTY_FUNCTION__[I + offset];
#endif
}
template <unsigned int ...Indexes>
constexpr static const char* impl(::boost::typeindex::detail::index_seq<Indexes...> ) BOOST_NOEXCEPT {
return ::boost::typeindex::detail::cstring<s<Indexes>()...>::data_;
}
template <unsigned int D = 0> // `D` means `Dummy`
constexpr static const char* n() BOOST_NOEXCEPT {
#if defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE)
constexpr unsigned int size = sizeof(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE);
#elif defined(__FUNCSIG__)
constexpr unsigned int size = sizeof(__FUNCSIG__);
#elif defined(__PRETTY_FUNCTION__) \
|| defined(__GNUC__) \
|| (defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x5130)) \
|| (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) \
|| (defined(__ICC) && (__ICC >= 600)) \
|| defined(__ghs__) \
|| defined(__DMC__)
constexpr unsigned int size = sizeof(__PRETTY_FUNCTION__);
#else
boost::typeindex::detail::failed_to_get_function_name<T>();
#endif
boost::typeindex::detail::assert_compile_time_legths<
(size > boost::typeindex::detail::ctti_skip_size_at_begin + boost::typeindex::detail::ctti_skip_size_at_end + sizeof("const *") - 1)
>();
static_assert(!boost::typeindex::detail::ctti_skip_more_at_runtime, "Skipping for GCC in C++14 mode is unsupported");
typedef typename boost::typeindex::detail::make_index_seq_impl<
boost::typeindex::detail::ctti_skip_size_at_begin,
size - sizeof("const *") + 1 - boost::typeindex::detail::ctti_skip_size_at_begin
>::type idx_seq;
return impl(idx_seq());
}
#else
/// Returns raw name. Must be as short, as possible, to avoid code bloat
BOOST_CXX14_CONSTEXPR static const char* n() BOOST_NOEXCEPT {
#if defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE)
return boost::typeindex::detail::skip_begining< sizeof(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE) >(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE);
#elif defined(__FUNCSIG__)
return boost::typeindex::detail::skip_begining< sizeof(__FUNCSIG__) >(__FUNCSIG__);
#elif defined(__PRETTY_FUNCTION__) \
|| defined(__GNUC__) \
|| (defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x5130)) \
|| (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) \
|| (defined(__ICC) && (__ICC >= 600)) \
|| defined(__ghs__) \
|| defined(__DMC__) \
|| defined(__clang__)
return boost::typeindex::detail::skip_begining< sizeof(__PRETTY_FUNCTION__) >(__PRETTY_FUNCTION__);
#else
boost::typeindex::detail::failed_to_get_function_name<T>();
return "";
#endif
}
#endif
};
}} // namespace boost::detail
#endif // BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP

View File

@ -0,0 +1,40 @@
//
// Copyright 2013-2022 Antony Polukhin.
//
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_TYPE_INDEX_CTTI_REGISTER_CLASS_HPP
#define BOOST_TYPE_INDEX_CTTI_REGISTER_CLASS_HPP
/// \file ctti_register_class.hpp
/// \brief Contains BOOST_TYPE_INDEX_REGISTER_CLASS macro implementation that uses boost::typeindex::ctti_type_index.
/// Not intended for inclusion from user's code.
#include <boost/type_index/ctti_type_index.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif
namespace boost { namespace typeindex { namespace detail {
template <class T>
inline const ctti_data& ctti_construct_typeid_ref(const T*) BOOST_NOEXCEPT {
return ctti_construct<T>();
}
}}} // namespace boost::typeindex::detail
/// @cond
#define BOOST_TYPE_INDEX_REGISTER_CLASS \
virtual const boost::typeindex::detail::ctti_data& boost_type_index_type_id_runtime_() const BOOST_NOEXCEPT { \
return boost::typeindex::detail::ctti_construct_typeid_ref(this); \
} \
/**/
/// @endcond
#endif // BOOST_TYPE_INDEX_CTTI_REGISTER_CLASS_HPP

View File

@ -0,0 +1,40 @@
//
// Copyright 2013-2022 Antony Polukhin.
//
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_TYPE_INDEX_STL_REGISTER_CLASS_HPP
#define BOOST_TYPE_INDEX_STL_REGISTER_CLASS_HPP
/// \file stl_register_class.hpp
/// \brief Contains BOOST_TYPE_INDEX_REGISTER_CLASS macro implementation that uses boost::typeindex::stl_type_index.
/// Not intended for inclusion from user's code.
#include <boost/type_index/stl_type_index.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif
namespace boost { namespace typeindex { namespace detail {
template <class T>
inline const stl_type_index::type_info_t& stl_construct_typeid_ref(const T*) BOOST_NOEXCEPT {
return typeid(T);
}
}}} // namespace boost::typeindex::detail
/// @cond
#define BOOST_TYPE_INDEX_REGISTER_CLASS \
virtual const boost::typeindex::stl_type_index::type_info_t& boost_type_index_type_id_runtime_() const BOOST_NOEXCEPT { \
return boost::typeindex::detail::stl_construct_typeid_ref(this); \
} \
/**/
/// @endcond
#endif // BOOST_TYPE_INDEX_STL_REGISTER_CLASS_HPP

View File

@ -0,0 +1,28 @@
//
// Copyright (c) Chris Glover, 2016.
//
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_TYPE_INDEX_RUNTIME_CAST_HPP
#define BOOST_TYPE_INDEX_RUNTIME_CAST_HPP
/// \file runtime_cast.hpp
/// \brief Contains the basic utilities necessary to fully emulate
/// dynamic_cast for language level constructs (raw pointers and references).
///
/// boost::typeindex::runtime_cast is a drop in replacement for dynamic_cast
/// that can be used in situations where traditional rtti is either unavailable
/// or undesirable.
#include <boost/type_index/runtime_cast/register_runtime_class.hpp>
#include <boost/type_index/runtime_cast/pointer_cast.hpp>
#include <boost/type_index/runtime_cast/reference_cast.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif
#endif // BOOST_TYPE_INDEX_RUNTIME_CAST_HPP

View File

@ -0,0 +1,49 @@
//
// Copyright (c) Chris Glover, 2016.
//
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_TYPE_INDEX_RUNTIME_CAST_BOOST_SHARED_PTR_CAST_HPP
#define BOOST_TYPE_INDEX_RUNTIME_CAST_BOOST_SHARED_PTR_CAST_HPP
/// \file boost_shared_ptr_cast.hpp
/// \brief Contains the overload of boost::typeindex::runtime_pointer_cast for
/// boost::shared_ptr types.
#include <boost/type_index/runtime_cast/detail/runtime_cast_impl.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif
namespace boost {
template<class T> class shared_ptr;
}
namespace boost { namespace typeindex {
/// \brief Creates a new instance of std::shared_ptr whose stored pointer is obtained from u's
/// stored pointer using a runtime_cast.
///
/// The new shared_ptr will share ownership with u, except that it is empty if the runtime_cast
/// performed by runtime_pointer_cast returns a null pointer.
/// \tparam T The desired target type to return a pointer of.
/// \tparam U A complete class type of the source instance pointed to from u.
/// \return If there exists a valid conversion from U* to T*, returns a boost::shared_ptr<T>
/// that points to an address suitably offset from u.
/// If no such conversion exists, returns boost::shared_ptr<T>();
template<typename T, typename U>
boost::shared_ptr<T> runtime_pointer_cast(boost::shared_ptr<U> const& u) {
T* value = detail::runtime_cast_impl<T>(u.get(), boost::is_base_and_derived<T, U>());
if(value)
return boost::shared_ptr<T>(u, value);
return boost::shared_ptr<T>();
}
}} // namespace boost::typeindex
#endif // BOOST_TYPE_INDEX_RUNTIME_CAST_BOOST_SHARED_PTR_CAST_HPP

View File

@ -0,0 +1,57 @@
//
// Copyright (c) Chris Glover, 2016.
//
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_TYPE_INDEX_RUNTIME_CAST_DETAIL_RUNTIME_CAST_IMPL_HPP
#define BOOST_TYPE_INDEX_RUNTIME_CAST_DETAIL_RUNTIME_CAST_IMPL_HPP
/// \file runtime_cast_impl.hpp
/// \brief Contains the overload of boost::typeindex::runtime_cast for
/// pointer types.
///
/// boost::typeindex::runtime_cast can be used to emulate dynamic_cast
/// functionality on platorms that don't provide it or should the user
/// desire opt in functionality instead of enabling it system wide.
#include <boost/type_index.hpp>
#include <boost/type_traits/integral_constant.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif
namespace boost { namespace typeindex {
namespace detail {
template<typename T, typename U>
T* runtime_cast_impl(U* u, boost::true_type) BOOST_NOEXCEPT {
return u;
}
template<typename T, typename U>
T const* runtime_cast_impl(U const* u, boost::true_type) BOOST_NOEXCEPT {
return u;
}
template<typename T, typename U>
T* runtime_cast_impl(U* u, boost::false_type) BOOST_NOEXCEPT {
return const_cast<T*>(static_cast<T const*>(
u->boost_type_index_find_instance_(boost::typeindex::type_id<T>())
));
}
template<typename T, typename U>
T const* runtime_cast_impl(U const* u, boost::false_type) BOOST_NOEXCEPT {
return static_cast<T const*>(u->boost_type_index_find_instance_(boost::typeindex::type_id<T>()));
}
} // namespace detail
}} // namespace boost::typeindex
#endif // BOOST_TYPE_INDEX_RUNTIME_CAST_DETAIL_RUNTIME_CAST_IMPL_HPP

View File

@ -0,0 +1,74 @@
//
// Copyright (c) Chris Glover, 2016.
//
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_TYPE_INDEX_RUNTIME_CAST_POINTER_CAST_HPP
#define BOOST_TYPE_INDEX_RUNTIME_CAST_POINTER_CAST_HPP
/// \file pointer_class.hpp
/// \brief Contains the function overloads of boost::typeindex::runtime_cast for
/// pointer types.
#include <boost/type_index.hpp>
#include <boost/type_index/runtime_cast/detail/runtime_cast_impl.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif
namespace boost { namespace typeindex {
/// \brief Safely converts pointers to classes up, down, and sideways along the inheritance hierarchy.
/// \tparam T The desired target type. Like dynamic_cast, must be a pointer to complete class type.
/// \tparam U A complete class type of the source instance, u.
/// \return If there exists a valid conversion from U* to T, returns a T that points to
/// an address suitably offset from u. If no such conversion exists, returns NULL.
template<typename T, typename U>
T runtime_cast(U* u) BOOST_NOEXCEPT {
typedef typename boost::remove_pointer<T>::type impl_type;
return detail::runtime_cast_impl<impl_type>(u, boost::is_base_and_derived<T, U>());
}
/// \brief Safely converts pointers to classes up, down, and sideways along the inheritance hierarchy.
/// \tparam T The desired target type. Like dynamic_cast, must be a pointer to complete class type.
/// \tparam U A complete class type of the source instance, u.
/// \return If there exists a valid conversion from U* to T, returns a T that points to
/// an address suitably offset from u. If no such conversion exists, returns NULL.
template<typename T, typename U>
T runtime_cast(U const* u) BOOST_NOEXCEPT {
typedef typename boost::remove_pointer<T>::type impl_type;
return detail::runtime_cast_impl<impl_type>(u, boost::is_base_and_derived<T, U>());
}
/// \brief Safely converts pointers to classes up, down, and sideways along the inheritance
/// hierarchy.
/// \tparam T The desired target type to return a pointer to.
/// \tparam U A complete class type of the source instance, u.
/// \return If there exists a valid conversion from U const* to T*, returns a T*
/// that points to an address suitably offset from u.
/// If no such conversion exists, returns NULL.
template<typename T, typename U>
T* runtime_pointer_cast(U* u) BOOST_NOEXCEPT {
return detail::runtime_cast_impl<T>(u, boost::is_base_and_derived<T, U>());
}
/// \brief Safely converts pointers to classes up, down, and sideways along the inheritance
/// hierarchy.
/// \tparam T The desired target type to return a pointer to.
/// \tparam U A complete class type of the source instance, u.
/// \return If there exists a valid conversion from U const* to T const*, returns a T const*
/// that points to an address suitably offset from u.
/// If no such conversion exists, returns NULL.
template<typename T, typename U>
T const* runtime_pointer_cast(U const* u) BOOST_NOEXCEPT {
return detail::runtime_cast_impl<T>(u, boost::is_base_and_derived<T, U>());
}
}} // namespace boost::typeindex
#endif // BOOST_TYPE_INDEX_RUNTIME_CAST_POINTER_CAST_HPP

View File

@ -0,0 +1,66 @@
//
// Copyright (c) Chris Glover, 2016.
//
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_TYPE_INDEX_RUNTIME_CAST_REFERENCE_CAST_HPP
#define BOOST_TYPE_INDEX_RUNTIME_CAST_REFERENCE_CAST_HPP
/// \file reference_cast.hpp
/// \brief Contains the overload of boost::typeindex::runtime_cast for
/// reference types.
#include <boost/core/addressof.hpp>
#include <boost/type_index/runtime_cast/detail/runtime_cast_impl.hpp>
#include <boost/throw_exception.hpp>
#include <boost/type_traits/add_reference.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif
namespace boost { namespace typeindex {
/// \brief Indicates that runtime_cast was unable to perform the desired cast operation
/// because the source instance was not also an instance of the target type.
struct bad_runtime_cast : std::exception
{};
/// \brief Safely converts references to classes up, down, and sideways along the inheritance hierarchy.
/// \tparam T The desired target type. Like dynamic_cast, must be a pointer to complete class type.
/// \tparam U A complete class type of the source instance, u.
/// \return If there exists a valid conversion from U& to T, returns a T that references an address
/// suitably offset from u. If no such conversion exists, throws boost::typeindex::bad_runtime_cast.
template<typename T, typename U>
typename boost::add_reference<T>::type runtime_cast(U& u) {
typedef typename boost::remove_reference<T>::type impl_type;
impl_type* value = detail::runtime_cast_impl<impl_type>(
boost::addressof(u), boost::is_base_and_derived<T, U>());
if(!value)
BOOST_THROW_EXCEPTION(bad_runtime_cast());
return *value;
}
/// \brief Safely converts references to classes up, down, and sideways along the inheritance hierarchy.
/// \tparam T The desired target type. Like dynamic_cast, must be a pointer to complete class type.
/// \tparam U A complete class type of the source instance, u.
/// \return If there exists a valid conversion from U const& to T const, returns a T const that references an address
/// suitably offset from u. If no such conversion exists, throws boost::typeindex::bad_runtime_cast.
template<typename T, typename U>
typename boost::add_reference<const T>::type runtime_cast(U const& u) {
typedef typename boost::remove_reference<T>::type impl_type;
impl_type* value = detail::runtime_cast_impl<impl_type>(
boost::addressof(u), boost::is_base_and_derived<T, U>());
if(!value)
BOOST_THROW_EXCEPTION(bad_runtime_cast());
return *value;
}
}} // namespace boost::typeindex
#endif // BOOST_TYPE_INDEX_RUNTIME_CAST_REFERENCE_CAST_HPP

View File

@ -0,0 +1,138 @@
//
// Copyright (c) Chris Glover, 2016.
//
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_TYPE_INDEX_RUNTIME_CAST_REGISTER_RUNTIME_CLASS_HPP
#define BOOST_TYPE_INDEX_RUNTIME_CAST_REGISTER_RUNTIME_CLASS_HPP
/// \file register_runtime_class.hpp
/// \brief Contains the macros BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST and
/// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS
#include <boost/type_index.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif
namespace boost { namespace typeindex {
namespace detail {
template<typename T>
inline type_index runtime_class_construct_type_id(T const*) {
return type_id<T>();
}
} // namespace detail
}} // namespace boost::typeindex
/// @cond
#define BOOST_TYPE_INDEX_CHECK_BASE_(r, data, Base) \
if(void const* ret_val = this->Base::boost_type_index_find_instance_(idx)) return ret_val;
/// @endcond
/// \def BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS
/// \brief Macro used to make a class compatible with boost::typeindex::runtime_cast
///
/// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS generates a virtual function
/// in the current class that, when combined with the supplied base class information, allows
/// boost::typeindex::runtime_cast to accurately convert between dynamic types of instances of
/// the current class.
///
/// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS also adds support for boost::typeindex::type_id_runtime
/// by including BOOST_TYPE_INDEX_REGISTER_CLASS. It is typical that these features are used together,
/// but in the event that BOOST_TYPE_INDEX_REGISTER_CLASS is undesirable in the current class,
/// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST is provided.
///
/// \b Example:
/// \code
/// struct base1 {
/// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(BOOST_TYPE_INDEX_NO_BASE_CLASS)
/// virtual ~base1();
/// };
///
/// struct base2 {
/// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(BOOST_TYPE_INDEX_NO_BASE_CLASS)
/// virtual ~base2();
/// };
///
/// struct derived1 : base1 {
/// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS((base1))
/// };
///
/// struct derived2 : base1, base2 {
/// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS((base1)(base2))
/// };
///
/// ...
///
/// base1* pb1 = get_object();
/// if(derived2* pb2 = boost::typeindex::runtime_cast<derived2*>(pb1)) {
/// assert(boost::typeindex::type_id_runtime(*pb1)) == boost::typeindex::type_id<derived2>());
/// }
/// \endcode
///
/// \param base_class_seq A Boost.Preprocessor sequence of the current class' direct bases, or
/// BOOST_TYPE_INDEX_NO_BASE_CLASS if this class has no direct base classes.
#define BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(base_class_seq) \
BOOST_TYPE_INDEX_REGISTER_CLASS \
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(base_class_seq)
/// \def BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST
/// \brief Macro used to make a class compatible with boost::typeindex::runtime_cast without including
/// support for boost::typeindex::type_id_runtime.
///
/// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST is provided as an alternative to BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS
/// in the event that support for boost::typeindex::type_id_runtime is undesirable.
///
/// \b Example:
/// \code
/// struct base1 {
/// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(BOOST_TYPE_INDEX_NO_BASE_CLASS)
/// virtual ~base1();
/// };
///
/// struct base2 {
/// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(BOOST_TYPE_INDEX_NO_BASE_CLASS)
/// virtual ~base2();
/// };
///
/// struct derived1 : base1 {
/// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST((base1))
/// };
///
/// struct derived2 : base1, base2 {
/// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST((base1)(base2))
/// };
///
/// ...
///
/// base1* pb1 = get_object();
/// if(derived2* pb2 = boost::typeindex::runtime_cast<derived2*>(pb1))
/// { /* can't call boost::typeindex::type_id_runtime(*pb1) here */ }
/// \endcode
///
/// \param base_class_seq A Boost.Preprocessor sequence of the current class' direct bases, or
/// BOOST_TYPE_INDEX_NO_BASE_CLASS if this class has no direct base classes.
#define BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(base_class_seq) \
virtual void const* boost_type_index_find_instance_(boost::typeindex::type_index const& idx) const BOOST_NOEXCEPT { \
if(idx == boost::typeindex::detail::runtime_class_construct_type_id(this)) \
return this; \
BOOST_PP_SEQ_FOR_EACH(BOOST_TYPE_INDEX_CHECK_BASE_, _, base_class_seq) \
return NULL; \
}
/// \def BOOST_TYPE_INDEX_NO_BASE_CLASS
/// \brief Instructs BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS and BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST
/// that this class has no base classes.
#define BOOST_TYPE_INDEX_NO_BASE_CLASS BOOST_PP_SEQ_NIL
#endif // BOOST_TYPE_INDEX_RUNTIME_CAST_REGISTER_RUNTIME_CLASS_HPP

View File

@ -0,0 +1,46 @@
//
// Copyright (c) Chris Glover, 2016.
//
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_TYPE_INDEX_RUNTIME_CAST_STD_SHARED_PTR_CAST_HPP
#define BOOST_TYPE_INDEX_RUNTIME_CAST_STD_SHARED_PTR_CAST_HPP
/// \file std_shared_ptr_cast.hpp
/// \brief Contains the overload of boost::typeindex::runtime_pointer_cast for
/// std::shared_ptr types.
#include <boost/type_index/runtime_cast/detail/runtime_cast_impl.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
#include <memory>
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif
namespace boost { namespace typeindex {
/// \brief Creates a new instance of std::shared_ptr whose stored pointer is obtained from u's
/// stored pointer using a runtime_cast.
///
/// The new shared_ptr will share ownership with u, except that it is empty if the runtime_cast
/// performed by runtime_pointer_cast returns a null pointer.
/// \tparam T The desired target type to return a pointer of.
/// \tparam U A complete class type of the source instance pointed to from u.
/// \return If there exists a valid conversion from U* to T*, returns a std::shared_ptr<T>
/// that points to an address suitably offset from u.
/// If no such conversion exists, returns std::shared_ptr<T>();
template<typename T, typename U>
std::shared_ptr<T> runtime_pointer_cast(std::shared_ptr<U> const& u) {
T* value = detail::runtime_cast_impl<T>(u.get(), boost::is_base_and_derived<T, U>());
if(value)
return std::shared_ptr<T>(u, value);
return std::shared_ptr<T>();
}
}} // namespace boost::typeindex
#endif // BOOST_TYPE_INDEX_RUNTIME_CAST_STD_SHARED_PTR_CAST_HPP

View File

@ -0,0 +1,278 @@
//
// Copyright 2013-2022 Antony Polukhin.
//
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_TYPE_INDEX_STL_TYPE_INDEX_HPP
#define BOOST_TYPE_INDEX_STL_TYPE_INDEX_HPP
/// \file stl_type_index.hpp
/// \brief Contains boost::typeindex::stl_type_index class.
///
/// boost::typeindex::stl_type_index class can be used as a drop-in replacement
/// for std::type_index.
///
/// It is used in situations when RTTI is enabled or typeid() method is available.
/// When typeid() is disabled or BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY macro
/// is defined boost::typeindex::ctti is usually used instead of boost::typeindex::stl_type_index.
#include <boost/type_index/type_index_facade.hpp>
// MSVC is capable of calling typeid(T) even when RTTI is off
#if defined(BOOST_NO_RTTI) && !defined(BOOST_MSVC)
#error "File boost/type_index/stl_type_index.ipp is not usable when typeid() is not available."
#endif
#include <typeinfo>
#include <cstring> // std::strcmp, std::strlen, std::strstr
#include <stdexcept>
#include <boost/static_assert.hpp>
#include <boost/throw_exception.hpp>
#include <boost/core/demangle.hpp>
#include <boost/type_traits/conditional.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/is_reference.hpp>
#include <boost/type_traits/is_volatile.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_reference.hpp>
#if (defined(_MSC_VER) && _MSC_VER > 1600) \
|| (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ > 5 && defined(__GXX_EXPERIMENTAL_CXX0X__)) \
|| (defined(__GNUC__) && __GNUC__ > 4 && __cplusplus >= 201103)
# define BOOST_TYPE_INDEX_STD_TYPE_INDEX_HAS_HASH_CODE
#else
# include <boost/container_hash/hash.hpp>
#endif
#if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \
|| (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744)
# include <boost/type_traits/is_signed.hpp>
# include <boost/type_traits/make_signed.hpp>
# include <boost/type_traits/type_identity.hpp>
#endif
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif
namespace boost { namespace typeindex {
/// \class stl_type_index
/// This class is a wrapper around std::type_info, that workarounds issues and provides
/// much more rich interface. \b For \b description \b of \b functions \b see type_index_facade.
///
/// This class requires typeid() to work. For cases when RTTI is disabled see ctti_type_index.
class stl_type_index
: public type_index_facade<
stl_type_index,
#ifdef BOOST_NO_STD_TYPEINFO
type_info
#else
std::type_info
#endif
>
{
public:
#ifdef BOOST_NO_STD_TYPEINFO
typedef type_info type_info_t;
#else
typedef std::type_info type_info_t;
#endif
private:
const type_info_t* data_;
public:
inline stl_type_index() BOOST_NOEXCEPT
: data_(&typeid(void))
{}
inline stl_type_index(const type_info_t& data) BOOST_NOEXCEPT
: data_(&data)
{}
inline const type_info_t& type_info() const BOOST_NOEXCEPT;
inline const char* raw_name() const BOOST_NOEXCEPT;
inline const char* name() const BOOST_NOEXCEPT;
inline std::string pretty_name() const;
inline std::size_t hash_code() const BOOST_NOEXCEPT;
inline bool equal(const stl_type_index& rhs) const BOOST_NOEXCEPT;
inline bool before(const stl_type_index& rhs) const BOOST_NOEXCEPT;
template <class T>
inline static stl_type_index type_id() BOOST_NOEXCEPT;
template <class T>
inline static stl_type_index type_id_with_cvr() BOOST_NOEXCEPT;
template <class T>
inline static stl_type_index type_id_runtime(const T& value) BOOST_NOEXCEPT;
};
inline const stl_type_index::type_info_t& stl_type_index::type_info() const BOOST_NOEXCEPT {
return *data_;
}
inline const char* stl_type_index::raw_name() const BOOST_NOEXCEPT {
#ifdef _MSC_VER
return data_->raw_name();
#else
return data_->name();
#endif
}
inline const char* stl_type_index::name() const BOOST_NOEXCEPT {
return data_->name();
}
inline std::string stl_type_index::pretty_name() const {
static const char cvr_saver_name[] = "boost::typeindex::detail::cvr_saver<";
static BOOST_CONSTEXPR_OR_CONST std::string::size_type cvr_saver_name_len = sizeof(cvr_saver_name) - 1;
// In case of MSVC demangle() is a no-op, and name() already returns demangled name.
// In case of GCC and Clang (on non-Windows systems) name() returns mangled name and demangle() undecorates it.
const boost::core::scoped_demangled_name demangled_name(data_->name());
const char* begin = demangled_name.get();
if (!begin) {
boost::throw_exception(std::runtime_error("Type name demangling failed"));
}
const std::string::size_type len = std::strlen(begin);
const char* end = begin + len;
if (len > cvr_saver_name_len) {
const char* b = std::strstr(begin, cvr_saver_name);
if (b) {
b += cvr_saver_name_len;
// Trim leading spaces
while (*b == ' ') { // the string is zero terminated, we won't exceed the buffer size
++ b;
}
// Skip the closing angle bracket
const char* e = end - 1;
while (e > b && *e != '>') {
-- e;
}
// Trim trailing spaces
while (e > b && *(e - 1) == ' ') {
-- e;
}
if (b < e) {
// Parsing seems to have succeeded, the type name is not empty
begin = b;
end = e;
}
}
}
return std::string(begin, end);
}
inline std::size_t stl_type_index::hash_code() const BOOST_NOEXCEPT {
#ifdef BOOST_TYPE_INDEX_STD_TYPE_INDEX_HAS_HASH_CODE
return data_->hash_code();
#else
return boost::hash_range(raw_name(), raw_name() + std::strlen(raw_name()));
#endif
}
/// @cond
// for this compiler at least, cross-shared-library type_info
// comparisons don't work, so we are using typeid(x).name() instead.
# if (defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5))) \
|| defined(_AIX) \
|| (defined(__sgi) && defined(__host_mips)) \
|| (defined(__hpux) && defined(__HP_aCC)) \
|| (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC))
# define BOOST_TYPE_INDEX_CLASSINFO_COMPARE_BY_NAMES
# endif
/// @endcond
inline bool stl_type_index::equal(const stl_type_index& rhs) const BOOST_NOEXCEPT {
#ifdef BOOST_TYPE_INDEX_CLASSINFO_COMPARE_BY_NAMES
return raw_name() == rhs.raw_name() || !std::strcmp(raw_name(), rhs.raw_name());
#else
return !!(*data_ == *rhs.data_);
#endif
}
inline bool stl_type_index::before(const stl_type_index& rhs) const BOOST_NOEXCEPT {
#ifdef BOOST_TYPE_INDEX_CLASSINFO_COMPARE_BY_NAMES
return raw_name() != rhs.raw_name() && std::strcmp(raw_name(), rhs.raw_name()) < 0;
#else
return !!data_->before(*rhs.data_);
#endif
}
#undef BOOST_TYPE_INDEX_CLASSINFO_COMPARE_BY_NAMES
template <class T>
inline stl_type_index stl_type_index::type_id() BOOST_NOEXCEPT {
typedef BOOST_DEDUCED_TYPENAME boost::remove_reference<T>::type no_ref_t;
typedef BOOST_DEDUCED_TYPENAME boost::remove_cv<no_ref_t>::type no_cvr_prefinal_t;
# if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \
|| (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744)
// Old EDG-based compilers seem to mistakenly distinguish 'integral' from 'signed integral'
// in typeid() expressions. Full template specialization for 'integral' fixes that issue:
typedef BOOST_DEDUCED_TYPENAME boost::conditional<
boost::is_signed<no_cvr_prefinal_t>::value,
boost::make_signed<no_cvr_prefinal_t>,
boost::type_identity<no_cvr_prefinal_t>
>::type no_cvr_prefinal_lazy_t;
typedef BOOST_DEDUCED_TYPENAME no_cvr_prefinal_t::type no_cvr_t;
#else
typedef no_cvr_prefinal_t no_cvr_t;
#endif
return typeid(no_cvr_t);
}
namespace detail {
template <class T> class cvr_saver{};
}
template <class T>
inline stl_type_index stl_type_index::type_id_with_cvr() BOOST_NOEXCEPT {
typedef BOOST_DEDUCED_TYPENAME boost::conditional<
boost::is_reference<T>::value || boost::is_const<T>::value || boost::is_volatile<T>::value,
detail::cvr_saver<T>,
T
>::type type;
return typeid(type);
}
template <class T>
inline stl_type_index stl_type_index::type_id_runtime(const T& value) BOOST_NOEXCEPT {
#ifdef BOOST_NO_RTTI
return value.boost_type_index_type_id_runtime_();
#else
return typeid(value);
#endif
}
}} // namespace boost::typeindex
#undef BOOST_TYPE_INDEX_STD_TYPE_INDEX_HAS_HASH_CODE
#endif // BOOST_TYPE_INDEX_STL_TYPE_INDEX_HPP

View File

@ -0,0 +1,297 @@
//
// Copyright 2013-2022 Antony Polukhin.
//
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_TYPE_INDEX_TYPE_INDEX_FACADE_HPP
#define BOOST_TYPE_INDEX_TYPE_INDEX_FACADE_HPP
#include <boost/config.hpp>
#include <boost/container_hash/hash_fwd.hpp>
#include <string>
#include <cstring>
#if !defined(BOOST_NO_IOSTREAM)
#if !defined(BOOST_NO_IOSFWD)
#include <iosfwd> // for std::basic_ostream
#else
#include <ostream>
#endif
#endif
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif
namespace boost { namespace typeindex {
/// \class type_index_facade
///
/// This class takes care about the comparison operators, hash functions and
/// ostream operators. Use this class as a public base class for defining new
/// type_info-conforming classes.
///
/// \b Example:
/// \code
/// class stl_type_index: public type_index_facade<stl_type_index, std::type_info>
/// {
/// public:
/// typedef std::type_info type_info_t;
/// private:
/// const type_info_t* data_;
///
/// public:
/// stl_type_index(const type_info_t& data) noexcept
/// : data_(&data)
/// {}
/// // ...
/// };
/// \endcode
///
/// \tparam Derived Class derived from type_index_facade.
/// \tparam TypeInfo Class that will be used as a base type_info class.
/// \note Take a look at the protected methods. They are \b not \b defined in type_index_facade.
/// Protected member functions raw_name() \b must be defined in Derived class. All the other
/// methods are mandatory.
/// \see 'Making a custom type_index' section for more information about
/// creating your own type_index using type_index_facade.
template <class Derived, class TypeInfo>
class type_index_facade {
private:
/// @cond
BOOST_CXX14_CONSTEXPR const Derived & derived() const BOOST_NOEXCEPT {
return *static_cast<Derived const*>(this);
}
/// @endcond
public:
typedef TypeInfo type_info_t;
/// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw.
/// \return Name of a type. By default returns Derived::raw_name().
inline const char* name() const BOOST_NOEXCEPT {
return derived().raw_name();
}
/// \b Override: This function \b may be redefined in Derived class. Overrides may throw.
/// \return Human readable type name. By default returns Derived::name().
inline std::string pretty_name() const {
return derived().name();
}
/// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw.
/// \return True if two types are equal. By default compares types by raw_name().
inline bool equal(const Derived& rhs) const BOOST_NOEXCEPT {
const char* const left = derived().raw_name();
const char* const right = rhs.raw_name();
return left == right || !std::strcmp(left, right);
}
/// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw.
/// \return True if rhs is greater than this. By default compares types by raw_name().
inline bool before(const Derived& rhs) const BOOST_NOEXCEPT {
const char* const left = derived().raw_name();
const char* const right = rhs.raw_name();
return left != right && std::strcmp(left, right) < 0;
}
/// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw.
/// \return Hash code of a type. By default hashes types by raw_name().
/// \note Derived class header \b must include <boost/container_hash/hash.hpp>, \b unless this function is redefined in
/// Derived class to not use boost::hash_range().
inline std::size_t hash_code() const BOOST_NOEXCEPT {
const char* const name_raw = derived().raw_name();
return boost::hash_range(name_raw, name_raw + std::strlen(name_raw));
}
#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
protected:
/// \b Override: This function \b must be redefined in Derived class. Overrides \b must not throw.
/// \return Pointer to unredable/raw type name.
inline const char* raw_name() const BOOST_NOEXCEPT;
/// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw.
/// \return Const reference to underlying low level type_info_t.
inline const type_info_t& type_info() const BOOST_NOEXCEPT;
/// This is a factory method that is used to create instances of Derived classes.
/// boost::typeindex::type_id() will call this method, if Derived has same type as boost::typeindex::type_index.
///
/// \b Override: This function \b may be redefined and made public in Derived class. Overrides \b must not throw.
/// Overrides \b must remove const, volatile && and & modifiers from T.
/// \tparam T Type for which type_index must be created.
/// \return type_index for type T.
template <class T>
static Derived type_id() BOOST_NOEXCEPT;
/// This is a factory method that is used to create instances of Derived classes.
/// boost::typeindex::type_id_with_cvr() will call this method, if Derived has same type as boost::typeindex::type_index.
///
/// \b Override: This function \b may be redefined and made public in Derived class. Overrides \b must not throw.
/// Overrides \b must \b not remove const, volatile && and & modifiers from T.
/// \tparam T Type for which type_index must be created.
/// \return type_index for type T.
template <class T>
static Derived type_id_with_cvr() BOOST_NOEXCEPT;
/// This is a factory method that is used to create instances of Derived classes.
/// boost::typeindex::type_id_runtime(const T&) will call this method, if Derived has same type as boost::typeindex::type_index.
///
/// \b Override: This function \b may be redefined and made public in Derived class.
/// \param variable Variable which runtime type will be stored in type_index.
/// \return type_index with runtime type of variable.
template <class T>
static Derived type_id_runtime(const T& variable) BOOST_NOEXCEPT;
#endif
};
/// @cond
template <class Derived, class TypeInfo>
BOOST_CXX14_CONSTEXPR inline bool operator == (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
return static_cast<Derived const&>(lhs).equal(static_cast<Derived const&>(rhs));
}
template <class Derived, class TypeInfo>
BOOST_CXX14_CONSTEXPR inline bool operator < (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
return static_cast<Derived const&>(lhs).before(static_cast<Derived const&>(rhs));
}
template <class Derived, class TypeInfo>
BOOST_CXX14_CONSTEXPR inline bool operator > (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
return rhs < lhs;
}
template <class Derived, class TypeInfo>
BOOST_CXX14_CONSTEXPR inline bool operator <= (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
return !(lhs > rhs);
}
template <class Derived, class TypeInfo>
BOOST_CXX14_CONSTEXPR inline bool operator >= (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
return !(lhs < rhs);
}
template <class Derived, class TypeInfo>
BOOST_CXX14_CONSTEXPR inline bool operator != (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
return !(lhs == rhs);
}
// ######################### COMPARISONS with Derived ############################ //
template <class Derived, class TypeInfo>
inline bool operator == (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
return Derived(lhs) == rhs;
}
template <class Derived, class TypeInfo>
inline bool operator < (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
return Derived(lhs) < rhs;
}
template <class Derived, class TypeInfo>
inline bool operator > (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
return rhs < Derived(lhs);
}
template <class Derived, class TypeInfo>
inline bool operator <= (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
return !(Derived(lhs) > rhs);
}
template <class Derived, class TypeInfo>
inline bool operator >= (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
return !(Derived(lhs) < rhs);
}
template <class Derived, class TypeInfo>
inline bool operator != (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
return !(Derived(lhs) == rhs);
}
template <class Derived, class TypeInfo>
inline bool operator == (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT {
return lhs == Derived(rhs);
}
template <class Derived, class TypeInfo>
inline bool operator < (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT {
return lhs < Derived(rhs);
}
template <class Derived, class TypeInfo>
inline bool operator > (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT {
return Derived(rhs) < lhs;
}
template <class Derived, class TypeInfo>
inline bool operator <= (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT {
return !(lhs > Derived(rhs));
}
template <class Derived, class TypeInfo>
inline bool operator >= (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT {
return !(lhs < Derived(rhs));
}
template <class Derived, class TypeInfo>
inline bool operator != (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT {
return !(lhs == Derived(rhs));
}
// ######################### COMPARISONS with Derived END ############################ //
/// @endcond
#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
/// noexcept comparison operators for type_index_facade classes.
bool operator ==, !=, <, ... (const type_index_facade& lhs, const type_index_facade& rhs) noexcept;
/// noexcept comparison operators for type_index_facade and it's TypeInfo classes.
bool operator ==, !=, <, ... (const type_index_facade& lhs, const TypeInfo& rhs) noexcept;
/// noexcept comparison operators for type_index_facade's TypeInfo and type_index_facade classes.
bool operator ==, !=, <, ... (const TypeInfo& lhs, const type_index_facade& rhs) noexcept;
#endif
#ifndef BOOST_NO_IOSTREAM
#ifdef BOOST_NO_TEMPLATED_IOSTREAMS
/// @cond
/// Ostream operator that will output demangled name
template <class Derived, class TypeInfo>
inline std::ostream& operator<<(std::ostream& ostr, const type_index_facade<Derived, TypeInfo>& ind) {
ostr << static_cast<Derived const&>(ind).pretty_name();
return ostr;
}
/// @endcond
#else
/// Ostream operator that will output demangled name.
template <class CharT, class TriatT, class Derived, class TypeInfo>
inline std::basic_ostream<CharT, TriatT>& operator<<(
std::basic_ostream<CharT, TriatT>& ostr,
const type_index_facade<Derived, TypeInfo>& ind)
{
ostr << static_cast<Derived const&>(ind).pretty_name();
return ostr;
}
#endif // BOOST_NO_TEMPLATED_IOSTREAMS
#endif // BOOST_NO_IOSTREAM
/// This free function is used by Boost's unordered containers.
/// \note <boost/container_hash/hash.hpp> has to be included if this function is used.
template <class Derived, class TypeInfo>
inline std::size_t hash_value(const type_index_facade<Derived, TypeInfo>& lhs) BOOST_NOEXCEPT {
return static_cast<Derived const&>(lhs).hash_code();
}
}} // namespace boost::typeindex
#endif // BOOST_TYPE_INDEX_TYPE_INDEX_FACADE_HPP

35
index.html Normal file
View File

@ -0,0 +1,35 @@
<!DOCTYPE html>
<!--
Copyright 2014-2022 Antony Polukhin
antoshkka at gmail dot com
Distributed under the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt
or copy at http://boost.org/LICENSE_1_0.txt)
-->
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="refresh" content="0; url=https://www.boost.org/doc/libs/master/doc/html/boost_typeindex.html">
<title>Boost.TypeIndex</title>
<style>
body {
background: #fff;
color: #000;
}
a {
color: #00f;
text-decoration: none;
}
</style>
</head>
<body>
<p>
Automatic redirection failed, please go to
<a href="https://www.boost.org/doc/libs/master/doc/html/boost_typeindex.html">https://www.boost.org/doc/libs/master/doc/html/boost_typeindex.html</a>
</p>
<p>
&copy; 2014-2022 Antony Polukhin
</p>
</body>
</html>

View File

@ -1,273 +0,0 @@
[library Boost.TypeIndex
[quickbook 1.6]
[version 2.1]
[copyright 2012-2013 Antony Polukhin]
[category Language Features Emulation]
[license
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
[@http://www.boost.org/LICENSE_1_0.txt])
]
]
[section Motivation]
Sometimes getting and storing information about a type at runtime is required. For such cases a construction like `&typeid(T)` or C++11 class `std::type_index` is usually used. And that is the point, where problems start:
* `typeid(T)` and `std::type_index` require Run Time Type Info (RTTI)
* some implementations of `typeid(T)` strip const, volatile and references from type, while others don't
* some compilers have bugs and do not correctly compare `std::type_info` objects across shared libraries
* only a few implementations of Standard Library currently provide `std::type_index`
* no easy way to store type info without stripping const, volatile and references
* no nice and portable way to get human readable type names
Boost.TypeIndex library was designed to work around all those issues.
[note `T` means type here. Think of it as of `T` in `template <class T>` ]
[warning During the Boost review was decided, that it is better to use interface close to v1.0 of this library. Version 3.0 will attempt to fix all the issues found during the review. ]
[endsect]
[section Getting started]
`boost::type_info` is a drop-in replacement for `std::type_info` and `boost::type_index` is a drop-in
replacement for `std::type_index`. Unlike Standard Library versions those classes may work without RTTI.
`boost::type_index` provides the full set of comparison operators, hashing functions and ostream
operators, so it can be used with any container class.
To start using Boost.TypeIndex:
[table:porting
[[Replace this:][With the following:]]
[[``
#include <typeinfo>
#include <typeindex>
``][``
#include <boost/type_index/type_info.hpp>
#include <boost/type_index/type_index.hpp>
`` or ``
#include <boost/type_index.hpp>
``]]
[[``
std::type_info
std::type_index
``][``
boost::type_info
boost::type_index
``]]
[[``
typeid(T)
typeid(please_save_modifiers<T>)
typeid(T).name() // not human readable
typeid(variable)
``][``
boost::type_id<T>()
boost::type_id_with_cvr<T>()
boost::type_id<T>().name_demangled() // human readable
boost::type_id_rtti_only(variable)
``]]
]
Here is how TypeIndex could be used in `boost/any.hpp`:
[table:any
[[Before] [With TypeIndex]]
[[``#include <typeinfo>``][``#include <boost/type_index/type_info.hpp>``]]
[[``
virtual const std::type_info & type() const BOOST_NOEXCEPT
{
// requires RTTI
return typeid(ValueType);
}
``] [``
virtual const boost::type_info & type() const BOOST_NOEXCEPT
{
// now works even with RTTI disabled
return boost::type_id<ValueType>();
}
``]]
]
Here is how TypeIndex could be used in `boost/variant/variant.hpp`:
[table:variant
[[Before] [With TypeIndex]]
[[``
#if !defined(BOOST_NO_TYPEID)
#include <typeinfo> // for typeid, std::type_info
#endif // BOOST_NO_TYPEID
``][``
#include <boost/type_info/type_info.hpp>
``]]
[[``
#if !defined(BOOST_NO_TYPEID)
class reflect
: public static_visitor<const std::type_info&>
{
public: // visitor interfaces
template <typename T>
const std::type_info& operator()(const T&) const BOOST_NOEXCEPT
{
return typeid(T);
}
};
#endif // BOOST_NO_TYPEID
``][``
class reflect
: public static_visitor<const boost::type_info&>
{
public: // visitor interfaces
template <typename T>
const boost::type_info& operator()(const T&) const BOOST_NOEXCEPT
{
return boost::type_id<T>();
}
};
``]]
[[``
#if !defined(BOOST_NO_TYPEID)
const std::type_info& type() const
{
detail::variant::reflect visitor;
return this->apply_visitor(visitor);
}
#endif
``] [``
const boost::type_info& type() const
{
detail::variant::reflect visitor;
return this->apply_visitor(visitor);
}
``]]
]
[endsect]
[section Examples]
[import ../examples/demangled_names.cpp]
[section Getting human readable and mangled type names] [type_index_names_example] [endsect]
[import ../examples/registry.cpp]
[section Storing information about a type in container ] [type_index_registry_example] [endsect]
[import ../examples/inheritance.cpp]
[section Getting through the inheritance to receive a real type name ] [type_index_derived_example] [endsect]
[import ../examples/exact_types_match.cpp]
[section Exact type match: storing type with const, volatile and reference ] [type_index_exact_type_match_example] [endsect]
[endsect]
[xinclude autodoc.xml]
[section Space and Performance]
* `template_info` uses macro for getting full text representation of function name which could lead to code bloat,
so prefer using `type_info` type.
* `type_index` and `template_index` classes hold a single pointer, so they are easy and fast to copy.
* Calls to `const char* name()` do not require dynamic memory allocation and usually just return a pointer to an array of chars in a read-only section of the binary image.
* Comparison operators are optimized as much as possible, and will at worst execute a single `std::strcmp`.
* Calls to `std::string name_demangled()` usually require dynamic memory allocation and some computations, so they are not recommended for usage in performance critical sections.
[endsect]
[section Code bloat]
Without RTTI TypeIndex library will switch from using `boost::type_info` class to `boost::template_info`.
`boost::template_info` uses macro for getting full text representation of function name for each type that
is passed to `type_id()` and `type_id_with_cvr()` functions.
This leads to big strings in binary file:
```
static const char* boost::detail::ctti<T>::n() [with T = int]
static const char* boost::detail::ctti<T>::n() [with T = user_defined_type]
```
While using RTTI, you'll get the following (more compact) string in binary file:
```
i
17user_defined_type
```
[endsect]
[section Compiler support]
TypeIndex has been tested and successfully work on MSVC2010, GCC-4.5, Clang-2.9. If your compiler is not
in a list of tested compilers, you must correctly define `BOOST_TYPE_INDEX_FUNCTION_SIGNATURE`,
`BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` and `BOOST_TYPE_INDEX_CTTI_END_SKIP` macroses:
# define `BOOST_TYPE_INDEX_FUNCTION_SIGNATURE` to a compiler specific macro, that outputs the *whole*
function signature, including template parameters
# define `BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` and `BOOST_TYPE_INDEX_CTTI_END_SKIP` to `0`
# get the output of `boost::template_id<int>().name()`
# set `BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` equal to characters count before last occurrence of `int` in output
# set `BOOST_TYPE_INDEX_CTTI_END_SKIP` equal to characters count after last occurrence of `int` in output
# check that `boost::template_id<int>().name_demangled()` returns "int"
# (optional, but highly recomended) [@http://www.boost.org/support/bugs.html create ticket] with
feature request to add your compiler to supported compilers list. Include
`BOOST_TYPE_INDEX_FUNCTION_SIGNATURE`, `BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` and
`BOOST_TYPE_INDEX_CTTI_END_SKIP` values.
Consider the following example:
With `BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` and `BOOST_TYPE_INDEX_CTTI_END_SKIP` set to `0`,
`boost::template_id<int>().name()` returns "const char *__cdecl boost::detail::ctti<int>::n(void)".
Then you shall set `BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` to
`sizeof("const char *__cdecl boost::detail::ctti<") - 1` and `BOOST_TYPE_INDEX_CTTI_END_SKIP`
to `sizeof(">::n(void)") - 1`
[endsect]
[section Mixing sources with RTTI on and RTTI off]
Linking a binary from source files that were compiled with different RTTI flags is not a very good
idea and may lead to a lot of surprises. However if there is a very strong need, TypeIndex library
provides a solution for mixing sources: just define `BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY`
macro. This would lead to usage of `boost::template_index` instead of `boost::type_index` class
and `boost::template_info` instead of `boost::type_info` class.
[note Do not forget to rebuild *all* the projects with `BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY` macro defined ]
You must know that linking RTTI on and RTTI off binaries may succeed even without defining the
`BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY` macro, but that does not mean that you'll get a
working binary. Such actions may break the One Definition Rule. Take a look at the table below,
that shows how the `boost::type_index get_integer();` function will look like with different
RTTI flags:
[table:diffs
[[RTTI on] [RTTI off]]
[[`boost::type_index get_integer();`] [`boost::template_index get_integer();`]]
]
Such differences are usually not detected by linker and lead to errors at runtime.
[warning
Even with `BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY` defined there is no guarantee
that everything will be OK. Libraries that use their own workarounds for disabled RTTI
may fail to link or to work correctly.
]
[endsect]
[section Acknowledgements]
In order of helping and advising:
* Peter Dimov for writing source codes in late 2007, ideas from which were refined and put into this library.
* Agustín Bergé K-ballo for helping with docs and fixing a lot of typos.
* Niall Douglas for generating a lot of great ideas and reviewing the sources.
[endsect]

View File

@ -1,50 +0,0 @@
// Copyright 2013 Antony Polukhin
// Distributed under the Boost Software License, Version 1.0.
// (See the accompanying file LICENSE_1_0.txt
// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
//[type_index_names_example
/*`
The following example shows how short (mangled) and human readable type names could be obtained from a type.
Works with and without RTTI.
*/
#include <boost/type_index/type_info.hpp>
#include <iostream>
template <class T>
void foo(T) {
std::cout << "\n Short name: " << boost::type_id<T>().name();
std::cout << "\n Readable name: " << boost::type_id<T>().name_demangled();
}
struct user_defined_type{};
int main() {
// Call to
foo(1);
// will output something like this:
//
// (RTTI on) (RTTI off)
// Short name: i Short name: int]
// Readable name: int Readable name: int
user_defined_type t;
foo(t);
// Will output:
//
// (RTTI on) (RTTI off)
// Short name: 17user_defined_type user_defined_type]
// Readable name: user_defined_type user_defined_type
}
/*`
Short names are very compiler dependant: some compiler will output `.H`, others `i`.
Readable names may also differ between compilers: `struct user_defined_type`, `user_defined_type`.
*/
//] [/type_index_names_example]

View File

@ -1,34 +0,0 @@
// Copyright 2013 Antony Polukhin
// Distributed under the Boost Software License, Version 1.0.
// (See the accompanying file LICENSE_1_0.txt
// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
//[type_index_derived_example
/*`
The following example shows that `boost::type_info` is able to store the real type, successfully getting through
all the inheritances.
Example works with RTTI only. Without RTTI support it won't compile, producing a compile-time error with message:
"boost::type_id_rtti_only(T&) requires RTTI"
*/
#include <boost/type_index/type_info.hpp>
#include <iostream>
struct A { virtual ~A(){} };
struct B: public A {};
struct C: public B {};
void print_real_type(const A& a) {
std::cout << boost::type_id_rtti_only(a).name_demangled() << '\n';
}
int main() {
C c;
const A& c_as_a = c;
print_real_type(c_as_a); // Outputs `struct C`
print_real_type(B()); // Outputs `struct B`
}
//] [/type_index_derived_example]

View File

@ -1,36 +0,0 @@
// Copyright 2013 Antony Polukhin
// Distributed under the Boost Software License, Version 1.0.
// (See the accompanying file LICENSE_1_0.txt
// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
//[type_index_registry_example
/*`
The following example shows how an information about a type could be stored.
Example works with and without RTTI.
*/
#include <boost/type_index/type_index.hpp>
#include <boost/unordered_set.hpp>
#include <cassert>
int main() {
boost::unordered_set<boost::type_index> types;
// Storing some `boost::type_info`s
types.insert(boost::type_id<int>());
types.insert(boost::type_id<float>());
// `types` variable contains two `boost::type_index`es:
assert(types.size() == 2);
// Const, volatile and reference will be striped from the type:
bool is_inserted = types.insert(boost::type_id<const int>()).second;
assert(!is_inserted);
assert(types.erase(boost::type_id<float&>()) == 1);
// We have erased the `float` type, only `int` remains
assert(*types.begin() == boost::type_id<int>());
}
//] [/type_index_registry_example]

View File

@ -1,62 +0,0 @@
# Copyright (C) 2012-2013 Antony Polukhin
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#
import testing ;
import feature ;
# Variable that contains all the stuff required for linking against -lboost_unit_test
tlib = /boost/test//boost_unit_test_framework/<link>static ;
# Variable that contains all the stuff required for linking together <rtti>on and <rtti>off
compat = <define>BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY ;
# Making own `nortti` that is link compatible
nortti = <toolset>gcc:<cxxflags>-fno-rtti <toolset>clang:<cxxflags>-fno-rtti <toolset>msvc:<cxxflags>/GR- ;
# Making libraries that CANNOT work between rtti-on/rtti-off modules
obj test_lib_nortti-obj : test_lib.cpp : <link>shared <rtti>off ;
obj test_lib_rtti-obj : test_lib.cpp : <link>shared ;
lib test_lib_rtti : test_lib_rtti-obj : <link>shared ;
lib test_lib_nortti : test_lib_nortti-obj : <link>shared <rtti>off ;
# Making libraries that can work between rtti-on/rtti-off modules
obj test_lib_nortti_compat-obj : test_lib.cpp : <link>shared $(nortti) $(compat) ;
obj test_lib_rtti_compat-obj : test_lib.cpp : <link>shared $(nortti) $(compat) ;
lib test_lib_nortti_compat : test_lib_nortti_compat-obj : <link>shared $(nortti) $(compat) ;
lib test_lib_rtti_compat : test_lib_rtti_compat-obj : <link>shared $(nortti) $(compat) ;
test-suite type_index
:
[ run type_index_test.cpp $(tlib) ]
[ run template_index_test.cpp $(tlib) ]
[ run testing_both.cpp $(tlib) ]
[ run testing_both_no_rtti.cpp $(tlib) : : : <rtti>off ]
[ run testing_crossmodule.cpp test_lib_rtti $(tlib) ]
[ run testing_crossmodule.cpp test_lib_nortti $(tlib) : : : <rtti>off : testing_crossmodule_no_rtti ]
# Mixing RTTI on and off
[ link-fail testing_crossmodule.cpp $(tlib) test_lib_rtti : $(nortti) : link_fail_nortti_rtti ]
# MSVC sometimes overrides the /GR-, that's why the following tests is disabled
#[ link-fail testing_crossmodule.cpp $(tlib) test_lib_nortti : : link_fail_rtti_nortti ]
[ run testing_crossmodule.cpp $(tlib) test_lib_rtti_compat : : : $(nortti) $(compat) : testing_crossmodule_nortti_rtti_compat ]
[ run testing_crossmodule.cpp $(tlib) test_lib_nortti_compat : : : $(compat) : testing_crossmodule_rtti_nortti_compat ]
# Examples that must work even with RTTI disabled
[ run ../examples/registry.cpp : : : <rtti>off : registry_no_rtti ]
[ run ../examples/exact_types_match.cpp : : : <rtti>off : exact_types_match_no_rtti ]
[ run ../examples/demangled_names.cpp : : : <rtti>off : demangled_names_no_rtti ]
[ compile-fail ../examples/inheritance.cpp : <rtti>off : failing_inheritance_example ]
;
# Assuring that examples compile and run. Adding sources from `examples` directory to the `type_index` test suite.
for local p in [ glob ../examples/*.cpp ]
{
type_index += [ run $(p) ] ;
}

View File

@ -1,23 +0,0 @@
//
// Copyright Antony Polukhin, 2012-2013.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_TEST_MODULE template_index_test_module
#include <boost/test/unit_test.hpp>
#include <boost/type_index/template_index.hpp>
namespace my_namespace1 {
class my_class{};
}
namespace my_namespace2 {
class my_class{};
}
#include "template_index_tests.ipp"

View File

@ -1,199 +0,0 @@
//
// Copyright Antony Polukhin, 2012-2013.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/functional/hash.hpp>
#include <boost/lexical_cast.hpp>
BOOST_AUTO_TEST_CASE(names_matches_template_id)
{
using namespace boost;
BOOST_CHECK_EQUAL(template_id<int>().name_demangled(), "int");
BOOST_CHECK_EQUAL(template_id<double>().name_demangled(), "double");
BOOST_CHECK_EQUAL(template_id<int>().name(), template_id<int>().name());
BOOST_CHECK_NE(template_id<int>().name(), template_id<double>().name());
BOOST_CHECK_NE(template_id<double>().name(), template_id<int>().name());
BOOST_CHECK_EQUAL(template_id<double>().name(), template_id<double>().name());
}
BOOST_AUTO_TEST_CASE(comparators_template_id)
{
using namespace boost;
template_index t_int = template_id<int>();
template_index t_double = template_id<double>();
BOOST_CHECK_EQUAL(t_int, t_int);
BOOST_CHECK_LE(t_int, t_int);
BOOST_CHECK_GE(t_int, t_int);
BOOST_CHECK_NE(t_int, t_double);
BOOST_CHECK_LE(t_double, t_double);
BOOST_CHECK_GE(t_double, t_double);
BOOST_CHECK_NE(t_double, t_int);
BOOST_CHECK(t_double < t_int || t_int < t_double);
BOOST_CHECK(t_double > t_int || t_int > t_double);
}
BOOST_AUTO_TEST_CASE(hash_code_template_id)
{
using namespace boost;
std::size_t t_int1 = template_id<int>().hash_code();
std::size_t t_double1 = template_id<double>().hash_code();
std::size_t t_int2 = template_id<int>().hash_code();
std::size_t t_double2 = template_id<double>().hash_code();
BOOST_CHECK_EQUAL(t_int1, t_int2);
BOOST_CHECK_NE(t_int1, t_double2);
BOOST_CHECK_LE(t_double1, t_double2);
}
template <class T1, class T2>
static void test_with_modofiers() {
using namespace boost;
template_index t1 = template_id_with_cvr<T1>();
template_index t2 = template_id_with_cvr<T2>();
BOOST_CHECK_NE(t2, t1);
BOOST_CHECK(t1 < t2 || t2 < t1);
BOOST_CHECK(t1 > t2 || t2 > t1);
BOOST_CHECK_EQUAL(t1, template_id_with_cvr<T1>());
BOOST_CHECK_EQUAL(t2, template_id_with_cvr<T2>());
BOOST_CHECK_EQUAL(t1.hash_code(), template_id_with_cvr<T1>().hash_code());
BOOST_CHECK_EQUAL(t2.hash_code(), template_id_with_cvr<T2>().hash_code());
BOOST_CHECK_NE(t1.hash_code(), template_id_with_cvr<T2>().hash_code());
BOOST_CHECK_NE(t2.hash_code(), template_id_with_cvr<T1>().hash_code());
}
BOOST_AUTO_TEST_CASE(template_id_storing_modifiers)
{
test_with_modofiers<int, const int>();
test_with_modofiers<int, const int&>();
test_with_modofiers<int, int&>();
test_with_modofiers<int, volatile int>();
test_with_modofiers<int, volatile int&>();
test_with_modofiers<int, const volatile int>();
test_with_modofiers<int, const volatile int&>();
test_with_modofiers<const int, int>();
test_with_modofiers<const int, const int&>();
test_with_modofiers<const int, int&>();
test_with_modofiers<const int, volatile int>();
test_with_modofiers<const int, volatile int&>();
test_with_modofiers<const int, const volatile int>();
test_with_modofiers<const int, const volatile int&>();
test_with_modofiers<const int&, int>();
test_with_modofiers<const int&, const int>();
test_with_modofiers<const int&, int&>();
test_with_modofiers<const int&, volatile int>();
test_with_modofiers<const int&, volatile int&>();
test_with_modofiers<const int&, const volatile int>();
test_with_modofiers<const int&, const volatile int&>();
test_with_modofiers<int&, const int>();
test_with_modofiers<int&, const int&>();
test_with_modofiers<int&, int>();
test_with_modofiers<int&, volatile int>();
test_with_modofiers<int&, volatile int&>();
test_with_modofiers<int&, const volatile int>();
test_with_modofiers<int&, const volatile int&>();
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
test_with_modofiers<int&&, const int>();
test_with_modofiers<int&&, const int&>();
test_with_modofiers<int&&, const int&&>();
test_with_modofiers<int&&, int>();
test_with_modofiers<int&&, volatile int>();
test_with_modofiers<int&&, volatile int&>();
test_with_modofiers<int&&, volatile int&&>();
test_with_modofiers<int&&, const volatile int>();
test_with_modofiers<int&&, const volatile int&>();
test_with_modofiers<int&&, const volatile int&&>();
#endif
}
template <class T>
static void test_storing_nonstoring_modifiers_templ() {
using namespace boost;
template_index t1 = template_id_with_cvr<T>();
template_index t2 = template_id<T>();
BOOST_CHECK_EQUAL(t2, t1);
BOOST_CHECK_EQUAL(t1, t2);
BOOST_CHECK(t1 <= t2);
BOOST_CHECK(t1 >= t2);
BOOST_CHECK(t2 <= t1);
BOOST_CHECK(t2 >= t1);
BOOST_CHECK_EQUAL(t2.name_demangled(), t1.name_demangled());
}
BOOST_AUTO_TEST_CASE(template_id_storing_modifiers_vs_nonstoring)
{
test_storing_nonstoring_modifiers_templ<int>();
test_storing_nonstoring_modifiers_templ<my_namespace1::my_class>();
test_storing_nonstoring_modifiers_templ<my_namespace2::my_class>();
boost::template_index t1 = boost::template_id_with_cvr<const int>();
boost::template_index t2 = boost::template_id<int>();
BOOST_CHECK_NE(t2, t1);
BOOST_CHECK(t1.name_demangled() == "const int" || t1.name_demangled() == "int const");
}
BOOST_AUTO_TEST_CASE(template_index_stream_operator_via_lexical_cast_testing)
{
using namespace boost;
std::string s_int2 = lexical_cast<std::string>(template_id<int>());
BOOST_CHECK_EQUAL(s_int2, "int");
std::string s_double2 = lexical_cast<std::string>(template_id<double>());
BOOST_CHECK_EQUAL(s_double2, "double");
}
BOOST_AUTO_TEST_CASE(template_index_stripping_cvr_test)
{
using namespace boost;
BOOST_CHECK_EQUAL(template_id<int>(), template_id<const int>());
BOOST_CHECK_EQUAL(template_id<int>(), template_id<const volatile int>());
BOOST_CHECK_EQUAL(template_id<int>(), template_id<const volatile int&>());
BOOST_CHECK_EQUAL(template_id<int>(), template_id<int&>());
BOOST_CHECK_EQUAL(template_id<int>(), template_id<volatile int>());
BOOST_CHECK_EQUAL(template_id<int>(), template_id<volatile int&>());
BOOST_CHECK_EQUAL(template_id<double>(), template_id<const double>());
BOOST_CHECK_EQUAL(template_id<double>(), template_id<const volatile double>());
BOOST_CHECK_EQUAL(template_id<double>(), template_id<const volatile double&>());
BOOST_CHECK_EQUAL(template_id<double>(), template_id<double&>());
BOOST_CHECK_EQUAL(template_id<double>(), template_id<volatile double>());
BOOST_CHECK_EQUAL(template_id<double>(), template_id<volatile double&>());
}
BOOST_AUTO_TEST_CASE(template_index_user_defined_class_test)
{
using namespace boost;
BOOST_CHECK_EQUAL(template_id<my_namespace1::my_class>(), template_id<my_namespace1::my_class>());
BOOST_CHECK_EQUAL(template_id<my_namespace2::my_class>(), template_id<my_namespace2::my_class>());
BOOST_CHECK_NE(template_id<my_namespace1::my_class>(), template_id<my_namespace2::my_class>());
BOOST_CHECK_NE(
template_id<my_namespace1::my_class>().name_demangled().find("my_namespace1::my_class"),
std::string::npos);
}

View File

@ -1,31 +0,0 @@
#define TEST_LIB_SOURCE
#include "test_lib.hpp"
namespace user_defined_namespace {
class user_defined{};
}
namespace test_lib {
boost::type_index get_integer() {
return boost::type_id<int>();
}
boost::type_index get_user_defined_class() {
return boost::type_id<user_defined_namespace::user_defined>();
}
boost::type_index get_const_integer() {
return boost::type_id_with_cvr<const int>();
}
boost::type_index get_const_user_defined_class() {
return boost::type_id_with_cvr<const user_defined_namespace::user_defined>();
}
// Just do nothing
void accept_typeindex(const boost::type_index&) {}
}

View File

@ -1,23 +0,0 @@
//
// Copyright Antony Polukhin, 2012-2013.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_TEST_MODULE testing_both_test_module
#include <boost/test/unit_test.hpp>
#include <boost/type_index.hpp>
namespace my_namespace1 {
class my_class{};
}
namespace my_namespace2 {
class my_class{};
}
#include "type_index_tests.ipp"
#include "template_index_tests.ipp"

View File

@ -1,27 +0,0 @@
//
// Copyright Antony Polukhin, 2012-2013.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_TEST_MODULE testing_both_test_module
#include <boost/test/unit_test.hpp>
#include <boost/type_index.hpp>
#ifndef BOOST_NO_RTTI
#error "This test must be run with disabled RTTI"
#endif
namespace my_namespace1 {
class my_class{};
}
namespace my_namespace2 {
class my_class{};
}
#include "type_index_tests.ipp"
#include "template_index_tests.ipp"

View File

@ -1,45 +0,0 @@
//
// Copyright Antony Polukhin, 2012-2013.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_TEST_MODULE testing_crossmodule_module
#include <boost/test/unit_test.hpp>
#include <boost/type_index/type_index.hpp>
#include "test_lib.hpp"
namespace user_defined_namespace {
class user_defined{};
}
BOOST_AUTO_TEST_CASE(comparing_types_between_modules)
{
boost::type_index t_const_int = boost::type_id_with_cvr<const int>();
boost::type_index t_int = boost::type_id<int>();
BOOST_CHECK_EQUAL(t_int, test_lib::get_integer());
BOOST_CHECK_EQUAL(t_const_int, test_lib::get_const_integer());
BOOST_CHECK_NE(t_const_int, test_lib::get_integer());
BOOST_CHECK_NE(t_int, test_lib::get_const_integer());
boost::type_index t_const_userdef = boost::type_id_with_cvr<const user_defined_namespace::user_defined>();
boost::type_index t_userdef = boost::type_id<user_defined_namespace::user_defined>();
BOOST_CHECK_EQUAL(t_userdef, test_lib::get_user_defined_class());
BOOST_CHECK_EQUAL(t_const_userdef, test_lib::get_const_user_defined_class());
BOOST_CHECK_NE(t_const_userdef, test_lib::get_user_defined_class());
BOOST_CHECK_NE(t_userdef, test_lib::get_const_user_defined_class());
BOOST_CHECK_NE(t_userdef, test_lib::get_integer());
BOOST_CHECK_NE(t_const_userdef, test_lib::get_integer());
BOOST_CHECK_NE(t_int, test_lib::get_user_defined_class());
BOOST_CHECK_NE(t_const_int, test_lib::get_const_user_defined_class());
test_lib::accept_typeindex(t_int);
}

View File

@ -1,26 +0,0 @@
//
// Copyright Antony Polukhin, 2012-2013.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_TEST_MODULE testing_both_test_module
#include <boost/test/unit_test.hpp>
#include <boost/type_index/type_index_minimal.hpp>
#ifndef BOOST_NO_RTTI
#error "This test must be run with disabled RTTI"
#endif
namespace my_namespace1 {
class my_class{};
}
namespace my_namespace2 {
class my_class{};
}
#include "type_index_tests.ipp"

View File

@ -1,22 +0,0 @@
//
// Copyright Antony Polukhin, 2012-2013.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_TEST_MODULE type_index_test_module
#include <boost/test/unit_test.hpp>
#include <boost/type_index/type_index.hpp>
namespace my_namespace1 {
class my_class{};
}
namespace my_namespace2 {
class my_class{};
}
#include "type_index_tests.ipp"

View File

@ -1,302 +0,0 @@
//
// Copyright Antony Polukhin, 2012.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/functional/hash.hpp>
#include <boost/lexical_cast.hpp>
BOOST_AUTO_TEST_CASE(names_matches_type_id)
{
using namespace boost;
BOOST_CHECK_EQUAL(type_id<int>().name_demangled(), "int");
BOOST_CHECK_EQUAL(type_id<double>().name_demangled(), "double");
BOOST_CHECK_EQUAL(type_id<int>().name(), type_id<int>().name());
BOOST_CHECK_NE(type_id<int>().name(), type_id<double>().name());
BOOST_CHECK_NE(type_id<double>().name(), type_id<int>().name());
BOOST_CHECK_EQUAL(type_id<double>().name(), type_id<double>().name());
}
BOOST_AUTO_TEST_CASE(comparators_type_id)
{
using namespace boost;
type_index t_int = type_id<int>();
type_index t_double = type_id<double>();
BOOST_CHECK_EQUAL(t_int, t_int);
BOOST_CHECK_LE(t_int, t_int);
BOOST_CHECK_GE(t_int, t_int);
BOOST_CHECK_NE(t_int, t_double);
BOOST_CHECK_LE(t_double, t_double);
BOOST_CHECK_GE(t_double, t_double);
BOOST_CHECK_NE(t_double, t_int);
BOOST_CHECK(t_double < t_int || t_int < t_double);
BOOST_CHECK(t_double > t_int || t_int > t_double);
}
BOOST_AUTO_TEST_CASE(hash_code_type_id)
{
using namespace boost;
std::size_t t_int1 = type_id<int>().hash_code();
std::size_t t_double1 = type_id<double>().hash_code();
std::size_t t_int2 = type_id<int>().hash_code();
std::size_t t_double2 = type_id<double>().hash_code();
BOOST_CHECK_EQUAL(t_int1, t_int2);
BOOST_CHECK_NE(t_int1, t_double2);
BOOST_CHECK_LE(t_double1, t_double2);
}
#ifndef BOOST_NO_RTTI
BOOST_AUTO_TEST_CASE(comparators_type_id_vs_type_info)
{
using namespace boost;
type_index t_int = type_id<int>();
BOOST_CHECK(t_int == typeid(int));
BOOST_CHECK(typeid(int) == t_int);
BOOST_CHECK(t_int <= typeid(int));
BOOST_CHECK(typeid(int) <= t_int);
BOOST_CHECK(t_int >= typeid(int));
BOOST_CHECK(typeid(int) >= t_int);
type_index t_double = type_id<double>();
BOOST_CHECK(t_double == typeid(double));
BOOST_CHECK(typeid(double) == t_double);
BOOST_CHECK(t_double <= typeid(double));
BOOST_CHECK(typeid(double) <= t_double);
BOOST_CHECK(t_double >= typeid(double));
BOOST_CHECK(typeid(double) >= t_double);
if (t_double < t_int) {
BOOST_CHECK(t_double < typeid(int));
BOOST_CHECK(typeid(double) < t_int);
BOOST_CHECK(typeid(int) > t_double);
BOOST_CHECK(t_int > typeid(double));
BOOST_CHECK(t_double <= typeid(int));
BOOST_CHECK(typeid(double) <= t_int);
BOOST_CHECK(typeid(int) >= t_double);
BOOST_CHECK(t_int >= typeid(double));
} else {
BOOST_CHECK(t_double > typeid(int));
BOOST_CHECK(typeid(double) > t_int);
BOOST_CHECK(typeid(int) < t_double);
BOOST_CHECK(t_int < typeid(double));
BOOST_CHECK(t_double >= typeid(int));
BOOST_CHECK(typeid(double) >= t_int);
BOOST_CHECK(typeid(int) <= t_double);
BOOST_CHECK(t_int <= typeid(double));
}
}
#endif // BOOST_NO_RTTI
template <class T1, class T2>
static void test_with_modofiers_type_id() {
using namespace boost;
type_index t1 = type_id_with_cvr<T1>();
type_index t2 = type_id_with_cvr<T2>();
BOOST_CHECK_NE(t2, t1);
BOOST_CHECK(t1 < t2 || t2 < t1);
BOOST_CHECK(t1 > t2 || t2 > t1);
BOOST_CHECK_EQUAL(t1, type_id_with_cvr<T1>());
BOOST_CHECK_EQUAL(t2, type_id_with_cvr<T2>());
BOOST_CHECK_EQUAL(t1.hash_code(), type_id_with_cvr<T1>().hash_code());
BOOST_CHECK_EQUAL(t2.hash_code(), type_id_with_cvr<T2>().hash_code());
BOOST_CHECK_NE(t1.hash_code(), type_id_with_cvr<T2>().hash_code());
BOOST_CHECK_NE(t2.hash_code(), type_id_with_cvr<T1>().hash_code());
}
BOOST_AUTO_TEST_CASE(type_id_storing_modifiers)
{
test_with_modofiers_type_id<int, const int>();
test_with_modofiers_type_id<int, const int&>();
test_with_modofiers_type_id<int, int&>();
test_with_modofiers_type_id<int, volatile int>();
test_with_modofiers_type_id<int, volatile int&>();
test_with_modofiers_type_id<int, const volatile int>();
test_with_modofiers_type_id<int, const volatile int&>();
test_with_modofiers_type_id<const int, int>();
test_with_modofiers_type_id<const int, const int&>();
test_with_modofiers_type_id<const int, int&>();
test_with_modofiers_type_id<const int, volatile int>();
test_with_modofiers_type_id<const int, volatile int&>();
test_with_modofiers_type_id<const int, const volatile int>();
test_with_modofiers_type_id<const int, const volatile int&>();
test_with_modofiers_type_id<const int&, int>();
test_with_modofiers_type_id<const int&, const int>();
test_with_modofiers_type_id<const int&, int&>();
test_with_modofiers_type_id<const int&, volatile int>();
test_with_modofiers_type_id<const int&, volatile int&>();
test_with_modofiers_type_id<const int&, const volatile int>();
test_with_modofiers_type_id<const int&, const volatile int&>();
test_with_modofiers_type_id<int&, const int>();
test_with_modofiers_type_id<int&, const int&>();
test_with_modofiers_type_id<int&, int>();
test_with_modofiers_type_id<int&, volatile int>();
test_with_modofiers_type_id<int&, volatile int&>();
test_with_modofiers_type_id<int&, const volatile int>();
test_with_modofiers_type_id<int&, const volatile int&>();
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
test_with_modofiers_type_id<int&&, const int>();
test_with_modofiers_type_id<int&&, const int&>();
test_with_modofiers_type_id<int&&, const int&&>();
test_with_modofiers_type_id<int&&, int>();
test_with_modofiers_type_id<int&&, volatile int>();
test_with_modofiers_type_id<int&&, volatile int&>();
test_with_modofiers_type_id<int&&, volatile int&&>();
test_with_modofiers_type_id<int&&, const volatile int>();
test_with_modofiers_type_id<int&&, const volatile int&>();
test_with_modofiers_type_id<int&&, const volatile int&&>();
#endif
}
template <class T>
static void test_storing_nonstoring_modifiers() {
using namespace boost;
type_index t1 = type_id_with_cvr<T>();
type_index t2 = type_id<T>();
BOOST_CHECK_EQUAL(t2, t1);
BOOST_CHECK_EQUAL(t1, t2);
BOOST_CHECK(t1 <= t2);
BOOST_CHECK(t1 >= t2);
BOOST_CHECK(t2 <= t1);
BOOST_CHECK(t2 >= t1);
BOOST_CHECK_EQUAL(t2.name_demangled(), t1.name_demangled());
}
BOOST_AUTO_TEST_CASE(type_id_storing_modifiers_vs_nonstoring)
{
test_storing_nonstoring_modifiers<int>();
test_storing_nonstoring_modifiers<my_namespace1::my_class>();
test_storing_nonstoring_modifiers<my_namespace2::my_class>();
boost::type_index t1 = boost::type_id_with_cvr<const int>();
boost::type_index t2 = boost::type_id<int>();
BOOST_CHECK_NE(t2, t1);
BOOST_CHECK(t1.name_demangled() == "const int" || t1.name_demangled() == "int const");
}
BOOST_AUTO_TEST_CASE(type_index_stream_operator_via_lexical_cast_testing)
{
using namespace boost;
std::string s_int1 = lexical_cast<std::string>(type_id<int>());
BOOST_CHECK_EQUAL(s_int1, "int");
std::string s_double1 = lexical_cast<std::string>(type_id<double>());
BOOST_CHECK_EQUAL(s_double1, "double");
}
BOOST_AUTO_TEST_CASE(type_index_stripping_cvr_test)
{
using namespace boost;
BOOST_CHECK_EQUAL(type_id<int>(), type_id<const int>());
BOOST_CHECK_EQUAL(type_id<int>(), type_id<const volatile int>());
BOOST_CHECK_EQUAL(type_id<int>(), type_id<const volatile int&>());
BOOST_CHECK_EQUAL(type_id<int>(), type_id<int&>());
BOOST_CHECK_EQUAL(type_id<int>(), type_id<volatile int>());
BOOST_CHECK_EQUAL(type_id<int>(), type_id<volatile int&>());
BOOST_CHECK_EQUAL(type_id<double>(), type_id<const double>());
BOOST_CHECK_EQUAL(type_id<double>(), type_id<const volatile double>());
BOOST_CHECK_EQUAL(type_id<double>(), type_id<const volatile double&>());
BOOST_CHECK_EQUAL(type_id<double>(), type_id<double&>());
BOOST_CHECK_EQUAL(type_id<double>(), type_id<volatile double>());
BOOST_CHECK_EQUAL(type_id<double>(), type_id<volatile double&>());
}
BOOST_AUTO_TEST_CASE(type_index_user_defined_class_test)
{
using namespace boost;
BOOST_CHECK_EQUAL(type_id<my_namespace1::my_class>(), type_id<my_namespace1::my_class>());
BOOST_CHECK_EQUAL(type_id<my_namespace2::my_class>(), type_id<my_namespace2::my_class>());
#ifndef BOOST_NO_RTTI
BOOST_CHECK(type_id<my_namespace1::my_class>() == typeid(my_namespace1::my_class));
BOOST_CHECK(type_id<my_namespace2::my_class>() == typeid(my_namespace2::my_class));
BOOST_CHECK(typeid(my_namespace1::my_class) == type_id<my_namespace1::my_class>());
BOOST_CHECK(typeid(my_namespace2::my_class) == type_id<my_namespace2::my_class>());
#endif
BOOST_CHECK_NE(type_id<my_namespace1::my_class>(), type_id<my_namespace2::my_class>());
BOOST_CHECK_NE(
type_id<my_namespace1::my_class>().name_demangled().find("my_namespace1::my_class"),
std::string::npos);
}
#ifndef BOOST_NO_RTTI
class A { public: virtual ~A(){} };
class B: public A{};
class C: public B {};
BOOST_AUTO_TEST_CASE(comparators_type_id_rtti_only)
{
C c1;
B b1;
A* pc1 = &c1;
A& rc1 = c1;
A* pb1 = &b1;
A& rb1 = b1;
BOOST_CHECK(typeid(rc1) == typeid(*pc1));
BOOST_CHECK(typeid(rb1) == typeid(*pb1));
BOOST_CHECK(typeid(rc1) != typeid(*pb1));
BOOST_CHECK(typeid(rb1) != typeid(*pc1));
BOOST_CHECK(typeid(&rc1) == typeid(pb1));
BOOST_CHECK(typeid(&rb1) == typeid(pc1));
BOOST_CHECK_EQUAL(boost::type_id_rtti_only(rc1), boost::type_id_rtti_only(*pc1));
BOOST_CHECK_EQUAL(boost::type_id_rtti_only(rb1), boost::type_id_rtti_only(*pb1));
BOOST_CHECK_NE(boost::type_id_rtti_only(rc1), boost::type_id_rtti_only(*pb1));
BOOST_CHECK_NE(boost::type_id_rtti_only(rb1), boost::type_id_rtti_only(*pc1));
BOOST_CHECK_EQUAL(boost::type_id_rtti_only(&rc1), boost::type_id_rtti_only(pb1));
BOOST_CHECK_EQUAL(boost::type_id_rtti_only(&rb1), boost::type_id_rtti_only(pc1));
BOOST_CHECK(boost::type_id_rtti_only(rc1) == typeid(*pc1));
BOOST_CHECK(boost::type_id_rtti_only(rb1) == typeid(*pb1));
BOOST_CHECK(boost::type_id_rtti_only(rc1) != typeid(*pb1));
BOOST_CHECK(boost::type_id_rtti_only(rb1) != typeid(*pc1));
BOOST_CHECK(boost::type_id_rtti_only(&rc1) == typeid(pb1));
BOOST_CHECK(boost::type_id_rtti_only(&rb1) == typeid(pc1));
}
#endif // BOOST_NO_RTTI

15
meta/libraries.json Normal file
View File

@ -0,0 +1,15 @@
{
"key": "type_index",
"name": "Type Index",
"authors": [
"Antony Polukhin"
],
"maintainers": [
"Antony Polukhin <antoshkka -at- gmail.com>"
],
"description": "Runtime/Compile time copyable type info.",
"category": [
"Emulation"
],
"cxxstd": "03"
}

View File

@ -3,3 +3,7 @@ patches for Boost libraries to work without RTTI
Here are the patches that are TESTED and work well with RTTI disabled and enabled.
Patches add tests for some of the libraries to make sure that library compile and work without RTTI.
Patches remove duplicate code, improve output, allow compilation with RTTI off...
Libraries Boost.Graph, Boost.XPressive, Boost.PropertyMap and others may also benefit from TypeIndex library.

View File

@ -1,12 +0,0 @@
Index: .
===================================================================
--- . (revision 86520)
+++ . (working copy)
@@ -8,6 +8,7 @@
test-suite any :
[ run ../any_test.cpp ]
+ [ run ../any_test.cpp : : : <rtti>off : testing_any_no_rtti ]
[ run any_test_rv.cpp ]
[ compile-fail any_cast_cv_failed.cpp ]
[ compile-fail any_test_temporary_to_ref_failed.cpp ]

View File

@ -1,91 +0,0 @@
Index: .
===================================================================
--- . (revision 86520)
+++ . (working copy)
@@ -15,7 +15,7 @@
// when: July 2001, April 2013 - May 2013
#include <algorithm>
-#include <typeinfo>
+#include <boost/type_index/type_info.hpp>
#include "boost/config.hpp"
#include <boost/type_traits/remove_reference.hpp>
@@ -29,17 +29,6 @@
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_const.hpp>
-// See boost/python/type_id.hpp
-// TODO: add BOOST_TYPEID_COMPARE_BY_NAME to config.hpp
-# if defined(__GNUC__) \
- || defined(_AIX) \
- || ( defined(__sgi) && defined(__host_mips)) \
- || (defined(__hpux) && defined(__HP_aCC)) \
- || (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC))
-# define BOOST_AUX_ANY_TYPE_ID_NAME
-#include <cstring>
-# endif
-
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable: 4172) // Mistakenly warns: returning address of local variable or temporary
@@ -149,9 +138,9 @@
any().swap(*this);
}
- const std::type_info & type() const BOOST_NOEXCEPT
+ const boost::type_info & type() const BOOST_NOEXCEPT
{
- return content ? content->type() : typeid(void);
+ return content ? content->type() : boost::type_id<void>();
}
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
@@ -170,7 +159,7 @@
public: // queries
- virtual const std::type_info & type() const BOOST_NOEXCEPT = 0;
+ virtual const boost::type_info & type() const BOOST_NOEXCEPT = 0;
virtual placeholder * clone() const = 0;
@@ -194,9 +183,9 @@
#endif
public: // queries
- virtual const std::type_info & type() const BOOST_NOEXCEPT
+ virtual const boost::type_info & type() const BOOST_NOEXCEPT
{
- return typeid(ValueType);
+ return boost::type_id<ValueType>();
}
virtual placeholder * clone() const
@@ -237,7 +226,12 @@
lhs.swap(rhs);
}
- class BOOST_SYMBOL_VISIBLE bad_any_cast : public std::bad_cast
+ class BOOST_SYMBOL_VISIBLE bad_any_cast :
+#ifndef BOOST_NO_RTTI
+ public std::bad_cast
+#else
+ public std::exception
+#endif
{
public:
virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW
@@ -251,11 +245,7 @@
ValueType * any_cast(any * operand) BOOST_NOEXCEPT
{
return operand &&
-#ifdef BOOST_AUX_ANY_TYPE_ID_NAME
- std::strcmp(operand->type().name(), typeid(ValueType).name()) == 0
-#else
- operand->type() == typeid(ValueType)
-#endif
+ operand->type() == boost::type_id<ValueType>()
? &static_cast<any::holder<ValueType> *>(operand->content)->held
: 0;
}

View File

@ -1,61 +0,0 @@
Index: .
===================================================================
--- . (revision 86520)
+++ . (working copy)
@@ -91,7 +91,10 @@
check_true(value.empty(), "empty");
check_null(any_cast<int>(&value), "any_cast<int>");
+#ifndef BOOST_NO_RTTI
check_equal(value.type(), typeid(void), "type");
+#endif
+ check_equal(value.type(), boost::type_id<void>(), "type boost");
}
void test_converting_ctor()
@@ -100,7 +103,10 @@
any value = text;
check_false(value.empty(), "empty");
+#ifndef BOOST_NO_RTTI
check_equal(value.type(), typeid(std::string), "type");
+#endif
+ check_equal(value.type(), boost::type_id<std::string>(), "type boost");
check_null(any_cast<int>(&value), "any_cast<int>");
check_non_null(any_cast<std::string>(&value), "any_cast<std::string>");
check_equal(
@@ -158,7 +164,10 @@
any * assign_result = &(value = text);
check_false(value.empty(), "type");
+#ifndef BOOST_NO_RTTI
check_equal(value.type(), typeid(std::string), "type");
+#endif
+ check_equal(value.type(), boost::type_id<std::string>(), "type boost");
check_null(any_cast<int>(&value), "any_cast<int>");
check_non_null(any_cast<std::string>(&value), "any_cast<std::string>");
check_equal(
@@ -191,7 +200,10 @@
check_true(original.empty(), "empty on original");
check_false(swapped.empty(), "empty on swapped");
+#ifndef BOOST_NO_RTTI
check_equal(swapped.type(), typeid(std::string), "type");
+#endif
+ check_equal(swapped.type(), boost::type_id<std::string>(), "type boost");
check_equal(
text, any_cast<std::string>(swapped),
"comparing swapped copy against original text");
@@ -264,8 +276,12 @@
check_false(value1.empty(), "type");
check_false(value2.empty(), "type");
+#ifndef BOOST_NO_RTTI
check_equal(value1.type(), typeid(const char*), "type");
check_equal(value2.type(), typeid(const char*), "type");
+#endif
+ check_equal(value1.type(), boost::type_id<const char*>(), "type boost");
+ check_equal(value2.type(), boost::type_id<const char*>(), "type boost");
check_non_null(any_cast<const char*>(&value1), "any_cast<const char*>");
check_non_null(any_cast<const char*>(&value2), "any_cast<const char*>");

View File

@ -1,29 +1,45 @@
Index: .
===================================================================
--- . (revision 86532)
+++ . (working copy)
@@ -15,121 +15,15 @@
From b77c0af6af8bc4797defc3627878acc3cf7a6f39 Mon Sep 17 00:00:00 2001
From: Antony Polukhin <antoshkka@gmail.com>
Date: Thu, 20 Feb 2014 17:57:24 +0400
Subject: [PATCH] detail/sp_typeinfo.hpp now uses TypeIndex
---
include/boost/detail/sp_typeinfo.hpp | 123 +++--------------------------------
1 file changed, 8 insertions(+), 115 deletions(-)
diff --git a/include/boost/detail/sp_typeinfo.hpp b/include/boost/detail/sp_typeinfo.hpp
index 43fae78..fbdf86d 100644
--- a/include/boost/detail/sp_typeinfo.hpp
+++ b/include/boost/detail/sp_typeinfo.hpp
@@ -10,126 +10,19 @@
// detail/sp_typeinfo.hpp
//
// Copyright 2007 Peter Dimov
+// Copyright 2014 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#include <boost/config.hpp>
+#include <boost/type_index/type_info.hpp>
-#if defined( BOOST_NO_TYPEID )
+#include <boost/type_index.hpp>
+namespace boost { namespace detail {
-#include <boost/current_function.hpp>
-#include <functional>
+typedef boost::type_info sp_typeinfo;
-namespace boost
-{
+
+typedef boost::typeind::type_info sp_typeinfo;
+
+}} // namespace boost::detail
-#if defined( BOOST_NO_TYPEID )
-
-#include <boost/current_function.hpp>
-#include <functional>
-
-namespace boost
-{
-
-namespace detail
-{
+#define BOOST_SP_TYPEID(T) (boost::type_id<T>())
-
-class sp_typeinfo
-{
-private:
@ -127,6 +143,9 @@ Index: .
-#define BOOST_SP_TYPEID(T) typeid(T)
-
-#endif
-
+#define BOOST_SP_TYPEID(T) (boost::typeind::type_id<T>().type_info())
#endif // #ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED
+
--
1.8.5.3

View File

@ -0,0 +1,156 @@
From 8f57d59bfbc978673a2493a90b4f3e7e54ddbf18 Mon Sep 17 00:00:00 2001
From: Antony Polukhin <antoshkka@gmail.com>
Date: Thu, 20 Feb 2014 18:30:11 +0400
Subject: [PATCH] Boost.Exception now uses TypeIndex to reduce duplicate code
and simplify name demanglings
---
include/boost/exception/detail/type_info.hpp | 43 +++-------------------
include/boost/exception/diagnostic_information.hpp | 2 +-
include/boost/exception/exception.hpp | 3 +-
include/boost/exception/info.hpp | 2 +-
test/Jamfile.v2 | 2 +
5 files changed, 12 insertions(+), 40 deletions(-)
diff --git a/include/boost/exception/detail/type_info.hpp b/include/boost/exception/detail/type_info.hpp
index 6e5942d..a247b71 100644
--- a/include/boost/exception/detail/type_info.hpp
+++ b/include/boost/exception/detail/type_info.hpp
@@ -12,13 +12,7 @@
#pragma warning(push,1)
#endif
-#include <boost/detail/sp_typeinfo.hpp>
-#include <boost/current_function.hpp>
-#include <boost/config.hpp>
-//#ifndef BOOST_NO_TYPEID
-//#include <boost/units/detail/utility.hpp>
-//#endif
-#include <string>
+#include <boost/type_index.hpp>
namespace
boost
@@ -28,11 +22,7 @@ boost
std::string
tag_type_name()
{
-#ifdef BOOST_NO_TYPEID
- return BOOST_CURRENT_FUNCTION;
-#else
- return /*units::detail::demangle*/(typeid(T*).name());
-#endif
+ return boost::typeind::type_id<T*>().pretty_name();
}
template <class T>
@@ -40,41 +30,20 @@ boost
std::string
type_name()
{
-#ifdef BOOST_NO_TYPEID
- return BOOST_CURRENT_FUNCTION;
-#else
- return /*units::detail::demangle*/(typeid(T).name());
-#endif
+ return boost::typeind::type_id<T>().pretty_name();
}
namespace
exception_detail
{
- struct
- type_info_
- {
- detail::sp_typeinfo const * type_;
-
- explicit
- type_info_( detail::sp_typeinfo const & type ):
- type_(&type)
- {
- }
-
- friend
- bool
- operator<( type_info_ const & a, type_info_ const & b )
- {
- return 0!=(a.type_->before(*b.type_));
- }
- };
+ typedef boost::typeind::type_index type_info_;
}
}
-#define BOOST_EXCEPTION_STATIC_TYPEID(T) ::boost::exception_detail::type_info_(BOOST_SP_TYPEID(T))
+#define BOOST_EXCEPTION_STATIC_TYPEID(T) ::boost::typeind::type_id<T>()
#ifndef BOOST_NO_RTTI
-#define BOOST_EXCEPTION_DYNAMIC_TYPEID(x) ::boost::exception_detail::type_info_(typeid(x))
+#define BOOST_EXCEPTION_DYNAMIC_TYPEID(x) ::boost::typeind::type_id_runtime(x)
#endif
#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
diff --git a/include/boost/exception/diagnostic_information.hpp b/include/boost/exception/diagnostic_information.hpp
index 2f5cb88..0f8b5e8 100644
--- a/include/boost/exception/diagnostic_information.hpp
+++ b/include/boost/exception/diagnostic_information.hpp
@@ -151,7 +151,7 @@ boost
#ifndef BOOST_NO_RTTI
if ( verbose )
tmp << std::string("Dynamic exception type: ") <<
- /*units::detail::demangle*/((be?(BOOST_EXCEPTION_DYNAMIC_TYPEID(*be)):(BOOST_EXCEPTION_DYNAMIC_TYPEID(*se))).type_->name()) << '\n';
+ /*units::detail::demangle*/((be?(BOOST_EXCEPTION_DYNAMIC_TYPEID(*be)):(BOOST_EXCEPTION_DYNAMIC_TYPEID(*se)))) << '\n';
#endif
if( with_what && se && verbose )
tmp << "std::exception::what: " << wh << '\n';
diff --git a/include/boost/exception/exception.hpp b/include/boost/exception/exception.hpp
index 9f20a04..53c341f 100644
--- a/include/boost/exception/exception.hpp
+++ b/include/boost/exception/exception.hpp
@@ -12,6 +12,8 @@
#pragma warning(push,1)
#endif
+#include <boost/exception/detail/type_info.hpp>
+
namespace
boost
{
@@ -151,7 +153,6 @@ boost
exception_detail
{
class error_info_base;
- struct type_info_;
struct
error_info_container
diff --git a/include/boost/exception/info.hpp b/include/boost/exception/info.hpp
index edbf058..e0f4950 100644
--- a/include/boost/exception/info.hpp
+++ b/include/boost/exception/info.hpp
@@ -96,7 +96,7 @@ boost
{
shared_ptr<error_info_base> const & p = i->second;
#ifndef BOOST_NO_RTTI
- BOOST_ASSERT( *BOOST_EXCEPTION_DYNAMIC_TYPEID(*p).type_==*ti.type_ );
+ BOOST_ASSERT(BOOST_EXCEPTION_DYNAMIC_TYPEID(*p)==ti );
#endif
return p;
}
diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
index d2dfcd6..5bd076d 100644
--- a/test/Jamfile.v2
+++ b/test/Jamfile.v2
@@ -35,7 +35,9 @@ run enable_error_info_test.cpp helper1.cpp ;
run throw_exception_test.cpp helper2.cpp ;
run errno_test.cpp ;
run error_info_test.cpp ;
+run error_info_test.cpp : : : <rtti>off : error_info_test_rtti ;
run diagnostic_information_test.cpp ;
+run diagnostic_information_test.cpp : : : <rtti>off : diagnostic_information_test_rtti ;
run refcount_ptr_test.cpp ;
run current_exception_cast_test.cpp ;
run no_exceptions_test.cpp : : : <exception-handling>off ;
--
1.8.5.3

View File

@ -0,0 +1,26 @@
From 03194eefcb9c3314054855d28bd9a90d3188768d Mon Sep 17 00:00:00 2001
From: Antony Polukhin <antoshkka@gmail.com>
Date: Thu, 20 Feb 2014 18:50:10 +0400
Subject: [PATCH] Use TypeIndex features in Boost.SharedPtr to avoid type_info
related bugs
---
include/boost/smart_ptr/detail/sp_counted_impl.hpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/boost/smart_ptr/detail/sp_counted_impl.hpp b/include/boost/smart_ptr/detail/sp_counted_impl.hpp
index a7b43ae..5955036 100644
--- a/include/boost/smart_ptr/detail/sp_counted_impl.hpp
+++ b/include/boost/smart_ptr/detail/sp_counted_impl.hpp
@@ -155,7 +155,7 @@ public:
virtual void * get_deleter( detail::sp_typeinfo const & ti )
{
- return ti == BOOST_SP_TYPEID(D)? &reinterpret_cast<char&>( del ): 0;
+ return ti == boost::typeind::type_id<D>()? &reinterpret_cast<char&>( del ): 0;
}
virtual void * get_untyped_deleter()
--
1.8.5.3

View File

@ -1 +0,0 @@
To be honest sp_typeinfo.hpp won't be required with Boost.TypeIndex, because Boost.TypeIndex is more functional then sp_typeinfo and requires much less macro for usage. sp_typeinfo.patch contains a temporary solution for easy migration. Later sp_typeinfo may be removed and BOOST_SP_TYPEID(T) macro deprecated.

View File

@ -1,23 +0,0 @@
Index: .
===================================================================
--- . (revision 86520)
+++ . (working copy)
@@ -59,6 +59,10 @@
/boost/test//boost_test_exec_monitor/<link>static
../build//boost_graph
../../regex/build//boost_regex : --log_level=all ]
+ [ run graphviz_test.cpp
+ /boost/test//boost_test_exec_monitor/<link>static
+ ../build//boost_graph
+ ../../regex/build//boost_regex : --log_level=all : : <rtti>off : testing_graphviz_no_rtti ]
[ run metis_test.cpp : $(METIS_INPUT_FILE) ]
[ run gursoy_atun_layout_test.cpp ]
[ run layout_test.cpp : : : <test-info>always_show_run_output <toolset>intel:<debug-symbols>off ]
@@ -124,6 +128,7 @@
[ run two_graphs_common_spanning_trees_test.cpp ]
[ run random_spanning_tree_test.cpp ../build//boost_graph ]
[ run graphml_test.cpp ../build//boost_graph : : "graphml_test.xml" ]
+ [ run graphml_test.cpp ../build//boost_graph : : "graphml_test.xml" : <rtti>off : testing_graphml_no_rtti ]
[ run mas_test.cpp ../../test/build//boost_unit_test_framework/<link>static : $(TEST_DIR) ]
[ run stoer_wagner_test.cpp ../../test/build//boost_unit_test_framework/<link>static : $(TEST_DIR) ]
[ compile filtered_graph_properties_dijkstra.cpp ]

View File

@ -1,83 +0,0 @@
Index: .
===================================================================
--- . (revision 86520)
+++ . (working copy)
@@ -18,7 +18,7 @@
#include <boost/type_traits/is_convertible.hpp>
#include <boost/graph/dll_import_export.hpp>
#include <boost/graph/graphviz.hpp> // for exceptions
-#include <typeinfo>
+#include <boost/type_index/type_info.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/find.hpp>
@@ -218,16 +218,16 @@
class get_type_name
{
public:
- get_type_name(const std::type_info& type, const char** type_names, std::string& type_name)
+ get_type_name(const boost::type_info& type, const char** type_names, std::string& type_name)
: m_type(type), m_type_names(type_names), m_type_name(type_name) {}
template <typename Type>
void operator()(Type)
{
- if (typeid(Type) == m_type)
+ if (boost::type_id<Type>() == m_type)
m_type_name = m_type_names[mpl::find<Types,Type>::type::pos::value];
}
private:
- const std::type_info &m_type;
+ const boost::type_info &m_type;
const char** m_type_names;
std::string &m_type_name;
};
@@ -262,18 +262,18 @@
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
{
std::string key_id = "key" + lexical_cast<std::string>(key_count++);
- if (i->second->key() == typeid(Graph*))
+ if (i->second->key() == boost::type_id<Graph*>())
graph_key_ids[i->first] = key_id;
- else if (i->second->key() == typeid(vertex_descriptor))
+ else if (i->second->key() == boost::type_id<vertex_descriptor>())
vertex_key_ids[i->first] = key_id;
- else if (i->second->key() == typeid(edge_descriptor))
+ else if (i->second->key() == boost::type_id<edge_descriptor>())
edge_key_ids[i->first] = key_id;
else
continue;
std::string type_name = "string";
mpl::for_each<value_types>(get_type_name<value_types>(i->second->value(), type_names, type_name));
out << " <key id=\"" << encode_char_entities(key_id) << "\" for=\""
- << (i->second->key() == typeid(Graph*) ? "graph" : (i->second->key() == typeid(vertex_descriptor) ? "node" : "edge")) << "\""
+ << (i->second->key() == boost::type_id<Graph*>() ? "graph" : (i->second->key() == boost::type_id<vertex_descriptor>() ? "node" : "edge")) << "\""
<< " attr.name=\"" << i->first << "\""
<< " attr.type=\"" << type_name << "\""
<< " />\n";
@@ -287,7 +287,7 @@
// Output graph data
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
{
- if (i->second->key() == typeid(Graph*))
+ if (i->second->key() == boost::type_id<Graph*>())
{
// The const_cast here is just to get typeid correct for property
// map key; the graph should not be mutated using it.
@@ -304,7 +304,7 @@
// Output data
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
{
- if (i->second->key() == typeid(vertex_descriptor))
+ if (i->second->key() == boost::type_id<vertex_descriptor>())
{
out << " <data key=\"" << vertex_key_ids[i->first] << "\">"
<< encode_char_entities(i->second->get_string(*v)) << "</data>\n";
@@ -325,7 +325,7 @@
// Output data
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
{
- if (i->second->key() == typeid(edge_descriptor))
+ if (i->second->key() == boost::type_id<edge_descriptor>())
{
out << " <data key=\"" << edge_key_ids[i->first] << "\">"
<< encode_char_entities(i->second->get_string(*e)) << "</data>\n";

View File

@ -1,30 +0,0 @@
Index: .
===================================================================
--- . (revision 86520)
+++ . (working copy)
@@ -16,6 +16,7 @@
#include <iostream>
#include <fstream>
#include <stdio.h> // for FILE
+#include <boost/type_index/type_info.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/graph/graph_traits.hpp>
@@ -489,7 +490,7 @@
bool first = true;
for (dynamic_properties::const_iterator i = dp->begin();
i != dp->end(); ++i) {
- if (typeid(key) == i->second->key()) {
+ if (boost::type_id<Descriptor>() == i->second->key()) {
if (first) out << " [";
else out << ", ";
first = false;
@@ -518,7 +519,7 @@
bool first = true;
for (dynamic_properties::const_iterator i = dp->begin();
i != dp->end(); ++i) {
- if (typeid(key) == i->second->key()
+ if (boost::type_id<Descriptor>() == i->second->key()
&& i->first != *node_id) {
if (first) out << " [";
else out << ", ";

View File

@ -1,40 +0,0 @@
Index: .
===================================================================
--- . (revision 86520)
+++ . (working copy)
@@ -22,7 +22,7 @@
#include <boost/iterator/counting_iterator.hpp>
#include <boost/random/uniform_int.hpp>
#include <boost/shared_ptr.hpp>
-#include <typeinfo>
+#include <boost/type_index/type_info.hpp>
namespace boost { namespace parallel {
@@ -71,7 +71,7 @@
virtual void* address() { return &distribution_; }
virtual const void* address() const { return &distribution_; }
- virtual const std::type_info& type() const { return typeid(Distribution); }
+ virtual const boost::type_info& type() const { return boost::type_id<Distribution>(); }
private:
Distribution distribution_;
@@ -106,7 +106,7 @@
template<typename T>
T* as()
{
- if (distribution_->type() == typeid(T))
+ if (distribution_->type() == boost::type_id<T>())
return static_cast<T*>(distribution_->address());
else
return 0;
@@ -115,7 +115,7 @@
template<typename T>
const T* as() const
{
- if (distribution_->type() == typeid(T))
+ if (distribution_->type() == boost::type_id<T>())
return static_cast<T*>(distribution_->address());
else
return 0;

View File

@ -1,3 +0,0 @@
This patch requires additional care.
It works and tested through the Boost.Graph tests, but in some places `typeid(variable)` were replaced with `typeid(Type)`.

View File

@ -1,80 +0,0 @@
Index: .
===================================================================
--- . (revision 86520)
+++ . (working copy)
@@ -24,7 +24,7 @@
#include <boost/any.hpp>
#include <boost/function/function3.hpp>
#include <boost/type_traits/is_convertible.hpp>
-#include <typeinfo>
+#include <boost/type_index/type_info.hpp>
#include <boost/mpl/bool.hpp>
#include <stdexcept>
#include <sstream>
@@ -60,8 +60,8 @@
virtual boost::any get(const any& key) = 0;
virtual std::string get_string(const any& key) = 0;
virtual void put(const any& key, const any& value) = 0;
- virtual const std::type_info& key() const = 0;
- virtual const std::type_info& value() const = 0;
+ virtual const boost::type_info& key() const = 0;
+ virtual const boost::type_info& value() const = 0;
};
@@ -147,7 +147,7 @@
using boost::put;
key_type key = any_cast<key_type>(in_key);
- if (in_value.type() == typeid(value_type)) {
+ if (in_value.type() == boost::type_id<value_type>()) {
put(property_map_, key, any_cast<value_type>(in_value));
} else {
// if in_value is an empty string, put a default constructed value_type.
@@ -188,8 +188,8 @@
writable_property_map_tag*>::value)>());
}
- virtual const std::type_info& key() const { return typeid(key_type); }
- virtual const std::type_info& value() const { return typeid(value_type); }
+ virtual const boost::type_info& key() const { return boost::type_id<key_type>(); }
+ virtual const boost::type_info& value() const { return boost::type_id<value_type>(); }
PropertyMap& base() { return property_map_; }
const PropertyMap& base() const { return property_map_; }
@@ -283,7 +283,7 @@
{
for (dynamic_properties::iterator i = dp.lower_bound(name);
i != dp.end() && i->first == name; ++i) {
- if (i->second->key() == typeid(key)) {
+ if (i->second->key() == boost::type_id<Key>()) {
i->second->put(key, value);
return true;
}
@@ -305,7 +305,7 @@
{
for (dynamic_properties::const_iterator i = dp.lower_bound(name);
i != dp.end() && i->first == name; ++i) {
- if (i->second->key() == typeid(key))
+ if (i->second->key() == boost::type_id<Key>())
return any_cast<Value>(i->second->get(key));
}
@@ -318,7 +318,7 @@
{
for (dynamic_properties::const_iterator i = dp.lower_bound(name);
i != dp.end() && i->first == name; ++i) {
- if (i->second->key() == typeid(key))
+ if (i->second->key() == boost::type_id<Key>())
return any_cast<Value>(i->second->get(key));
}
@@ -331,7 +331,7 @@
{
for (dynamic_properties::const_iterator i = dp.lower_bound(name);
i != dp.end() && i->first == name; ++i) {
- if (i->second->key() == typeid(key))
+ if (i->second->key() == boost::type_id<Key>())
return i->second->get_string(key);
}

View File

@ -1,22 +0,0 @@
Index: .
===================================================================
--- . (revision 86520)
+++ . (working copy)
@@ -650,7 +650,7 @@
}
BOOST_PROPERTY_TREE_THROW(ptree_bad_data(
std::string("conversion of data to type \"") +
- typeid(Type).name() + "\" failed", data()));
+ boost::type_id<Type>().name_demangled() + "\" failed", data()));
}
template<class K, class D, class C>
@@ -805,7 +805,7 @@
data() = *o;
} else {
BOOST_PROPERTY_TREE_THROW(ptree_bad_data(
- std::string("conversion of type \"") + typeid(Type).name() +
+ std::string("conversion of type \"") + boost::type_id<Type>().name_demangled() +
"\" to data failed", boost::any()));
}
}

View File

@ -1,12 +0,0 @@
Index: .
===================================================================
--- . (revision 86532)
+++ . (working copy)
@@ -53,6 +53,7 @@
<toolset>clang:<cxxflags>-fno-exceptions
: variant_noexcept_test
]
+ [ run recursive_variant_test.cpp : : : <rtti>off : variant_nortti_test ]
[ run variant_swap_test.cpp ]
;

View File

@ -1,57 +0,0 @@
Index: .
===================================================================
--- . (revision 86532)
+++ . (working copy)
@@ -18,9 +18,7 @@
#include <cstddef> // for std::size_t
#include <new> // for placement new
-#if !defined(BOOST_NO_TYPEID)
-#include <typeinfo> // for typeid, std::type_info
-#endif // BOOST_NO_TYPEID
+#include "boost/type_index/type_info.hpp"
#include "boost/variant/detail/config.hpp"
#include "boost/mpl/aux_/value_wknd.hpp"
@@ -830,23 +828,19 @@
// Generic static visitor that performs a typeid on the value it visits.
//
-#if !defined(BOOST_NO_TYPEID)
-
class reflect
- : public static_visitor<const std::type_info&>
+ : public static_visitor<const boost::type_info&>
{
public: // visitor interfaces
template <typename T>
- const std::type_info& operator()(const T&) const BOOST_NOEXCEPT
+ const boost::type_info& operator()(const T&) const BOOST_NOEXCEPT
{
- return typeid(T);
+ return boost::type_id<T>();
}
};
-#endif // BOOST_NO_TYPEID
-
///////////////////////////////////////////////////////////////////////////////
// (detail) class comparer
//
@@ -2155,13 +2149,11 @@
return false;
}
-#if !defined(BOOST_NO_TYPEID)
- const std::type_info& type() const
+ const boost::type_info& type() const
{
detail::variant::reflect visitor;
return this->apply_visitor(visitor);
}
-#endif
public: // prevent comparison with foreign types

View File

@ -1,38 +0,0 @@
Index: .
===================================================================
--- . (revision 86520)
+++ . (working copy)
@@ -19,7 +19,7 @@
#endif
#include <stack>
#include <limits>
-#include <typeinfo>
+#include <boost/type_index/type_info.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/version.hpp>
@@ -144,7 +144,7 @@
explicit xpression_linker(Traits const &tr)
: back_stack_()
, traits_(&tr)
- , traits_type_(&typeid(Traits))
+ , traits_type_(&boost::type_id<Traits>())
, has_backrefs_(false)
{
}
@@ -310,13 +310,13 @@
template<typename Traits>
Traits const &get_traits() const
{
- BOOST_ASSERT(*this->traits_type_ == typeid(Traits));
+ BOOST_ASSERT(*this->traits_type_ == boost::type_id<Traits>());
return *static_cast<Traits const *>(this->traits_);
}
std::stack<void const *> back_stack_;
void const *traits_;
- std::type_info const *traits_type_;
+ boost::type_info const *traits_type_;
bool has_backrefs_;
};

View File

@ -1,33 +0,0 @@
Index: .
===================================================================
--- . (revision 86520)
+++ . (working copy)
@@ -25,9 +25,9 @@
#include <vector>
#include <utility>
#include <iterator>
-#include <typeinfo>
#include <algorithm>
#include <boost/config.hpp>
+#include <boost/type_index/type_info.hpp>
#include <boost/assert.hpp>
#include <boost/integer.hpp>
#include <boost/mpl/if.hpp>
@@ -72,7 +72,7 @@
//
struct type_info_less
{
- bool operator()(std::type_info const *left, std::type_info const *right) const
+ bool operator()(boost::type_info const *left, boost::type_info const *right) const
{
return 0 != left->before(*right);
}
@@ -679,7 +679,7 @@
typedef typename proto::result_of::value<right_type>::type arg_right_type;
BOOST_MPL_ASSERT((proto::matches<Arg, detail::ActionArgBinding>));
BOOST_MPL_ASSERT((is_same<typename arg_left_type::type, arg_right_type>));
- this->args_[&typeid(proto::value(proto::left(arg)))] = &proto::value(proto::right(arg));
+ this->args_[&boost::type_id<arg_left_type>()] = &proto::value(proto::right(arg));
return *this;
}

View File

@ -1,43 +0,0 @@
Index: .
===================================================================
--- . (revision 86520)
+++ . (working copy)
@@ -14,7 +14,7 @@
#endif
#include <string>
-#include <typeinfo>
+#include <boost/type_index/type_info.hpp>
#include <boost/assert.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/assert.hpp>
@@ -250,9 +250,9 @@
if(0 == this->traits_)
{
this->traits_ = &tr;
- this->traits_type_ = &typeid(Traits);
+ this->traits_type_ = &boost::type_id<Traits>();
}
- else if(*this->traits_type_ != typeid(Traits) || this->get_traits_<Traits>() != tr)
+ else if(*this->traits_type_ != boost::type_id<Traits>() || this->get_traits_<Traits>() != tr)
{
this->fail(); // traits mis-match! set all and bail
}
@@ -265,7 +265,7 @@
template<typename Traits>
Traits const &get_traits_() const
{
- BOOST_ASSERT(!!(*this->traits_type_ == typeid(Traits)));
+ BOOST_ASSERT(!!(*this->traits_type_ == boost::type_id<Traits>()));
return *static_cast<Traits const *>(this->traits_);
}
@@ -274,7 +274,7 @@
bool str_icase_;
bool line_start_;
void const *traits_;
- std::type_info const *traits_type_;
+ boost::type_info const *traits_type_;
int leading_simple_repeat_;
bool has_backrefs_;
};

81
test/Jamfile.v2 Normal file
View File

@ -0,0 +1,81 @@
# Copyright 2012-2022 Antony Polukhin
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#
import testing ;
import feature ;
import os ;
# Variable that contains all the stuff required for linking together <rtti>on and <rtti>off
compat = <define>BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY ;
# Making own `nortti` that is link compatible.
# We explicitly define BOOST_NO_RTTI because it sometimes can not be detected by build system.
nortti = <toolset>gcc:<cxxflags>"-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID" <toolset>clang:<cxxflags>"-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID" <toolset>intel:<cxxflags>"-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID" <toolset>darwin:<cxxflags>"-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID" <toolset>msvc:<cxxflags>"/GR-" ;
norttidefines = <toolset>gcc:<cxxflags>"-DBOOST_NO_RTTI -DBOOST_NO_TYPEID" <toolset>clang:<cxxflags>"-DBOOST_NO_RTTI -DBOOST_NO_TYPEID" <toolset>intel:<cxxflags>"-DBOOST_NO_RTTI -DBOOST_NO_TYPEID" <toolset>darwin:<cxxflags>"-DBOOST_NO_RTTI -DBOOST_NO_TYPEID" <toolset>msvc:<cxxflags>"-DBOOST_NO_RTTI" ;
# Making libraries that CANNOT work between rtti-on/rtti-off modules
obj test_lib_nortti-obj : test_lib.cpp : <link>shared <rtti>off $(norttidefines) ;
obj test_lib_anonymous_nortti-obj : test_lib_anonymous.cpp : <link>shared <rtti>off $(norttidefines) ;
lib test_lib_nortti : test_lib_nortti-obj : <link>shared <rtti>off $(norttidefines) ;
lib test_lib_anonymous_nortti : test_lib_anonymous_nortti-obj : <link>shared <rtti>off $(norttidefines) ;
obj test_lib_rtti-obj : test_lib.cpp : <link>shared ;
obj test_lib_anonymous_rtti-obj : test_lib_anonymous.cpp : <link>shared ;
lib test_lib_rtti : test_lib_rtti-obj : <link>shared ;
lib test_lib_anonymous_rtti : test_lib_anonymous_rtti-obj : <link>shared ;
# Making libraries that can work between rtti-on/rtti-off modules
obj test_lib_nortti_compat-obj : test_lib.cpp : <link>shared $(nortti) $(compat) ;
obj test_lib_rtti_compat-obj : test_lib.cpp : <link>shared $(nortti) $(compat) ;
lib test_lib_nortti_compat : test_lib_nortti_compat-obj : <link>shared $(nortti) $(compat) ;
lib test_lib_rtti_compat : test_lib_rtti_compat-obj : <link>shared $(nortti) $(compat) ;
exe testing_crossmodule_anonymous_no_rtti : testing_crossmodule_anonymous.cpp test_lib_anonymous_nortti : <rtti>off $(norttidefines) ;
test-suite type_index
:
[ run type_index_test.cpp ]
[ run type_index_runtime_cast_test.cpp ]
[ run type_index_constexpr_test.cpp ]
[ run type_index_test.cpp : : : <rtti>off $(norttidefines) : type_index_test_no_rtti ]
[ run ctti_print_name.cpp : : : <test-info>always_show_run_output ]
[ run testing_crossmodule.cpp test_lib_rtti ]
[ run testing_crossmodule.cpp test_lib_nortti : : : <rtti>off $(norttidefines) : testing_crossmodule_no_rtti ]
[ run testing_crossmodule_anonymous.cpp test_lib_anonymous_rtti : : : <test-info>always_show_run_output ]
[ run compare_ctti_stl.cpp ]
[ run track_13621.cpp ]
[ compile-fail type_index_test_ctti_copy_fail.cpp ]
[ compile-fail type_index_test_ctti_construct_fail.cpp ]
[ compile type_index_test_ctti_alignment.cpp ]
# Mixing RTTI on and off
# MSVC sometimes overrides the /GR-, without `detect_missmatch` this test may link.
# TODO: Disabled on MSVC. Enable again when there'll be an understanding of how to write this test correctly wor MSVC.
[ link-fail testing_crossmodule.cpp test_lib_rtti : $(nortti) <toolset>msvc:<build>no : link_fail_nortti_rtti ]
[ link-fail testing_crossmodule.cpp test_lib_nortti : <toolset>msvc:<build>no : link_fail_rtti_nortti ]
[ run testing_crossmodule.cpp test_lib_rtti_compat : : : $(nortti) $(compat) : testing_crossmodule_nortti_rtti_compat ]
[ run testing_crossmodule.cpp test_lib_nortti_compat : : : $(compat) : testing_crossmodule_rtti_nortti_compat ]
;
# Assuring that examples compile and run. Adding sources from `examples` directory to the `type_index` test suite.
for local p in [ glob ../examples/*.cpp ]
{
# RTTI on
type_index += [ run $(p) ] ;
# RTTI off
local target_name = $(p[1]:B)_no_rtti ;
if $(target_name) != "table_of_names_no_rtti"
{
type_index += [ run $(p) : : : <rtti>off $(norttidefines) : $(target_name) ] ;
}
}

90
test/appveyor.yml Normal file
View File

@ -0,0 +1,90 @@
# Use, modification, and distribution are
# subject to the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#
# Copyright 2016-2022 Antony Polukhin.
#
# See https://svn.boost.org/trac/boost/wiki/TravisCoverals for description of this file
# and how it can be used with Boost libraries.
#
# File revision #6
init:
# boost-local/libs/ folder to put this library into. This may be useful, if you're for example running Travis
# from `Boost.DLL` repo while Boost already has `dll` and with to replace `dll` with content of`Boost.DLL`.
#
# Otherwise just leave the default value - set BOOST_LIBS_FOLDER=%APPVEYOR_PROJECT_NAME%
- set BOOST_LIBS_FOLDER=%APPVEYOR_PROJECT_NAME%
###############################################################################################################
# From this point and below code is same for all the Boost libs
###############################################################################################################
version: 1.64.{build}-{branch}
# branches to build
branches:
except:
- gh-pages
skip_tags: true
environment:
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
TOOLSET: msvc-9.0,msvc-10.0,msvc-11.0,msvc-12.0
ADDRMD: 32
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
TOOLSET: msvc-14.1,clang-win
CXXSTD: 14,17
ADDRMD: 32,64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
ADDPATH: C:\cygwin\bin;
TOOLSET: gcc
CXXSTD: 03,11,14,1z
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
ADDPATH: C:\cygwin64\bin;
TOOLSET: gcc
CXXSTD: 03,11,14,1z
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
ADDPATH: C:\mingw\bin;
TOOLSET: gcc
CXXSTD: 03,11,14,1z
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
ADDPATH: C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin;
TOOLSET: gcc
CXXSTD: 03,11,14,1z
before_build:
- set BOOST_BRANCH=develop
- if "%APPVEYOR_REPO_BRANCH%" == "master" set BOOST_BRANCH=master
- echo "Testing %APPVEYOR_PROJECT_NAME%"
# Cloning Boost libraries (fast nondeep cloning)
- set BOOST=C:/boost-local
- git clone -b %BOOST_BRANCH% --depth 10 https://github.com/boostorg/boost.git %BOOST%
- cd %BOOST%
- git submodule update --init --depth 10 tools/build tools/boostdep libs/unordered # Boost.TypeIndex examples need Boost.Unordered
- rm -rf %BOOST%/libs/%BOOST_LIBS_FOLDER%
- mv -f %APPVEYOR_BUILD_FOLDER% %BOOST%/libs/%BOOST_LIBS_FOLDER%
- python tools/boostdep/depinst/depinst.py --git_args "--depth 10 --jobs 2" %BOOST_LIBS_FOLDER%
build_script:
- cmd /c bootstrap
- b2.exe headers
- cd %BOOST%/libs/%BOOST_LIBS_FOLDER%/test
after_build:
before_test:
test_script:
- PATH=%ADDPATH%%PATH%
- if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD%
- if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD%
- echo "Running command ..\..\..\b2 -j3 toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release"
- ..\..\..\b2.exe -j3 toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release cxxflags="-DBOOST_TRAVISCI_BUILD"
after_test:
on_success:
on_failure:
on_finish:

67
test/compare_ctti_stl.cpp Normal file
View File

@ -0,0 +1,67 @@
// Copyright Klemens Morgenstern, 2012-2015.
// Copyright 2019-2022 Antony Polukhin.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/type_index/ctti_type_index.hpp>
#include <boost/type_index/stl_type_index.hpp>
#include <boost/core/lightweight_test.hpp>
namespace my_namespace1 {
class my_class{};
}
namespace my_namespace2 {
class my_class{};
}
namespace my_namespace3
{
template<typename T, typename U>
struct my_template {};
}
#if !defined( BOOST_NO_RTTI )
template<typename T>
void compare()
{
typedef boost::typeindex::ctti_type_index ctti;
typedef boost::typeindex::stl_type_index stl;
BOOST_TEST_EQ(
ctti::type_id<int>().pretty_name(),
stl::type_id<int>().pretty_name()
);
}
int main()
{
compare<void>();
compare<int>();
compare<double*>();
compare<const double&>();
compare<my_namespace1::my_class>();
compare<my_namespace3::my_template<
my_namespace1::my_class,
my_namespace2::my_class> >();
return boost::report_errors();
}
#else
int main()
{
return 0;
}
#endif

44
test/ctti_print_name.cpp Normal file
View File

@ -0,0 +1,44 @@
//
// Copyright 2012-2022 Antony Polukhin.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <iostream>
// This cpp file:
// * tests BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING macro
// * outputs full ctti name so that TypeIndex library could be adjust to new compiler without requesting regression tester's help
#define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING (0,0,false,"")
#include <boost/type_index/ctti_type_index.hpp>
namespace user_defined_namespace {
class user_defined_class {};
}
class empty
{
};
int main()
{
using namespace boost::typeindex;
std::cout << "int: "
<< ctti_type_index::type_id<int>() << '\n';
std::cout << "double: "
<< ctti_type_index::type_id<double>() << '\n';
std::cout << "user_defined_namespace::user_defined_class: "
<< ctti_type_index::type_id<user_defined_namespace::user_defined_class>() << '\n';
std::cout << "empty:"
<< ctti_type_index::type_id<empty>() << '\n';
return 0;
}

40
test/test_lib.cpp Normal file
View File

@ -0,0 +1,40 @@
//
// Copyright 2012-2022 Antony Polukhin.
//
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#define TEST_LIB_SOURCE
#include "test_lib.hpp"
namespace user_defined_namespace {
class user_defined{};
}
namespace test_lib {
boost::typeindex::type_index get_integer() {
return boost::typeindex::type_id<int>();
}
boost::typeindex::type_index get_user_defined_class() {
return boost::typeindex::type_id<user_defined_namespace::user_defined>();
}
boost::typeindex::type_index get_const_integer() {
return boost::typeindex::type_id_with_cvr<const int>();
}
boost::typeindex::type_index get_const_user_defined_class() {
return boost::typeindex::type_id_with_cvr<const user_defined_namespace::user_defined>();
}
#if !defined(BOOST_HAS_PRAGMA_DETECT_MISMATCH) || !defined(_CPPRTTI)
// Just do nothing
void accept_typeindex(const boost::typeindex::type_index&) {}
#endif
}

View File

@ -1,5 +1,5 @@
//
// Copyright (c) Antony Polukhin, 2012-2013.
// Copyright 2012-2022 Antony Polukhin.
//
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
@ -25,14 +25,16 @@
namespace test_lib {
TEST_LIB_DECL boost::type_index get_integer();
TEST_LIB_DECL boost::type_index get_user_defined_class();
TEST_LIB_DECL boost::typeindex::type_index get_integer();
TEST_LIB_DECL boost::typeindex::type_index get_user_defined_class();
TEST_LIB_DECL boost::type_index get_const_integer();
TEST_LIB_DECL boost::type_index get_const_user_defined_class();
TEST_LIB_DECL boost::typeindex::type_index get_const_integer();
TEST_LIB_DECL boost::typeindex::type_index get_const_user_defined_class();
#if !defined(BOOST_HAS_PRAGMA_DETECT_MISMATCH) || !defined(_CPPRTTI)
// This is required for checking RTTI on/off linkage
TEST_LIB_DECL void accept_typeindex(const boost::type_index&);
TEST_LIB_DECL void accept_typeindex(const boost::typeindex::type_index&);
#endif
}

View File

@ -0,0 +1,27 @@
//
// Copyright 2012-2022 Antony Polukhin.
//
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#define TEST_LIB_SOURCE
#include "test_lib_anonymous.hpp"
namespace {
class user_defined{};
} // anonymous namespace
namespace test_lib {
boost::typeindex::type_index get_anonymous_user_defined_class() {
return boost::typeindex::type_id<user_defined>();
}
boost::typeindex::type_index get_const_anonymous_user_defined_class() {
return boost::typeindex::type_id_with_cvr<const user_defined>();
}
}

View File

@ -0,0 +1,34 @@
//
// Copyright 2012-2022 Antony Polukhin.
//
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_TYPE_INDEX_TESTS_TEST_LIB_ANONYMOUS_HPP
#define BOOST_TYPE_INDEX_TESTS_TEST_LIB_ANONYMOUS_HPP
// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/type_index.hpp>
// This is ALWAYS a dynamic library
#if defined(TEST_LIB_SOURCE)
# define TEST_LIB_DECL BOOST_SYMBOL_EXPORT
# else
# define TEST_LIB_DECL BOOST_SYMBOL_IMPORT
# endif
namespace test_lib {
TEST_LIB_DECL boost::typeindex::type_index get_anonymous_user_defined_class();
TEST_LIB_DECL boost::typeindex::type_index get_const_anonymous_user_defined_class();
}
#endif // BOOST_TYPE_INDEX_TESTS_TEST_LIB_ANONYMOUS_HPP

View File

@ -0,0 +1,57 @@
//
// Copyright 2012-2022 Antony Polukhin.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/type_index.hpp>
#include "test_lib.hpp"
#include <boost/core/lightweight_test.hpp>
namespace user_defined_namespace {
class user_defined{};
}
void comparing_types_between_modules()
{
boost::typeindex::type_index t_const_int = boost::typeindex::type_id_with_cvr<const int>();
boost::typeindex::type_index t_int = boost::typeindex::type_id<int>();
BOOST_TEST_EQ(t_int, test_lib::get_integer());
BOOST_TEST_EQ(t_const_int, test_lib::get_const_integer());
BOOST_TEST_NE(t_const_int, test_lib::get_integer());
BOOST_TEST_NE(t_int, test_lib::get_const_integer());
boost::typeindex::type_index t_const_userdef
= boost::typeindex::type_id_with_cvr<const user_defined_namespace::user_defined>();
boost::typeindex::type_index t_userdef
= boost::typeindex::type_id<user_defined_namespace::user_defined>();
BOOST_TEST_EQ(t_userdef, test_lib::get_user_defined_class());
BOOST_TEST_EQ(t_const_userdef, test_lib::get_const_user_defined_class());
BOOST_TEST_NE(t_const_userdef, test_lib::get_user_defined_class());
BOOST_TEST_NE(t_userdef, test_lib::get_const_user_defined_class());
BOOST_TEST_NE(t_userdef, test_lib::get_integer());
BOOST_TEST_NE(t_const_userdef, test_lib::get_integer());
BOOST_TEST_NE(t_int, test_lib::get_user_defined_class());
BOOST_TEST_NE(t_const_int, test_lib::get_const_user_defined_class());
// MSVC supports detect_missmatch pragma, but /GR- silently switch disable the link time check.
// /GR- undefies the _CPPRTTI macro. Using it to detect working detect_missmatch pragma.
#if !defined(BOOST_HAS_PRAGMA_DETECT_MISMATCH) || !defined(_CPPRTTI)
test_lib::accept_typeindex(t_int);
#endif
}
int main() {
comparing_types_between_modules();
return boost::report_errors();
}

View File

@ -0,0 +1,48 @@
//
// Copyright 2012-2022 Antony Polukhin.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/core/lightweight_test.hpp>
#include <boost/type_index.hpp>
#include "test_lib_anonymous.hpp"
#include <iostream>
#define BOOST_CHECK_NE(x, y) BOOST_CHECK(x != y)
namespace {
class user_defined{};
}
void comparing_anonymous_types_between_modules()
{
boost::typeindex::type_index t_const_userdef = boost::typeindex::type_id_with_cvr<const user_defined>();
boost::typeindex::type_index t_userdef = boost::typeindex::type_id<user_defined>();
// Known to fail on Clang and old versions of GCC.
//BOOST_TEST_NE(t_userdef, test_lib::get_anonymous_user_defined_class());
//BOOST_TEST_NE(t_const_userdef, test_lib::get_const_anonymous_user_defined_class());
std::cout
<< "t_userdef == " << t_userdef
<< ", test_lib::get_anonymous_user_defined_class() == " << test_lib::get_anonymous_user_defined_class()
<< '\n';
std::cout
<< "t_const_userdef == " << t_const_userdef
<< ", test_lib::get_const_anonymous_user_defined_class() == " << test_lib::get_const_anonymous_user_defined_class()
<< '\n';
BOOST_TEST_NE(t_const_userdef, test_lib::get_anonymous_user_defined_class());
BOOST_TEST_NE(t_userdef, test_lib::get_const_anonymous_user_defined_class());
}
int main() {
comparing_anonymous_types_between_modules();
return boost::report_errors();
}

23
test/track_13621.cpp Normal file
View File

@ -0,0 +1,23 @@
//
// Copyright 2018-2022 Antony Polukhin.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/type_index/ctti_type_index.hpp>
#include <string>
#include <boost/core/lightweight_test.hpp>
class empty
{
};
int main()
{
std::string name = boost::typeindex::ctti_type_index::type_id<empty>().pretty_name();
BOOST_TEST(name.find("empty") != std::string::npos);
return boost::report_errors();
}

View File

@ -0,0 +1,157 @@
//
// Copyright 2015-2022 Antony Polukhin.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/type_index/ctti_type_index.hpp>
#include <algorithm>
#include <string>
#include <boost/core/lightweight_test.hpp>
const char* hello1 = "Hello word";
const char* hello1_end = hello1 + sizeof("Hello word");
const char* hello2 = "Hello word, pal!";
const char* hello2_end = hello2 + sizeof("Hello word, pal!");
void strcmp_same() {
using boost::typeindex::detail::constexpr_strcmp;
BOOST_TEST(
constexpr_strcmp(hello1, hello1) == 0
);
BOOST_TEST(
constexpr_strcmp(hello2, hello2) == 0
);
BOOST_TEST(
constexpr_strcmp(hello1, hello2) != 0
);
BOOST_TEST(
constexpr_strcmp(hello2, hello1) != 0
);
BOOST_TEST(
(constexpr_strcmp(hello2, hello1) < 0)
==
(std::strcmp(hello2, hello1) < 0)
);
BOOST_TEST(
(constexpr_strcmp(hello1, hello2) < 0)
==
(std::strcmp(hello1, hello2) < 0)
);
}
void search_same() {
using boost::typeindex::detail::constexpr_search;
BOOST_TEST(
constexpr_search(hello1, hello1_end, hello2, hello2_end) == std::search(hello1, hello1_end, hello2, hello2_end)
);
BOOST_TEST(
constexpr_search(hello2, hello2_end, hello1, hello1_end) == std::search(hello2, hello2_end, hello1, hello1_end)
);
const char* word = "word";
const char* word_end = word + sizeof("word") - 1;
BOOST_TEST(
constexpr_search(hello1, hello1_end, word, word_end) == std::search(hello1, hello1_end, word, word_end)
);
BOOST_TEST(
constexpr_search(hello2, hello2_end, word, word_end) == std::search(hello2, hello2_end, word, word_end)
);
}
template <class T, std::size_t N>
BOOST_CXX14_CONSTEXPR bool in_namespace(const char (&ns)[N]) BOOST_NOEXCEPT {
BOOST_CXX14_CONSTEXPR const char* name = boost::typeindex::ctti_type_index::type_id<T>().raw_name();
for (std::size_t i = 0; i < N - 1; ++i)
if (name[i] != ns[i])
return false;
return true;
}
template <class T>
BOOST_CXX14_CONSTEXPR bool is_boost_namespace() BOOST_NOEXCEPT {
return in_namespace<T>("boost::") || in_namespace<T>("class boost::") || in_namespace<T>("struct boost::");
}
void constexpr_test() {
using namespace boost::typeindex;
BOOST_CXX14_CONSTEXPR ctti_type_index t_int0 = ctti_type_index::type_id<int>();
(void)t_int0;
BOOST_CXX14_CONSTEXPR ctti_type_index t_short0 = ctti_type_index::type_id<short>();
(void)t_short0;
BOOST_CXX14_CONSTEXPR ctti_type_index t_int1 = ctti_type_index::type_id<int>();
(void)t_int1;
BOOST_CXX14_CONSTEXPR ctti_type_index t_short1 = ctti_type_index::type_id<short>();
(void)t_short1;
// Following tests are known to fail on _MSC_VER == 1916.
#if !defined(_MSC_VER) || _MSC_VER > 1916
BOOST_CXX14_CONSTEXPR bool same0 = (t_int0 == t_int1);
BOOST_TEST(same0);
BOOST_CXX14_CONSTEXPR bool same1 = (t_short1 == t_short0);
BOOST_TEST(same1);
BOOST_CXX14_CONSTEXPR bool same2 = (t_int1 == t_int1);
BOOST_TEST(same2);
BOOST_CXX14_CONSTEXPR bool same3 = (t_short0 == t_short0);
BOOST_TEST(same3);
BOOST_CXX14_CONSTEXPR bool same4 = !(t_short0 < t_short0 || t_short0 > t_short0);
BOOST_TEST(same4);
BOOST_CXX14_CONSTEXPR bool same5 = (t_short0 <= t_short0 && t_short0 >= t_short0);
BOOST_TEST(same5);
BOOST_CXX14_CONSTEXPR bool not_same0 = (t_int0 != t_short1);
BOOST_TEST(not_same0);
BOOST_CXX14_CONSTEXPR bool not_same1 = (t_int1 != t_short0);
BOOST_TEST(not_same1);
BOOST_CXX14_CONSTEXPR bool not_same2 = (t_int1 < t_short0 || t_int1 > t_short0);
BOOST_TEST(not_same2);
BOOST_CXX14_CONSTEXPR const char* int_name = t_int0.name();
BOOST_TEST(*int_name != '\0');
BOOST_CXX14_CONSTEXPR const char* short_name = t_short0.name();
BOOST_TEST(*short_name != '\0');
BOOST_CXX14_CONSTEXPR bool in_namespace = is_boost_namespace<ctti_type_index>();
BOOST_TEST(in_namespace);
BOOST_CXX14_CONSTEXPR bool not_in_namespace = !is_boost_namespace<std::string>();
BOOST_TEST(not_in_namespace);
#endif // #if !defined(_MSC_VER) || _MSC_VER > 1916
}
int main() {
strcmp_same();
search_same();
constexpr_test();
return boost::report_errors();
}

View File

@ -0,0 +1,296 @@
//
// Copyright Chris Glover, 2016.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// #include <boost/type_index/runtime_cast.hpp>
// #include <boost/type_index/runtime_reference_cast.hpp>
#include <boost/type_index/runtime_cast.hpp>
#include <boost/type_index/runtime_cast/boost_shared_ptr_cast.hpp>
#include <boost/smart_ptr/make_shared.hpp>
#include <boost/core/lightweight_test.hpp>
#if !defined(BOOST_NO_CXX11_SMART_PTR)
# include <boost/type_index/runtime_cast/std_shared_ptr_cast.hpp>
#endif
// Classes include a member variable "name" with the
// name of the class hard coded so we can be sure that
// the pointer offsets are all working, since we're doing
// a cast from void* at some point.
#define IMPLEMENT_CLASS(type_name) \
type_name() : name( #type_name ) {} \
std::string name;
struct base {
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(BOOST_TYPE_INDEX_NO_BASE_CLASS)
IMPLEMENT_CLASS(base)
};
struct single_derived : base {
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST((base))
IMPLEMENT_CLASS(single_derived)
};
struct base1 {
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(BOOST_TYPE_INDEX_NO_BASE_CLASS)
IMPLEMENT_CLASS(base1)
};
struct base2 {
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(BOOST_TYPE_INDEX_NO_BASE_CLASS)
IMPLEMENT_CLASS(base2)
};
struct multiple_derived : base1, base2 {
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST((base1)(base2))
IMPLEMENT_CLASS(multiple_derived)
};
struct baseV1 : virtual base {
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST((base))
IMPLEMENT_CLASS(baseV1)
};
struct baseV2 : virtual base {
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST((base))
IMPLEMENT_CLASS(baseV2)
};
struct multiple_virtual_derived : baseV1, baseV2 {
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST((baseV1)(baseV2))
IMPLEMENT_CLASS(multiple_virtual_derived)
};
struct unrelated {
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(BOOST_TYPE_INDEX_NO_BASE_CLASS)
IMPLEMENT_CLASS(unrelated)
};
struct unrelated_with_base : base {
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST((base))
IMPLEMENT_CLASS(unrelated_with_base)
};
struct unrelatedV1 : virtual base {
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST((base))
IMPLEMENT_CLASS(unrelatedV1)
};
struct level1_a : base {
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST((base))
IMPLEMENT_CLASS(level1_a)
};
struct level1_b : base {
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST((base))
IMPLEMENT_CLASS(level1_b)
};
struct level2 : level1_a, level1_b {
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST((level1_a)(level1_b))
IMPLEMENT_CLASS(level2)
};
struct reg_base {
BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(BOOST_TYPE_INDEX_NO_BASE_CLASS)
};
struct reg_derived : reg_base {
BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS((reg_base))
};
void no_base()
{
using namespace boost::typeindex;
base b;
base* b2 = runtime_pointer_cast<base>(&b);
BOOST_TEST_NE(b2, (base*)NULL);
BOOST_TEST_EQ(b2->name, "base");
BOOST_TEST_EQ(runtime_pointer_cast<unrelated>(&b), (unrelated*)NULL);
BOOST_TEST_EQ(runtime_pointer_cast<single_derived>(&b), (single_derived*)NULL);
BOOST_TEST_EQ(runtime_pointer_cast<unrelatedV1>(&b), (unrelatedV1*)NULL);
BOOST_TEST_EQ(runtime_pointer_cast<unrelated_with_base>(&b), (unrelated_with_base*)NULL);
}
void single_base()
{
using namespace boost::typeindex;
single_derived d;
base* b = &d;
single_derived* d2 = runtime_pointer_cast<single_derived>(b);
BOOST_TEST_NE(d2, (single_derived*)NULL);
BOOST_TEST_EQ(d2->name, "single_derived");
BOOST_TEST_EQ(runtime_pointer_cast<unrelated>(&d), (unrelated*)NULL);
BOOST_TEST_EQ(runtime_pointer_cast<unrelated>(b), (unrelated*)NULL);
BOOST_TEST_EQ(runtime_pointer_cast<unrelated_with_base>(b), (unrelated_with_base*)NULL);
}
void multiple_base()
{
using namespace boost::typeindex;
multiple_derived d;
base1* b1 = &d;
multiple_derived* d2 = runtime_pointer_cast<multiple_derived>(b1);
BOOST_TEST_NE(d2, (multiple_derived*)NULL);
BOOST_TEST_EQ(d2->name, "multiple_derived");
base2* b2 = runtime_pointer_cast<base2>(b1);
BOOST_TEST_NE(b2, (base2*)NULL);
BOOST_TEST_EQ(b2->name, "base2");
BOOST_TEST_EQ(runtime_pointer_cast<unrelated>(&d), (unrelated*)NULL);
BOOST_TEST_EQ(runtime_pointer_cast<unrelated>(b1), (unrelated*)NULL);
BOOST_TEST_EQ(runtime_pointer_cast<unrelated_with_base>(b1), (unrelated_with_base*)NULL);
}
void virtual_base()
{
using namespace boost::typeindex;
multiple_virtual_derived d;
base* b = &d;
multiple_virtual_derived* d2 = runtime_pointer_cast<multiple_virtual_derived>(b);
baseV1* bv1 = runtime_pointer_cast<baseV1>(b);
baseV2* bv2 = runtime_pointer_cast<baseV2>(b);
BOOST_TEST_NE(d2, (multiple_virtual_derived*)NULL);
BOOST_TEST_EQ(d2->name, "multiple_virtual_derived");
BOOST_TEST_NE(bv1, (baseV1*)NULL);
BOOST_TEST_EQ(bv1->name, "baseV1");
BOOST_TEST_NE(bv2, (baseV2*)NULL);
BOOST_TEST_EQ(bv2->name, "baseV2");
BOOST_TEST_EQ(runtime_pointer_cast<unrelated>(b), (unrelated*)NULL);
BOOST_TEST_EQ(runtime_pointer_cast<unrelated>(&d), (unrelated*)NULL);
BOOST_TEST_EQ(runtime_pointer_cast<unrelated_with_base>(b), (unrelated_with_base*)NULL);
}
void pointer_interface()
{
using namespace boost::typeindex;
single_derived d;
base* b = &d;
single_derived* d2 = runtime_cast<single_derived*>(b);
BOOST_TEST_NE(d2, (single_derived*)NULL);
BOOST_TEST_EQ(d2->name, "single_derived");
BOOST_TEST_EQ(runtime_pointer_cast<unrelated>(b), (unrelated*)NULL);
}
void reference_interface()
{
using namespace boost::typeindex;
single_derived d;
base& b = d;
single_derived& d2 = runtime_cast<single_derived&>(b);
BOOST_TEST_EQ(d2.name, "single_derived");
try {
unrelated& u = runtime_cast<unrelated&>(b);
(void)u;
BOOST_TEST(!"should throw bad_runtime_cast");
}
catch(boost::typeindex::bad_runtime_cast&) {
}
catch(...) {
BOOST_TEST(!"should throw bad_runtime_cast");
}
}
void const_pointer_interface()
{
using namespace boost::typeindex;
const single_derived d;
base const* b = &d;
single_derived const* d2 = runtime_cast<single_derived const*>(b);
BOOST_TEST_NE(d2, (single_derived*)NULL);
BOOST_TEST_EQ(d2->name, "single_derived");
BOOST_TEST_EQ(runtime_pointer_cast<unrelated>(b), (unrelated*)NULL);
}
void const_reference_interface()
{
using namespace boost::typeindex;
const single_derived d;
base const& b = d;
single_derived const& d2 = runtime_cast<single_derived const&>(b);
BOOST_TEST_EQ(d2.name, "single_derived");
try {
unrelated const& u = runtime_cast<unrelated const&>(b);
(void)u;
BOOST_TEST(!"should throw bad_runtime_cast");
}
catch(boost::typeindex::bad_runtime_cast&) {
}
catch(...) {
BOOST_TEST(!"should throw bad_runtime_cast");
}
}
void diamond_non_virtual()
{
using namespace boost::typeindex;
level2 inst;
level1_a* l1a = &inst;
base* b1 = l1a;
level1_b* l1_b = runtime_cast<level1_b*>(b1);
BOOST_TEST_NE(l1_b, (level1_b*)NULL);
BOOST_TEST_EQ(l1_b->name, "level1_b");
}
void boost_shared_ptr()
{
using namespace boost::typeindex;
boost::shared_ptr<single_derived> d = boost::make_shared<single_derived>();
boost::shared_ptr<base> b = d;
boost::shared_ptr<single_derived> d2 = runtime_pointer_cast<single_derived>(b);
BOOST_TEST_NE(d2, boost::shared_ptr<single_derived>());
BOOST_TEST_EQ(d2->name, "single_derived");
}
void std_shared_ptr()
{
#if !defined(BOOST_NO_CXX11_SMART_PTR)
using namespace boost::typeindex;
std::shared_ptr<single_derived> d = std::make_shared<single_derived>();
std::shared_ptr<base> b = d;
std::shared_ptr<single_derived> d2 = runtime_pointer_cast<single_derived>(b);
BOOST_TEST_NE(d2, std::shared_ptr<single_derived>());
BOOST_TEST_EQ(d2->name, "single_derived");
#endif
}
void register_runtime_class()
{
using namespace boost::typeindex;
reg_derived rd;
reg_base* rb = &rd;
reg_derived* prd = runtime_pointer_cast<reg_derived>(rb);
BOOST_TEST_NE(prd, (reg_derived*)NULL);
BOOST_TEST_EQ(type_id_runtime(*prd), type_id<reg_derived>());
}
int main() {
no_base();
single_derived();
multiple_base();
virtual_base();
pointer_interface();
reference_interface();
const_pointer_interface();
const_reference_interface();
diamond_non_virtual();
boost_shared_ptr();
std_shared_ptr();
register_runtime_class();
return boost::report_errors();
}

400
test/type_index_test.cpp Normal file
View File

@ -0,0 +1,400 @@
//
// Copyright 2012-2022 Antony Polukhin.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/type_index.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/core/lightweight_test.hpp>
namespace my_namespace1 {
class my_class{};
}
namespace my_namespace2 {
class my_class{};
}
void names_matches_type_id()
{
using namespace boost::typeindex;
BOOST_TEST_EQ(type_id<int>().pretty_name(), "int");
BOOST_TEST_EQ(type_id<double>().pretty_name(), "double");
BOOST_TEST_EQ(type_id<int>().name(), type_id<int>().name());
BOOST_TEST_NE(type_id<int>().name(), type_id<double>().name());
BOOST_TEST_NE(type_id<double>().name(), type_id<int>().name());
BOOST_TEST_EQ(type_id<double>().name(), type_id<double>().name());
}
void default_construction()
{
using namespace boost::typeindex;
type_index ti1, ti2;
BOOST_TEST_EQ(ti1, ti2);
BOOST_TEST_EQ(type_id<void>(), ti1);
BOOST_TEST_EQ(type_id<void>().name(), ti1.name());
BOOST_TEST_NE(type_id<int>(), ti1);
}
void copy_construction()
{
using namespace boost::typeindex;
type_index ti1, ti2 = type_id<int>();
BOOST_TEST_NE(ti1, ti2);
ti1 = ti2;
BOOST_TEST_EQ(ti2, ti1);
const type_index ti3(ti1);
BOOST_TEST_EQ(ti3, ti1);
}
void comparators_type_id()
{
using namespace boost::typeindex;
type_index t_int = type_id<int>();
type_index t_double = type_id<double>();
BOOST_TEST_EQ(t_int, t_int);
BOOST_TEST_LE(t_int, t_int);
BOOST_TEST_GE(t_int, t_int);
BOOST_TEST_NE(t_int, t_double);
BOOST_TEST_LE(t_double, t_double);
BOOST_TEST_GE(t_double, t_double);
BOOST_TEST_NE(t_double, t_int);
BOOST_TEST(t_double < t_int || t_int < t_double);
BOOST_TEST(t_double > t_int || t_int > t_double);
}
void hash_code_type_id()
{
using namespace boost::typeindex;
std::size_t t_int1 = type_id<int>().hash_code();
std::size_t t_double1 = type_id<double>().hash_code();
std::size_t t_int2 = type_id<int>().hash_code();
std::size_t t_double2 = type_id<double>().hash_code();
BOOST_TEST_EQ(t_int1, t_int2);
BOOST_TEST_NE(t_int1, t_double2);
BOOST_TEST_LE(t_double1, t_double2);
}
template <class T1, class T2>
static void test_with_modofiers() {
using namespace boost::typeindex;
type_index t1 = type_id_with_cvr<T1>();
type_index t2 = type_id_with_cvr<T2>();
BOOST_TEST_NE(t2, t1);
BOOST_TEST(t2 != t1.type_info());
BOOST_TEST(t2.type_info() != t1);
BOOST_TEST(t1 < t2 || t2 < t1);
BOOST_TEST(t1 > t2 || t2 > t1);
BOOST_TEST(t1.type_info() < t2 || t2.type_info() < t1);
BOOST_TEST(t1.type_info() > t2 || t2.type_info() > t1);
BOOST_TEST(t1 < t2.type_info() || t2 < t1.type_info());
BOOST_TEST(t1 > t2.type_info() || t2 > t1.type_info());
// Chaecking that comparison operators overloads compile
BOOST_TEST(t1 <= t2 || t2 <= t1);
BOOST_TEST(t1 >= t2 || t2 >= t1);
BOOST_TEST(t1.type_info() <= t2 || t2.type_info() <= t1);
BOOST_TEST(t1.type_info() >= t2 || t2.type_info() >= t1);
BOOST_TEST(t1 <= t2.type_info() || t2 <= t1.type_info());
BOOST_TEST(t1 >= t2.type_info() || t2 >= t1.type_info());
BOOST_TEST_EQ(t1, type_id_with_cvr<T1>());
BOOST_TEST_EQ(t2, type_id_with_cvr<T2>());
BOOST_TEST(t1 == type_id_with_cvr<T1>().type_info());
BOOST_TEST(t2 == type_id_with_cvr<T2>().type_info());
BOOST_TEST(t1.type_info() == type_id_with_cvr<T1>());
BOOST_TEST(t2.type_info() == type_id_with_cvr<T2>());
BOOST_TEST_EQ(t1.hash_code(), type_id_with_cvr<T1>().hash_code());
BOOST_TEST_EQ(t2.hash_code(), type_id_with_cvr<T2>().hash_code());
BOOST_TEST_NE(t1.hash_code(), type_id_with_cvr<T2>().hash_code());
BOOST_TEST_NE(t2.hash_code(), type_id_with_cvr<T1>().hash_code());
}
void type_id_storing_modifiers()
{
test_with_modofiers<int, const int>();
test_with_modofiers<int, const int&>();
test_with_modofiers<int, int&>();
test_with_modofiers<int, volatile int>();
test_with_modofiers<int, volatile int&>();
test_with_modofiers<int, const volatile int>();
test_with_modofiers<int, const volatile int&>();
test_with_modofiers<const int, int>();
test_with_modofiers<const int, const int&>();
test_with_modofiers<const int, int&>();
test_with_modofiers<const int, volatile int>();
test_with_modofiers<const int, volatile int&>();
test_with_modofiers<const int, const volatile int>();
test_with_modofiers<const int, const volatile int&>();
test_with_modofiers<const int&, int>();
test_with_modofiers<const int&, const int>();
test_with_modofiers<const int&, int&>();
test_with_modofiers<const int&, volatile int>();
test_with_modofiers<const int&, volatile int&>();
test_with_modofiers<const int&, const volatile int>();
test_with_modofiers<const int&, const volatile int&>();
test_with_modofiers<int&, const int>();
test_with_modofiers<int&, const int&>();
test_with_modofiers<int&, int>();
test_with_modofiers<int&, volatile int>();
test_with_modofiers<int&, volatile int&>();
test_with_modofiers<int&, const volatile int>();
test_with_modofiers<int&, const volatile int&>();
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
test_with_modofiers<int&&, const int>();
test_with_modofiers<int&&, const int&>();
test_with_modofiers<int&&, const int&&>();
test_with_modofiers<int&&, int>();
test_with_modofiers<int&&, volatile int>();
test_with_modofiers<int&&, volatile int&>();
test_with_modofiers<int&&, volatile int&&>();
test_with_modofiers<int&&, const volatile int>();
test_with_modofiers<int&&, const volatile int&>();
test_with_modofiers<int&&, const volatile int&&>();
#endif
}
template <class T>
static void test_storing_nonstoring_modifiers_templ() {
using namespace boost::typeindex;
type_index t1 = type_id_with_cvr<T>();
type_index t2 = type_id<T>();
BOOST_TEST_EQ(t2, t1);
BOOST_TEST_EQ(t1, t2);
BOOST_TEST(t1 <= t2);
BOOST_TEST(t1 >= t2);
BOOST_TEST(t2 <= t1);
BOOST_TEST(t2 >= t1);
BOOST_TEST_EQ(t2.pretty_name(), t1.pretty_name());
}
void type_id_storing_modifiers_vs_nonstoring()
{
test_storing_nonstoring_modifiers_templ<int>();
test_storing_nonstoring_modifiers_templ<my_namespace1::my_class>();
test_storing_nonstoring_modifiers_templ<my_namespace2::my_class>();
boost::typeindex::type_index t1 = boost::typeindex::type_id_with_cvr<const int>();
boost::typeindex::type_index t2 = boost::typeindex::type_id<int>();
BOOST_TEST_NE(t2, t1);
BOOST_TEST(t1.pretty_name() == "const int" || t1.pretty_name() == "int const");
}
void type_index_stream_operator_via_lexical_cast_testing()
{
using namespace boost::typeindex;
std::string s_int2 = boost::lexical_cast<std::string>(type_id<int>());
BOOST_TEST_EQ(s_int2, "int");
std::string s_double2 = boost::lexical_cast<std::string>(type_id<double>());
BOOST_TEST_EQ(s_double2, "double");
}
void type_index_stripping_cvr_test()
{
using namespace boost::typeindex;
BOOST_TEST_EQ(type_id<int>(), type_id<const int>());
BOOST_TEST_EQ(type_id<int>(), type_id<const volatile int>());
BOOST_TEST_EQ(type_id<int>(), type_id<const volatile int&>());
BOOST_TEST_EQ(type_id<int>(), type_id<int&>());
BOOST_TEST_EQ(type_id<int>(), type_id<volatile int>());
BOOST_TEST_EQ(type_id<int>(), type_id<volatile int&>());
BOOST_TEST_EQ(type_id<double>(), type_id<const double>());
BOOST_TEST_EQ(type_id<double>(), type_id<const volatile double>());
BOOST_TEST_EQ(type_id<double>(), type_id<const volatile double&>());
BOOST_TEST_EQ(type_id<double>(), type_id<double&>());
BOOST_TEST_EQ(type_id<double>(), type_id<volatile double>());
BOOST_TEST_EQ(type_id<double>(), type_id<volatile double&>());
}
void type_index_user_defined_class_test()
{
using namespace boost::typeindex;
BOOST_TEST_EQ(type_id<my_namespace1::my_class>(), type_id<my_namespace1::my_class>());
BOOST_TEST_EQ(type_id<my_namespace2::my_class>(), type_id<my_namespace2::my_class>());
#ifndef BOOST_NO_RTTI
BOOST_TEST(type_id<my_namespace1::my_class>() == typeid(my_namespace1::my_class));
BOOST_TEST(type_id<my_namespace2::my_class>() == typeid(my_namespace2::my_class));
BOOST_TEST(typeid(my_namespace1::my_class) == type_id<my_namespace1::my_class>());
BOOST_TEST(typeid(my_namespace2::my_class) == type_id<my_namespace2::my_class>());
#endif
BOOST_TEST_NE(type_id<my_namespace1::my_class>(), type_id<my_namespace2::my_class>());
BOOST_TEST_NE(
type_id<my_namespace1::my_class>().pretty_name().find("my_namespace1::my_class"),
std::string::npos);
}
struct A {
public:
BOOST_TYPE_INDEX_REGISTER_CLASS
virtual ~A(){}
};
struct B: public A {
BOOST_TYPE_INDEX_REGISTER_CLASS
};
struct C: public B {
BOOST_TYPE_INDEX_REGISTER_CLASS
};
void comparators_type_id_runtime()
{
C c1;
B b1;
A* pc1 = &c1;
A& rc1 = c1;
A* pb1 = &b1;
A& rb1 = b1;
#ifndef BOOST_NO_RTTI
BOOST_TEST(typeid(rc1) == typeid(*pc1));
BOOST_TEST(typeid(rb1) == typeid(*pb1));
BOOST_TEST(typeid(rc1) != typeid(*pb1));
BOOST_TEST(typeid(rb1) != typeid(*pc1));
BOOST_TEST(typeid(&rc1) == typeid(pb1));
BOOST_TEST(typeid(&rb1) == typeid(pc1));
#else
BOOST_TEST(boost::typeindex::type_index(pc1->boost_type_index_type_id_runtime_()).raw_name());
#endif
BOOST_TEST_EQ(boost::typeindex::type_id_runtime(rc1), boost::typeindex::type_id_runtime(*pc1));
BOOST_TEST_EQ(boost::typeindex::type_id<C>(), boost::typeindex::type_id_runtime(*pc1));
BOOST_TEST_EQ(boost::typeindex::type_id_runtime(rb1), boost::typeindex::type_id_runtime(*pb1));
BOOST_TEST_EQ(boost::typeindex::type_id<B>(), boost::typeindex::type_id_runtime(*pb1));
BOOST_TEST_NE(boost::typeindex::type_id_runtime(rc1), boost::typeindex::type_id_runtime(*pb1));
BOOST_TEST_NE(boost::typeindex::type_id_runtime(rb1), boost::typeindex::type_id_runtime(*pc1));
#ifndef BOOST_NO_RTTI
BOOST_TEST_EQ(boost::typeindex::type_id_runtime(&rc1), boost::typeindex::type_id_runtime(pb1));
BOOST_TEST_EQ(boost::typeindex::type_id_runtime(&rb1), boost::typeindex::type_id_runtime(pc1));
BOOST_TEST(boost::typeindex::type_id_runtime(rc1) == typeid(*pc1));
BOOST_TEST(boost::typeindex::type_id_runtime(rb1) == typeid(*pb1));
BOOST_TEST(boost::typeindex::type_id_runtime(rc1) != typeid(*pb1));
BOOST_TEST(boost::typeindex::type_id_runtime(rb1) != typeid(*pc1));
BOOST_TEST(boost::typeindex::type_id_runtime(&rc1) == typeid(pb1));
BOOST_TEST(boost::typeindex::type_id_runtime(&rb1) == typeid(pc1));
#endif
}
#ifndef BOOST_NO_RTTI
void comparators_type_id_vs_type_info()
{
using namespace boost::typeindex;
type_index t_int = type_id<int>();
BOOST_TEST(t_int == typeid(int));
BOOST_TEST(typeid(int) == t_int);
BOOST_TEST(t_int <= typeid(int));
BOOST_TEST(typeid(int) <= t_int);
BOOST_TEST(t_int >= typeid(int));
BOOST_TEST(typeid(int) >= t_int);
type_index t_double = type_id<double>();
BOOST_TEST(t_double == typeid(double));
BOOST_TEST(typeid(double) == t_double);
BOOST_TEST(t_double <= typeid(double));
BOOST_TEST(typeid(double) <= t_double);
BOOST_TEST(t_double >= typeid(double));
BOOST_TEST(typeid(double) >= t_double);
if (t_double < t_int) {
BOOST_TEST(t_double < typeid(int));
BOOST_TEST(typeid(double) < t_int);
BOOST_TEST(typeid(int) > t_double);
BOOST_TEST(t_int > typeid(double));
BOOST_TEST(t_double <= typeid(int));
BOOST_TEST(typeid(double) <= t_int);
BOOST_TEST(typeid(int) >= t_double);
BOOST_TEST(t_int >= typeid(double));
} else {
BOOST_TEST(t_double > typeid(int));
BOOST_TEST(typeid(double) > t_int);
BOOST_TEST(typeid(int) < t_double);
BOOST_TEST(t_int < typeid(double));
BOOST_TEST(t_double >= typeid(int));
BOOST_TEST(typeid(double) >= t_int);
BOOST_TEST(typeid(int) <= t_double);
BOOST_TEST(t_int <= typeid(double));
}
}
#endif // BOOST_NO_RTTI
int main() {
names_matches_type_id();
default_construction();
copy_construction();
comparators_type_id();
hash_code_type_id();
type_id_storing_modifiers();
type_id_storing_modifiers_vs_nonstoring();
type_index_stream_operator_via_lexical_cast_testing();
type_index_stripping_cvr_test();
type_index_user_defined_class_test();
comparators_type_id_runtime();
#ifndef BOOST_NO_RTTI
comparators_type_id_vs_type_info();
#endif
return boost::report_errors();
}

View File

@ -0,0 +1,18 @@
//
// Copyright 2012-2022 Antony Polukhin.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/type_index/ctti_type_index.hpp>
#include <boost/type_traits/alignment_of.hpp>
int main() {
BOOST_STATIC_ASSERT_MSG(
boost::alignment_of<boost::typeindex::detail::ctti_data>::value == boost::alignment_of<char>::value,
"Alignments of boost::typeindex::detail::ctti_data and char differ. "
"It is unsafe to reinterpret_cast between them."
);
}

View File

@ -0,0 +1,15 @@
//
// Copyright 2012-2022 Antony Polukhin.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/type_index/ctti_type_index.hpp>
int main() {
using namespace boost::typeindex;
ctti_type_index::type_info_t t;
(void)t;
}

View File

@ -0,0 +1,15 @@
//
// Copyright 2012-2022 Antony Polukhin.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/type_index/ctti_type_index.hpp>
int main() {
using namespace boost::typeindex;
ctti_type_index::type_info_t t = ctti_type_index::type_id<int>().type_info();
(void)t;
}