Compare commits

..

285 Commits

Author SHA1 Message Date
Antony Polukhin
29ab3258a7 do not run tests on old MSVC in appveyor 2023-08-25 14:06:21 +03:00
Antony Polukhin
4a04bb5f46 update meta 2023-08-25 12:49:14 +03:00
Antony Polukhin
34e6c165da run tests on more compilers 2023-08-25 11:59:54 +03:00
Antony Polukhin
034d105a48 Remove hard error about C++11 requirement (fixes #38) 2023-08-25 11:41:48 +03:00
Mohammad Nejati
62a3c9e89f Use relative URL for redirect in index.html (#37) 2023-08-12 11:03:19 +03:00
Antony Polukhin
b9815d397b Drop C++03 support and Boost.Preprocessor usage (#13) 2023-08-11 21:34:25 +03:00
Antony Polukhin
7bde4f36af Update CI (3) 2023-05-27 17:30:17 +03:00
Antony Polukhin
b66e6cf881 update CI setup (2) 2023-05-21 12:21:05 +03:00
Antony Polukhin
ad7e8f7e4b update CI setup (1) 2023-05-21 11:19:51 +03:00
Antony Polukhin
6fcb86f6cc update CI setup 2023-05-21 10:59:55 +03:00
Antony Polukhin
b8e658c5bd add C++03 deprecation warnings 2023-05-14 20:08:00 +03:00
Antony Polukhin
9507b06b68 Update copyright years 2023-01-19 10:22:50 +03:00
Peter Dimov
9f35fab4cf Update ci.yml 2022-12-24 17:51:43 +02:00
Peter Dimov
d4fe92e302 Regenerate CMakeLists.txt 2022-12-23 03:05:52 +02:00
Antony Polukhin
cca370a918 update copyright years 2022-01-30 15:01:13 +03:00
Antony Polukhin
97fc5b9838 do not use depth 1 for checkouts in CI 2021-09-20 21:56:00 +03:00
Antony Polukhin
0cc169ecd6 modernize CI setup 2021-09-11 18:18:54 +03:00
Peter Dimov
a3c6a957ee Update CMakeLists.txt 2021-06-10 00:48:35 +03:00
Antony Polukhin
04cc1734ef use HTTPS links in Readme 2021-04-27 11:22:44 +03:00
Antony Polukhin
f395836779 gather coverage in CI from more platforms 2021-04-24 21:53:20 +03:00
Antony Polukhin
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
Antony Polukhin
a2ef72c907 CI updates: proper setup of clang-7 and restore sanitizers for gcc-10 2021-04-24 14:28:28 +03:00
Antony Polukhin
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
Antony Polukhin
d6d07a8ce8 add missing include and do not tests on clang-3.7 2021-04-24 13:49:52 +03:00
Antony Polukhin
4468903f8f modernize CI 2021-04-24 12:47:19 +03:00
Antony Polukhin
88c5d9a998 fix broken link 2021-04-24 12:46:59 +03:00
Antony Polukhin
f0b87ea7d3 Merge pull request #35 from sdarwin/githubactions
GitHub Actions config
2021-04-18 14:10:35 +03:00
sdarwin
03794d6144 Add GitHub Actions config [ci skip] 2021-03-04 18:22:58 +00:00
Antony Polukhin
62154d3b19 Merge pull request #33 from sdarwin/drone
Drone config
2021-01-27 10:29:41 +03:00
Antony Polukhin
b4014f385d Merge pull request #32 from eldiener/develop
[skip ci] Add "cxxstd" json field
2021-01-27 10:25:31 +03:00
sdarwin
0dc42bab8f add drone config [ci skip] 2021-01-26 15:29:49 +00:00
Edward Diener
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
Antony Polukhin
f40f4731e1 Merge github.com:apolukhin/type_index into develop 2021-01-04 18:29:36 +03:00
Antony Polukhin
754fb0f348 CI fix attempt (1) 2021-01-04 13:32:09 +03:00
Antony Polukhin
6fa4f57e7d CI fix attempt 2021-01-04 13:23:42 +03:00
Antony Polukhin
c79f1c8d5d Specify address model for MSVC
Relates boostorg/build#659
2021-01-04 11:04:54 +03:00
Antony Polukhin
843ee6848b update copyright years 2021-01-03 20:01:31 +03:00
Antony Polukhin
6fc5b35b00 Merge pull request #31 from sdarwin/lcov
update .travis.yml to correct lcov error messages
2021-01-03 12:49:28 +03:00
sdarwin
84d68f32e2 update lcov in .travis.yml 2020-12-31 00:51:49 +00:00
Antony Polukhin
1dacdb561e Merge pull request #29 from Kojoley/cease-dependence-on-smart_ptr
Cease dependence on SmartPtr
2020-08-27 12:03:36 +03:00
Antony Polukhin
9862011b6b CI fixes 2020-07-06 11:36:48 +03:00
Nikita Kniazev
321749796e Cease dependence on SmartPtr
by forward declaring `boost::shared_ptr`
2020-05-26 02:56:12 +03:00
Antony Polukhin
f2e395a7f3 update copyright years 2020-01-22 23:26:24 +03:00
Antony Polukhin
9936c31851 Attempt to fix CI 2019-11-12 09:00:57 +03:00
Antony Polukhin
560c7d2ef6 Change header file to include 2019-11-11 20:56:04 +03:00
Antony Polukhin
bf33e63feb CI fixes 2019-11-11 18:47:46 +03:00
Antony Polukhin
2152466531 CI fixes 2019-08-29 19:12:02 +03:00
Antony Polukhin
389f621450 CI + inspect tool fixes 2019-08-29 16:00:48 +03:00
Antony Polukhin
0b65c1a8d8 Disable some of the inspect tool checks 2019-08-28 20:59:16 +03:00
Antony Polukhin
216c21b728 Fix issues found by inspect too and add it to CI 2019-08-28 17:54:46 +03:00
Antony Polukhin
afd1b6cdc8 Merge pull request #28 from Breakthrough/develop
Add CTTI name prettifying for GHS C++ compiler.
2019-03-02 11:33:11 +03:00
Brandon Castellano
d69a8a211b Add CTTI name prettifying for GHS C++ compiler. 2019-02-28 12:33:14 -05:00
Antony Polukhin
ebe74ba4ba Merge pull request #27 from Mike-Devel/min_cmake
[CMake] Add minimal cmake file
2019-02-20 21:27:23 -10:00
Mike Dev
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
Antony Polukhin
f68d6dc073 update copyrights 2019-01-17 22:45:35 +03:00
Antony Polukhin
85f43ece0d Merge remote-tracking branch 'lastique/optimize_ctti_strcmp' into develop 2018-12-23 12:24:16 +03:00
Antony Polukhin
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
Antony Polukhin
c585d74669 Disable part of the tests for _MSC_VER == 1916 and below 2018-12-16 11:55:04 +03:00
Antony Polukhin
32909cb25a fixes for tests 2018-12-16 11:30:59 +03:00
Antony Polukhin
7af1661709 Fixes for travis CI 2018-12-15 22:06:18 +03:00
Antony Polukhin
351cedf404 ADjust sanitizers in CI builds 2018-12-15 21:26:25 +03:00
Antony Polukhin
098c84481e Merge branch 'develop' into feature/ci-update 2018-12-15 16:33:40 +03:00
Antony Polukhin
d9d13b9574 ci update 2018-12-14 11:56:02 +03:00
Antony Polukhin
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
Peter Dimov
acb536a67e Fix compile_time_type_info for clang-cl 2018-11-16 02:06:10 +02:00
Antony Polukhin
7654c26594 Increase MSVC requirements for constexpr sorted test (refs #24) 2018-11-16 01:58:18 +03:00
Antony Polukhin
075b3682ae Disable constexpr sort test for MSVC <= 1914 (refs #24) 2018-11-15 21:58:17 +03:00
Antony Polukhin
a60e25a74d Better diagnostics for missing PRETTY_FUNCTION macro (refs #24) 2018-11-14 09:09:37 +03:00
Andrey Semashev
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
Antony Polukhin
f3da852bca Update stl_type_index.hpp 2018-10-20 20:19:04 +03:00
Antony Polukhin
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
Nikita Kniazev
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
Antony Polukhin
09f0bc23c5 fix b2 warnings 2018-09-22 22:13:42 +03:00
Glen Fernandes
718af3e8dc Fix tests which did not return report_errors() 2018-09-17 07:43:19 -04:00
Antony Polukhin
c9c1412a05 Tests to reproduce the track issue 13621 2018-07-28 17:44:17 +03:00
Antony Polukhin
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
Justin LaPolla
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
Antony Polukhin
be9f5a4b9b Droped dependency on MPL 2018-03-24 09:50:37 +03:00
Antony Polukhin
bd19ed1a87 Disable link-fail tests and restore MinGW CI 2018-01-23 10:40:56 +03:00
Antony Polukhin
727cdadc86 Restore link-fail 2018-01-16 01:21:20 +03:00
Antony Polukhin
5bc4f54183 Dropped -fail to check the MSVC builds 2018-01-16 01:10:28 +03:00
Antony Polukhin
918e59c109 One more fix in tests for /GR- flag 2018-01-16 00:44:11 +03:00
Antony Polukhin
cd659212aa Workaround for /GR- override in tests 2018-01-16 00:28:48 +03:00
Antony Polukhin
70e51a62e9 Workaround for /GR- override that disables link time assertions 2018-01-15 23:21:34 +03:00
Antony Polukhin
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
Antony Polukhin
82ed016577 Use hash_fwd header and use new paths to boost::hash* 2018-01-14 23:41:33 +03:00
Antony Polukhin
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
Antony Polukhin
be08eda196 Do not suppress already suppressed warnings 2017-09-26 22:05:57 +03:00
Antony Polukhin
baa5019c90 Merge pull request #16 from bebuch/develop
fix ctti_type_index for GCC 7
2017-07-29 20:13:04 +03:00
Benjamin Buch
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
Antony Polukhin
93e7b2458b Fixed some warnings 2017-06-25 14:05:08 +03:00
Daniela Engert
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
Antony Polukhin
b0737f4169 Fix formatting in README 2017-05-18 22:51:47 +03:00
Antony Polukhin
be74716251 Use native hash_code() when possible on GCC-like compilers 2017-05-18 22:50:25 +03:00
Antony Polukhin
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
Antony Polukhin
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
Chris Glover
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
Chris Glover
7f8af2a6e9 Merge branch 'develop' into split_register_and_implement 2017-02-25 13:19:16 -05:00
Antony Polukhin
342d835289 Run MinGW tests too (thanks to Pavel Filinov for showing that appveyor apability) 2017-02-23 21:35:40 +03:00
Edward Catmur
5cacb67510 Make it derived class responsibility to include <boost/functional/hash.hpp> 2017-02-16 21:55:12 +00:00
Ed Catmur
f2616bcd17 Correct preprocessor condition to match below 2017-02-16 16:30:52 +00:00
Ed Catmur
8c582362d0 Include <boost/functional/hash.hpp> if required 2017-02-16 16:18:48 +00:00
Antony Polukhin
f71d9eb3f2 Fix undefined macro warning (trac 12739) 2017-01-18 22:33:13 +03:00
Antony Polukhin
cfcdcd647d Update CI script version 2016-12-04 02:39:22 +03:00
Antony Polukhin
8bee2f6939 Fix coverage info gathering in travisCI script for GCC-6 2016-12-04 02:29:02 +03:00
Antony Polukhin
40985de221 Update CI scripts and tests 2016-11-18 22:31:01 +03:00
Chris Glover
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
Rene Rivera
c52fdfe30c Add, and update, documentation build targets. 2016-10-07 23:07:37 -05:00
Antony Polukhin
7f840c882e Fix build in C++98 mode 2016-10-02 10:39:54 +03:00
Antony Polukhin
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
Antony Polukhin
d656e1879a Merge pull request #12 from cdglove/runtime_cast_test_fixes
Cleanup of shared_ptr ifdef.
2016-10-02 10:58:49 +04:00
Chris Glover
b1ed011b6e Cleaner removal of std::shared_ptr tests on compilers without C++11 shared_ptr 2016-10-01 14:49:28 -04:00
Antony Polukhin
4d1cf425e0 Merge pull request #11 from cdglove/runtime_cast_test_fixes
Runtime cast test fixes
2016-09-30 21:34:10 +04:00
Chris Glover
d6ca24ff3c Merge branch 'runtime_cast' into runtime_cast_test_fixes 2016-09-29 22:31:07 -04:00
Chris Glover
4459af9532 FIx a unit test so that the NULL check happens before the dereference. 2016-09-29 22:29:35 -04:00
Chris Glover
b61a7423b7 Update unit test to remove shared_ptr on compilers less than C++11. 2016-09-29 22:29:10 -04:00
Chris Glover
1a918009fd Fix comment. 2016-09-29 22:27:10 -04:00
Antony Polukhin
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
Antony Polukhin
6cf5288a8c Merge pull request #9 from efcs/clang-4-fix
Support Clang version 4.0.
2016-08-30 22:43:14 +04:00
Eric Fiselier
4453acf867 Support Clang 4.0 and newer 2016-08-29 22:10:34 -06:00
Chris Glover
b6b23bad3a Cleanup line endings, file endings, some spacing etc. 2016-08-21 12:47:44 -04:00
Chris Glover
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
Chris Glover
9cd218bbc4 Add missing include to example. 2016-08-19 18:42:22 -04:00
Chris Glover
ad26256d09 Initial documentation. 2016-08-11 10:31:16 -04:00
Chris Glover
5af925602e Invoke smart_ptr tests. 2016-08-10 10:06:41 -04:00
Chris Glover
2fb667a6a0 Experiment with a version of runtime_cast that has only a single registration macro. 2016-08-09 23:13:54 -04:00
Chris Glover
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
Chris Glover
0b006b6af6 Remove all references to std::type_traits
Replace variadic template with boost preprocessor.
2016-08-08 12:16:58 -04:00
Chris Glover
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
Chris Glover
ee7b15a493 First version.
TODO: Error messages when using mismatched types are not clear. Needs consideration.
2016-07-15 16:30:16 -04:00
Chris Glover
1dc8310826 Optimization: Don't check all bases. 2016-07-15 10:10:07 -04:00
Chris Glover
b230140529 First version. 2016-07-15 08:49:54 -04:00
Antony Polukhin
31ec1d2524 Fix link in README 2016-06-05 13:02:56 +03:00
Antony Polukhin
40e9bd336a Test on same Boost branch when running Appveyor 2016-06-04 21:10:20 +03:00
Antony Polukhin
767c724983 README now shows build status on Windows platform 2016-06-04 15:59:29 +03:00
Antony Polukhin
24708cc109 One more example and integrate examples into the docs 2016-03-30 23:24:53 +03:00
Antony Polukhin
57205874ae Added namespace detection example 2016-03-30 22:28:53 +03:00
Antony Polukhin
1b4a85764f Fixing test under Windows 2016-03-29 23:16:17 +03:00
Antony Polukhin
1976355e8f appveyor update 1 2016-03-29 22:36:12 +03:00
Antony Polukhin
0efc48e16c Add appveyor integration and increment minor version of the library 2016-03-29 21:45:50 +03:00
Antony Polukhin
e96a6e8f80 Use constexpr in documentation 2016-03-29 21:38:46 +03:00
Antony Polukhin
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
Antony Polukhin
8b6c3facb3 Fixes and GCC related improvements 2016-03-28 22:42:39 +03:00
Antony Polukhin
ffb98af0dd Attempt to use libc++ in TravisCi tests no. 6 2016-03-27 22:05:40 +03:00
Antony Polukhin
9122022faf Attempt to use libc++ in TravisCi tests no. 5 2016-03-27 21:50:33 +03:00
Antony Polukhin
18dbaea6ee Attempt to use libc++ in TravisCi tests no. 4 2016-03-27 21:42:08 +03:00
Antony Polukhin
6dabf11504 Third attempt to use libc++ in TravisCi tests 2016-03-27 21:32:18 +03:00
Antony Polukhin
7bd788c5d7 Second attempt to use libc++ in TravisCi tests 2016-03-27 21:27:10 +03:00
Antony Polukhin
2d87bc6194 Attempt to use libc++ in travisCi tests 2016-03-27 18:38:08 +03:00
Antony Polukhin
36efa3969b Use the cstring workaround only for GCC 2016-03-27 14:46:27 +03:00
Antony Polukhin
551535f8cf Dropped the using syntax 2016-03-26 16:43:22 +03:00
Antony Polukhin
3f004511a2 Do not use decltype 2016-03-26 16:24:51 +03:00
Antony Polukhin
30bb93bd23 Test on clang too 2016-03-26 16:01:42 +03:00
Antony Polukhin
7f2b9fd31a Combine klemens-morgenstern ideas with mine. Must compile and work at least on GCC-5 2016-03-26 15:49:09 +03:00
Antony Polukhin
c9f1370d0c Merge tests from klemens-morgenstern 2016-03-25 21:34:30 +03:00
Antony Polukhin
1ec4460244 Merge .travis.yml from klemens-morgenstern 2016-03-25 21:26:47 +03:00
Antony Polukhin
1ed55a2f12 Merge branch 'constexpr14' of github.com:boostorg/type_index into constexpr14 2016-03-25 21:16:21 +03:00
Antony Polukhin
1c685fa119 Initial C++14 constexpr version of ctti_type_index. No ABI breakage 2016-03-25 21:15:52 +03:00
Antony Polukhin
37484c19ec Merge pull request #5 from klemens-morgenstern/develop
FIxed space removal
2016-02-13 23:50:45 +03:00
klemens-morgenstern
bb02f97414 Merge remote-tracking branch 'remotes/fork/develop' into develop 2016-02-13 19:12:19 +01:00
klemens-morgenstern
b9db462091 fixed length with noexcept 2016-02-13 19:11:04 +01:00
klemens-morgenstern
cf4f09b520 Merge branch 'develop' of https://github.com/boostorg/type_index into develop 2016-02-13 19:09:13 +01:00
klemens-morgenstern
5de7f5def6 added comparison test 2016-02-13 19:08:59 +01:00
klemens-morgenstern
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
Antony Polukhin
6ff2a75da3 Merge pull request #4 from klemens-morgenstern/develop
added in variant for MSVC with noexcept
2016-02-13 19:48:26 +03:00
klemens-morgenstern
58b0f69e52 added in variant for MSVC with noexcept 2016-02-12 10:00:44 +01:00
Antony Polukhin
478da3512a Merge pull request #7 from norbertwenzel/develop
fixed two typos in documentation
2016-01-28 22:51:50 +03:00
Norbert Wenzel
a373a4c7ed fixed two typos in documentation 2016-01-27 20:13:40 +01:00
Antony Polukhin
34835b90e3 Ignore tests coverage for unrelated libraries 2016-01-05 16:49:41 +03:00
Antony Polukhin
236fdc8dba Update .travisci to use non-sudo approach 2016-01-05 16:39:43 +03:00
Antony Polukhin
1ff942f329 Fix old MSVC warning 2015-12-10 20:55:45 +03:00
Antony Polukhin
f58844637c travis fixes 2015-08-22 21:21:46 +03:00
Antony Polukhin
9fede62a7c Fix travis build 2015-08-22 12:55:55 +03:00
Antony Polukhin
48d50ae178 Run TravisCI tests using valgrind 2015-08-22 11:44:54 +03:00
Antony Polukhin
743b2a8851 Initial C++14 constexpr version of ctti_type_index. No ABI breakage 2015-08-01 20:13:38 +03:00
Antony Polukhin
7e2a538eb5 Fixed semicolon warnings 2015-07-30 23:00:41 +03:00
Antony Polukhin
e5e105013a Fix shadow warning for name variable (svn #11503) 2015-07-28 22:53:24 +03:00
Antony Polukhin
d7ec25e56b Use lightweight tests to avoid Boost.Test warnings, RTTI issues and minimize compilation times 2015-06-21 23:16:46 +03:00
Antony Polukhin
c0f75c27fa Avoid warnings in some tests and do more checks 2015-06-18 22:01:45 +03:00
Antony Polukhin
3e6695971d Removed applied patches 2015-06-17 21:54:04 +03:00
Antony Polukhin
8d3127935d Drop dependency to Boost.Functional 2015-04-25 12:44:27 +03:00
Antony Polukhin
d585fc3673 Merge pull request #6 from akumta/patch-1
Update compile_time_type_info.hpp
2015-03-12 16:20:12 +04:00
akumta
6b5d2743c5 Update compile_time_type_info.hpp
Update for ticket 11099
2015-03-10 13:44:18 -07:00
Antony Polukhin
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
Antony Polukhin
8ddc5feac4 Updated README.md and added .travis.yml 2014-12-23 14:33:20 +03:00
Antony Polukhin
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
Marcel Raad
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
Antony Polukhin
242d9a0bed Use detect_mismatch pragma when possible (refs #10404 in track) 2014-08-26 14:41:54 +04:00
Antony Polukhin
99f58714d1 Fix a lot of typos [refs #10294](https://svn.boost.org/trac/boost/ticket/10294) 2014-08-02 16:15:00 +04:00
Antony Polukhin
7b04caa160 Fixed problems reported by inspection program 2014-08-01 12:34:34 +04:00
Antony Polukhin
4d221d4f71 Minor changes: added consts and replaced BOOST_THROW_EXCEPTION with throw_exception 2014-06-16 09:42:21 +04:00
Antony Polukhin
806a192df1 Merge pull request #4 from Lastique/patch-1
Thanks a lot!
2014-06-16 09:31:49 +04:00
Andrey Semashev
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
Andrey Semashev
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
Antony Polukhin
436ecd0b3e Added Configuration section to the docs and fixed minor issues 2014-06-02 15:56:12 +04:00
Antony Polukhin
9fcbfd18ce Add more -DBOOST_NO_RTTI to Jamfile 2014-05-24 11:42:14 +04:00
Antony Polukhin
1916e2b42f Fixes for Clang+Apple 2014-05-22 17:03:02 +04:00
Antony Polukhin
56bd9b401a Gix a Boost.test another chance, more macro definitions in build scripts 2014-05-22 12:38:32 +04:00
Antony Polukhin
e2c227d4aa Fix a typo and improve macro definitionas in Jamfile 2014-05-21 10:47:30 +04:00
Antony Polukhin
80086cbc4f Do not use Boost.Test at all 2014-05-21 10:33:22 +04:00
Antony Polukhin
0f0902d11c Explicitly define BOOSTNO_RTTI: do not rely on ability of Boost.Config to detect RTTI 2014-05-20 21:26:33 +04:00
Antony Polukhin
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
Antony Polukhin
ce103443fd Merge pull request #3 from danieljames/redirect-fix
Redirect fix
2014-05-20 17:04:45 +04:00
Daniel James
b34d4d466d Fix the documentation redirect location. 2014-05-20 09:01:59 +01:00
Antony Polukhin
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
Daniel James
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
Antony Polukhin
76dc3d1053 Added index.html 2014-05-19 11:28:27 +04:00
Antony Polukhin
28c77f4036 Merge pull request #1 from danieljames/metadata
Add metadata file
2014-05-19 08:41:15 +04:00
Daniel James
631e592b7a Add metadata file 2014-05-18 23:30:16 +01:00
Antony Polukhin
fa2fa1805c Added always_show_run_output to ctti_print_name test rule 2014-05-14 09:32:34 +04:00
Antony Polukhin
0744f86a2c Simplify the ctti_print_name.cpp 2014-05-13 14:17:42 +04:00
Antony Polukhin
61594ba1da Fix nortti builds on Intel compiler 2014-05-13 12:03:15 +04:00
Antony Polukhin
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
Antony Polukhin
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
Antony Polukhin
8c8d9c6c69 Simplify redefinition of parsing rules 2014-05-11 03:11:34 +04:00
Antony Polukhin
eac9c8af2f Another attempt to disable table_of_names_no_rtti test 2014-05-08 11:37:09 +04:00
Antony Polukhin
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
Antony Polukhin
ecac9ac83c Tune CTTI for different versions of Clang 2014-05-07 16:46:07 +04:00
Antony Polukhin
8a8a3ec639 Fix build script 2014-05-07 16:37:57 +04:00
Antony Polukhin
6931c1de4c Updated docs and removed applied patch 2014-05-07 15:29:52 +04:00
Antony Polukhin
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
Antony Polukhin
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
Antony Polukhin
f7388d59b5 Fix some of the notes mentioned by Andrey Semashev (more to come) 2014-05-06 16:27:03 +04:00
Antony Polukhin
2602569bc4 Fixed issueas mentioned by Mathieu Champlon during Boost review 2014-05-06 13:03:59 +04:00
Antony Polukhin
172d4a25ca Fixed issues mentioned by Dominique Devienne during Boost review 2014-05-05 19:49:56 +04:00
Antony Polukhin
6af608a827 Fixed notes mentioned by Klaim - Joël Lamotte during review 2014-05-04 20:28:45 +04:00
Antony Polukhin
5ed8543025 Changed namespace to boost::typeindex 2014-05-04 14:42:12 +04:00
Antony Polukhin
a66ffcfa50 Fixed issues noted by Paul A. Bristow during review 2014-05-04 14:22:25 +04:00
Antony Polukhin
2e11dc75d4 Fix a typo 2014-04-14 18:00:01 +04:00
Antony Polukhin
a2a934dde8 Added test to ensure that alignments of ctti_data and char are same 2014-03-06 11:39:10 +04:00
Antony Polukhin
3f51425f3c Fixed possible UB 2014-03-06 10:32:23 +04:00
Antony Polukhin
501a0a992e Fix typos in docs 2014-03-05 15:12:25 +04:00
Antony Polukhin
b8265cdb4f Minor changes to docs 2014-02-21 17:49:32 +04:00
Antony Polukhin
89398ac07c Added .gitignore 2014-02-21 13:01:05 +04:00
Antony Polukhin
40f6ae1ede Make code thread safe even on antique/broken compilers. Improve examples and add more tests 2014-02-21 12:52:07 +04:00
Antony Polukhin
2ebd172f4e Final cleanup of directory. Patches were updated. Minor bugfixes. 2014-02-20 18:53:05 +04:00
Antony Polukhin
70fdaa633e Fix typo 2014-02-20 16:38:55 +04:00
Antony Polukhin
7ddb306c65 Some MSVC related updates and docs improvements 2014-02-20 16:30:13 +04:00
Antony Polukhin
7488e75a9c Finished example with user defined type_index, improved doocs and refactored some of the functions 2014-02-20 15:36:23 +04:00
Antony Polukhin
b44845b46d Started documenting the user_defined_typeinfo example and embedding it into the docs 2014-02-19 18:54:28 +04:00
Antony Polukhin
0d8c6f36ad Fix typo 2014-02-19 17:31:54 +04:00
Antony Polukhin
98e5bbe6ac Docs improved 2014-02-19 17:22:37 +04:00
Antony Polukhin
276101f1b3 Added example of user defined type index class 2014-02-19 16:20:19 +04:00
Antony Polukhin
ea2e5beabb Allow runtime type info even when RTTI is off. Improve tests and examples 2014-02-19 13:03:12 +04:00
Antony Polukhin
c99b7b26da Sources cleanup and some typo fixes 2014-02-14 16:00:32 +04:00
Antony Polukhin
78824176ea Minor change of interface. Added default constructors. More tests added. Documentation improved 2014-02-14 14:39:09 +04:00
Antony Polukhin
de0d90eca1 More functionality moved to type_index_facade and better documentation for facade. 2014-02-09 14:16:36 +04:00
Antony Polukhin
2ef8924510 Documented some of the classes and features 2014-02-07 17:10:36 +04:00
Antony Polukhin
beaa53f460 Add some examples of how to create type_indexes 2014-02-07 15:08:14 +04:00
Antony Polukhin
0137b9b43f Moved some of the classes from boost::typeind::detail namespace to boost::typeind namespace 2014-02-07 13:41:17 +04:00
Antony Polukhin
683dab93a2 Reimplement and simplify design using type_index_facade class 2014-02-07 13:32:24 +04:00
Antony Polukhin
496ab93589 Reduced header dependencies 2014-02-06 19:00:14 +04:00
Antony Polukhin
c0871ef714 Removed old unused files 2014-02-06 18:46:01 +04:00
Antony Polukhin
2f9c4b7834 Restored all the tests and examples, fixed some issues 2014-02-06 18:42:08 +04:00
Antony Polukhin
c43f8c1cfa Restore some of the tests and fix a bunch of bugs 2014-02-06 17:52:18 +04:00
Antony Polukhin
50d496288f Compile time type info implementation added 2014-02-06 16:53:10 +04:00
Antony Polukhin
3daeab38fa Started the work on new interface 2014-02-06 16:00:27 +04:00
Antony Polukhin
5f97225a18 New project structure to satisfy Modular Boost requirements. 2014-01-11 19:02:05 +04:00
Antony Polukhin
5977f9ce6e Update docs to reflect library status after Boost review 2014-01-11 18:37:43 +04:00
Antony Polukhin
9ea436c4d3 Applied one more part of changes proposed by Vicente J. Botet Escriba 2013-11-13 11:01:54 +04:00
Antony Polukhin
9e4e48a9b3 Applied first portion of fixes, proposed by Vicente J. Botet Escriba 2013-11-13 10:35:20 +04:00
Antony Polukhin
986ff55058 Add compile time error mesage when attempting to call RTTI only method under MSVC 2013-11-12 10:44:52 +04:00
Antony Polukhin
736bdd4e04 Workarounf MSVC1600 issues, supress MSVC warnings 2013-11-12 10:27:44 +04:00
Antony Polukhin
45649b44e5 Minor improvements of docs 2013-11-06 11:26:40 +04:00
Antony Polukhin
477a7b0c2c minor docs update 2013-11-05 19:32:39 +04:00
Antony Polukhin
9aef004abc Attempt to optimize MSVC calls to typeid with RTTI off 2013-11-05 19:20:30 +04:00
Antony Polukhin
2a086a81c5 Added sp_typeinfo patch 2013-11-01 17:42:45 +04:00
Antony Polukhin
c2910c18a8 Added patches for Boost.Variant 2013-11-01 15:53:03 +04:00
Antony Polukhin
860c454c93 Fixed MSVC warnings and added some notes 2013-11-01 11:00:04 +04:00
Antony Polukhin
a37c8ed87c Disabled one of the tests, that does build with incorrect flags under MSVC 2013-10-31 16:17:41 +04:00
Antony Polukhin
19fef8ddab Fixed MSVC related bugs 2013-10-31 15:55:34 +04:00
Antony Polukhin
79fbd3ab5c Fixed a few more notes from Niall 2013-10-31 11:40:16 +04:00
Antony Polukhin
868328d2f6 Test and verify patches 2013-10-30 16:00:43 +04:00
Antony Polukhin
83e02d83c4 More user friendly 'Getting Started section' 2013-10-29 18:10:13 +04:00
Antony Polukhin
cadd22c74d Docs and doxygen markup updated 2013-10-29 17:08:28 +04:00
Antony Polukhin
1508e1d560 Updated docs 2013-10-29 16:19:26 +04:00
Antony Polukhin
d0d30d56df Updated docs and fixed some issues 2013-10-28 17:16:19 +04:00
Antony Polukhin
8ab45702a0 Many fixes, tests now compile and work 2013-10-28 14:58:30 +04:00
Antony Polukhin
8789bff181 Restored some of the tests, fixed issues and added template_index.hpp.. Still in the middle of big changes 2013-10-28 14:08:19 +04:00
Antony Polukhin
2a45139fd3 In the middle of changes 2013-10-26 21:00:25 +04:00
Antony Polukhin
5d71c723cc Still in the middle of heavy changes 2013-10-26 20:51:14 +04:00
Antony Polukhin
cf4096d317 Some more modifications. 2013-10-26 19:47:31 +04:00
Antony Polukhin
3f48978268 Another commit right in the midle of modifications 2013-10-26 19:14:40 +04:00
Antony Polukhin
69a4fddfb6 Commit is made in the midle of modification process 2013-10-26 18:42:46 +04:00
Antony Polukhin
300001d7c7 Initial commit of branch that attempts to make a pure drop-in replacement for std::type_info 2013-10-26 16:46:39 +04:00
87 changed files with 5319 additions and 10032 deletions

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

@@ -0,0 +1,192 @@
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-12
cxxstd: "03,11,14,17,2a"
os: ubuntu-22.04
cxxflags: "cxxflags=--coverage -fsanitize=address,leak,undefined -fno-sanitize-recover=undefined"
linkflags: "linkflags=--coverage -lasan -lubsan"
gcov_tool: "gcov-12"
launcher: "testing.launcher=LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libasan.so.8"
- toolset: gcc-11
cxxstd: "03,11,14,17,2a"
os: ubuntu-22.04
cxxflags: "cxxflags=--coverage -fsanitize=address,leak,undefined -fno-sanitize-recover=undefined"
linkflags: "linkflags=--coverage -lasan -lubsan"
gcov_tool: "gcov-11"
launcher: "testing.launcher=LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libasan.so.6"
- toolset: gcc-10
cxxstd: "03,11,14,17,2a"
os: ubuntu-22.04
cxxflags: "cxxflags=--coverage -fsanitize=address,leak,undefined -fno-sanitize-recover=undefined"
linkflags: "linkflags=--coverage -lasan -lubsan"
gcov_tool: "gcov-10"
launcher: "testing.launcher=LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libasan.so.6"
- toolset: gcc-9
cxxstd: "03,11,14,17,2a"
os: ubuntu-22.04
cxxflags: "cxxflags=--coverage -fsanitize=address,leak,undefined -fno-sanitize-recover=undefined"
linkflags: "linkflags=--coverage -lasan -lubsan"
gcov_tool: "gcov-9"
launcher: "testing.launcher=LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libasan.so.5"
- toolset: clang
compiler: clang++-14
cxxstd: "03,11,14,17,2a"
os: ubuntu-22.04
- toolset: clang
compiler: clang++-10
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v3
- 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.0
cxxstd: "14,latest"
addrmd: 32,64
os: windows-2019
- toolset: msvc-14.2
cxxstd: "14,17,20,latest"
addrmd: 32,64
os: windows-2019
- toolset: msvc-14.3
cxxstd: "14,17,20,latest"
addrmd: 32,64
os: windows-2022
- toolset: clang-win
cxxstd: "14,17,latest"
addrmd: 32,64
os: windows-2022
- toolset: gcc
cxxstd: "03,11,14,17,2a"
addrmd: 64
os: windows-2019
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v3
- 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 embed-manifest-via=linker
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

378
.gitignore vendored
View File

@@ -1,376 +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/
doc/autodoc.xml
doc/html

27
CMakeLists.txt Normal file
View File

@@ -0,0 +1,27 @@
# Generated by `boostdep --cmake type_index`
# Copyright 2020, 2021 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# https://www.boost.org/LICENSE_1_0.txt
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::throw_exception
)
if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt")
add_subdirectory(test)
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,28 +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 type_index.hpp
/// \brief Includes all the headers of the Boost.TypeIndex library.
///
/// By inclusion of this file both classes (boost::type_index if RTTI is on and boost::template_index) will be available.
///
/// Consider including <boost/type_index/type_index_minimal.hpp> if you do not whant to include
/// boost::template_index class while RTTI is available (this is recommended).
// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/type_index/type_index_minimal.hpp>
#include <boost/type_index/template_index_impl.hpp>
#endif // BOOST_TYPE_INDEX_HPP

View File

@@ -1,311 +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_IMPL_HPP
#define BOOST_TYPE_INDEX_TEMPLATE_INDEX_IMPL_HPP
// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
# pragma once
#endif
#ifndef BOOST_TYPE_INDEX_TYPE_INDEX_MINIMAL_HPP
#error "Header <boost/type_index/template_index_impl.hpp> must not be included directly."
#error "Include <boost/type_index/type_index_minimal.hpp> or <boost/type_index.hpp> instead."
#endif
/// \file template_index_impl.hpp
/// \brief Contains implementation of boost::template_index class.
///
/// boost::template_index class is used instead of boost::type_index class in situations when RTTI is disabled.
///
/// Consider including <boost/type_index/type_index_minimal.hpp> or <boost/type_index.hpp> instead of this file.
#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_index 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_index, 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_index class.
#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_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();
}
/// Returns true if the type precedes the type of rhs in the collation order.
/// The collation order is just an internal order.
template <class BefT>
static bool before() BOOST_NOEXCEPT {
return std::strcmp(this_type::n(), ctti<BefT>::n()) < 0;
}
/// Returns length of demangled name
static std::size_t name_length() BOOST_NOEXCEPT {
return std::strlen(this_type::n() + detail::ctti_skip_size_at_end);
}
/// Returns user-friendly name
static std::string name_demangled() BOOST_NOEXCEPT {
return std::string(this_type::n(), this_type::name_length());
}
};
} // namespace detail
/// Copyable type_info that does not require RTTI and could store const,
/// volatile and references if constructed via construct_with_cvr()
class template_index {
private:
const char* name_;
/// @cond
explicit template_index(const char* name) BOOST_NOEXCEPT
: name_(name)
{}
/// @endcond
public:
/// Default constructor.
template_index() BOOST_NOEXCEPT
: name_(detail::ctti<void>::name())
{}
/// Factory method for constructing template_index instance for type T.
/// Strips const, volatile and & modifiers from T
template <class T>
static template_index construct(){
typedef BOOST_DEDUCED_TYPENAME boost::remove_reference<T>::type no_ref_t;
typedef BOOST_DEDUCED_TYPENAME boost::remove_cv<no_ref_t>::type no_cvr_t;
# if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \
|| (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744)
BOOST_STATIC_ASSERT_MSG( !boost::is_arithmetic<no_cvr_t>::type::value
, "Your EDG-based compiler seems to mistakenly distinguish 'int' from 'signed int', in typeid() expressions.");
#endif
return template_index(detail::ctti<no_cvr_t>::name());
}
/// Factory method for constructing template_index instance for type T.
/// Does not strip const, volatile and & modifiers from T
template <class T>
static template_index construct_with_cvr() {
# if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \
|| (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744)
BOOST_STATIC_ASSERT_MSG( !boost::is_arithmetic<T>::type::value
, "Your EDG-based compiler seems to mistakenly distinguish 'int' from 'signed int', in typeid() expressions.");
#endif
return template_index(detail::ctti<T>::name());
}
/// Returns true if the type precedes the type of rhs in the collation order.
/// The collation order is just an internal order.
bool before(const template_index& rhs) const 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 {
return std::string(name_, std::strlen(name_ + detail::ctti_skip_size_at_end));
}
/// @cond
bool operator == (const template_index& rhs) const BOOST_NOEXCEPT {
return !std::strcmp(name_, rhs.name());
}
bool operator != (const template_index& rhs) const BOOST_NOEXCEPT {
return !!std::strcmp(name_, rhs.name());
}
bool operator < (const template_index& rhs) const BOOST_NOEXCEPT {
return std::strcmp(name_, rhs.name()) < 0;
}
bool operator > (const template_index& rhs) const BOOST_NOEXCEPT {
return std::strcmp(name_, rhs.name()) > 0;
}
bool operator <= (const template_index& rhs) const BOOST_NOEXCEPT {
return std::strcmp(name_, rhs.name()) <= 0;
}
bool operator >= (const template_index& rhs) const BOOST_NOEXCEPT {
return std::strcmp(name_, rhs.name()) >= 0;
}
/// @endcond
/// 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_index instance for type T.
/// Strips const, volatile and & modifiers from T.
template <class T>
inline template_index template_id() BOOST_NOEXCEPT {
return template_index::construct<T>();
}
/// Factory method for constructing template_index 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 template_index template_id_with_cvr() BOOST_NOEXCEPT {
return template_index::construct_with_cvr<T>();
}
/* *************** template_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, template_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, template_index const& ind) {
ostr << ind.name_demangled();
return ostr;
}
#endif // BOOST_NO_TEMPLATED_IOSTREAMS
#endif // BOOST_NO_IOSTREAM
/// hash_value function overload for template_index
inline std::size_t hash_value(template_index const& v) BOOST_NOEXCEPT {
return v.hash_code();
}
} // namespace boost
#endif // BOOST_TYPE_INDEX_TEMPLATE_INDEX_IMPL_HPP

View File

@@ -1,392 +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_IMPL_HPP
#define BOOST_TYPE_INDEX_TYPE_INDEX_IMPL_HPP
// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
# pragma once
#endif
#ifndef BOOST_TYPE_INDEX_TYPE_INDEX_MINIMAL_HPP
#error "Header <boost/type_index/type_index_impl.hpp> must not be included directly."
#error "Include <boost/type_index/type_index_minimal.hpp> or <boost/type_index.hpp> instead."
#endif
/// \file type_index_impl.hpp
/// \brief Contains implementation of boost::type_index class.
///
/// boost::type_index class is used in situations when RTTI is enabled.
/// When RTTI is disabled or BOOST_TYPE_INDEX_FORCE_NORTTI_COMPATIBILITY macro is defined boost::template_index
/// is used instead.
///
/// Consider including <boost/type_index/type_index_minimal.hpp> or <boost/type_index.hpp> instead of this file.
#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/current_function.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/functional/hash_fwd.hpp>
#ifndef BOOST_NO_RTTI
#include <typeinfo>
#endif
#if !defined(BOOST_NO_IOSTREAM)
#if !defined(BOOST_NO_IOSFWD)
#include <iosfwd> // for std::basic_ostream
#else
#include <ostream>
#endif
#endif
#ifdef __GNUC__
#include <cxxabi.h>
#endif
namespace boost {
#ifndef BOOST_NO_RTTI
#ifndef BOOST_TYPE_INDEX_DOXYGEN_INVOKED
// for this compiler at least, cross-shared-library type_info
// comparisons don't work, so use typeid(x).name() instead. It's not
// yet clear what the best default strategy is.
# if (defined(__GNUC__) && (__GNUC__ < 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
#endif // BOOST_TYPE_INDEX_DOXYGEN_INVOKED
namespace detail {
template <class T> class cvr_saver{};
}
/// Copyable type_info class that requires RTTI.
class type_index {
public:
#ifdef BOOST_NO_STD_TYPEINFO
typedef type_info stl_type_info;
#else
typedef std::type_info stl_type_info;
#endif
private:
const stl_type_info* pinfo_;
public:
/// Default constructor.
type_index() BOOST_NOEXCEPT
: pinfo_(&typeid(void))
{}
/// Constructs type_index from an instance of std::type_info.
explicit type_index(const stl_type_info& inf) BOOST_NOEXCEPT
: pinfo_(&inf)
{}
/// Factory method for constructing type_index instance for type T.
/// Strips const, volatile and & modifiers from T.
template <class T>
static type_index 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 type_index(typeid(no_cvr_t));
}
/// Factory method for constructing type_index 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>()`.
template <class T>
static type_index 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 construct<type>();
}
/// Factory function, that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index.
/// This method available only with RTTI enabled.
template <class T>
static type_index construct_rtti_only(T& rtti_val) {
return type_index(typeid(rtti_val));
}
/// Factory function, that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index.
/// This method available only with RTTI enabled.
template <class T>
static type_index construct_rtti_only(T* rtti_val) {
return type_index(typeid(rtti_val));
}
/// 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 {
#ifdef _MSC_VER
return pinfo_->raw_name();
#else
return pinfo_->name();
#endif
}
/// Returns user-friendly name
std::string name_demangled() const {
#if defined(__GNUC__)
std::string ret;
int status = 0;
char* demang = abi::__cxa_demangle(pinfo_->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);
#else
std::string ret = pinfo_->name();
#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] == ' ') {
-- end;
}
return ret.substr(pos, end - pos);
}
#ifndef BOOST_TYPE_INDEX_DOXYGEN_INVOKED
bool operator == (type_index const& rhs) const BOOST_NOEXCEPT {
#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
return !std::strcmp(pinfo_->name(), rhs.pinfo_->name());
#else
return *pinfo_ == *rhs.pinfo_;
#endif
}
bool operator != (type_index const& rhs) const BOOST_NOEXCEPT {
return !(*this == rhs);
}
bool operator < (type_index const& rhs) const BOOST_NOEXCEPT {
#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
return std::strcmp(pinfo_->name(), rhs.pinfo_->name()) < 0;
#else
return before(rhs);
#endif
}
bool operator > (type_index const& rhs) const 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 {
#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
return !std::strcmp(pinfo_->name(), rhs.name());
#else
return *pinfo_ == rhs;
#endif
}
bool operator != (stl_type_info const& rhs) const BOOST_NOEXCEPT {
return !(*this == rhs);
}
bool operator < (stl_type_info const& rhs) const BOOST_NOEXCEPT {
#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
return std::strcmp(pinfo_->name(), rhs.name()) < 0;
#else
return !!pinfo_->before(rhs);
#endif
}
bool operator > (stl_type_info const& rhs) const BOOST_NOEXCEPT {
#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
return std::strcmp(pinfo_->name(), rhs.name()) > 0;
#else
return !!rhs.before(*pinfo_);
#endif
}
bool operator <= (stl_type_info const& rhs) const BOOST_NOEXCEPT {
return !(*this > rhs);
}
bool operator >= (stl_type_info const& rhs) const BOOST_NOEXCEPT {
return !(*this < rhs);
}
#endif // BOOST_TYPE_INDEX_DOXYGEN_INVOKED
/// 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 pinfo_->hash_code();
#else
return boost::hash_range(name(), name() + std::strlen(name()));
#endif
}
};
#ifndef BOOST_TYPE_INDEX_DOXYGEN_INVOKED
/* *************** type_index free functions ******************* */
inline bool operator == (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT {
return rhs == lhs; // Operation is commutative
}
inline bool operator != (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT {
return rhs != lhs; // Operation is commutative
}
inline bool operator < (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT {
return rhs > lhs;
}
inline bool operator > (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT {
return rhs < lhs;
}
inline bool operator <= (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT {
return rhs >= lhs;
}
inline bool operator >= (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT {
return rhs <= lhs;
}
#endif // BOOST_TYPE_INDEX_DOXYGEN_INVOKED
#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
#undef BOOST_CLASSINFO_COMPARE_BY_NAMES
#endif
/// @endcond
/// Function, to get type_index for a type T. Strips const, volatile and & modifiers from T.
template <class T>
inline type_index type_id() BOOST_NOEXCEPT {
return type_index::construct<T>();
}
/// Function for constructing type_index 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 type_index type_id_with_cvr() BOOST_NOEXCEPT {
return type_index::construct_with_cvr<T>();
}
/// Function, that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index.
/// 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 type_index type_id_rtti_only(T& rtti_val) BOOST_NOEXCEPT {
return type_index::construct_rtti_only(rtti_val);
}
/// Function, that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index.
/// 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 type_index type_id_rtti_only(T* rtti_val) {
return type_index::construct_rtti_only(rtti_val);
}
/* *************** type_index free functions ******************* */
/// @cond
#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();
}
/// @endcond
#endif // BOOST_NO_RTTI
} // namespace boost
#endif // BOOST_TYPE_INDEX_TYPE_INDEX_IMPL_HPP

View File

@@ -1,70 +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_MINIMAL_HPP
#define BOOST_TYPE_INDEX_TYPE_INDEX_MINIMAL_HPP
// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
# pragma once
#endif
/// \file type_index_minimal.hpp
/// \brief This is the header that required for ussage of boost::type_index with/without RTTI.
///
/// It includes only the minamally required headers and does the 'typedef template_index type_index;'
/// when RTTI is disabled.
#include <boost/config.hpp>
#if !defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NORTTI_COMPATIBILITY)
# include <boost/type_index/type_index_impl.hpp>
#else
# include <boost/type_index/template_index_impl.hpp>
# include <boost/static_assert.hpp>
namespace boost {
typedef template_index type_index;
template <class T>
inline type_index type_id() BOOST_NOEXCEPT {
return template_index::construct<T>();
}
template <class T>
inline type_index type_id_with_cvr() BOOST_NOEXCEPT {
return template_index::construct_with_cvr<T>();
}
template <class T>
inline type_index 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 type_index();
}
template <class T>
inline type_index type_id_rtti_only(T* rtti_val) {
BOOST_STATIC_ASSERT_MSG(sizeof(T) && false, "boost::type_id_rtti_only(T*) requires RTTI");
return type_index();
}
} // namespace boost
#endif // BOOST_NO_RTTI
#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
/// \def BOOST_TYPE_INDEX_FORCE_NORTTI_COMPATIBILITY
/// Define the BOOST_TYPE_INDEX_FORCE_NORTTI_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_NORTTI_COMPATIBILITY
#endif // BOOST_TYPE_INDEX_DOXYGEN_INVOKED
#endif // BOOST_TYPE_INDEX_TYPE_INDEX_MINIMAL_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.
# Copyright 2011-2023 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)
@@ -10,7 +10,8 @@ import doxygen ;
doxygen autodoc
:
[ glob ../../../boost/type_index.hpp ]
[ glob ../../../boost/type_index/* ]
[ glob ../../../boost/type_index/*.hpp ]
[ glob ../../../boost/type_index/runtime_cast/*.hpp ]
:
<doxygen:param>EXTRACT_ALL=NO
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
@@ -18,20 +19,14 @@ doxygen autodoc
<doxygen:param>ENABLE_PREPROCESSING=YES
<doxygen:param>EXPAND_ONLY_PREDEF=YES
<doxygen:param>MACRO_EXPANSION=YES
<doxygen:param>"PREDEFINED=\"insert_const_ref_type= const T&\" \\
<doxygen:param>"PREDEFINED=\"stl_type_info=std::type_info\" \\
\"BOOST_TYPE_INDEX_DOXYGEN_INVOKED\" \\
\"BOOST_RV_REF(T)=T &&\" \\
\"BOOST_RV_REF_BEG=\" \\
\"BOOST_RV_REF_END=&&\" \\
\"BOOST_CLASSINFO_COMPARISON_NOEXCEPT=\" \\
\"BOOST_COPY_ASSIGN_REF(T)=const T &\" \\
\"BOOST_RV_REF_2_TEMPL_ARGS(T,a,b)=T<a, b> &&\" \\
\"BOOST_RV_REF_3_TEMPL_ARGS(T,a,b,c)=T<a,b,c>T<a,b,c> &&\" \\
\"BOOST_FWD_REF(a)=a &&\""
\"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
@@ -39,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-2023 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-2023 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-2023 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-2023 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

@@ -0,0 +1,76 @@
// Copyright 2013-2023 Antony Polukhin
// Distributed under the Boost Software License, Version 1.0.
// (See the accompanying file LICENSE_1_0.txt
// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
//[type_index_exact_type_match_example
/*`
The following example shows that `type_index` (and `type_info`) is able to store the exact type,
without stripping const, volatile and references. Example works with and without RTTI.
In this example we'll create a class that stores a pointer to function and remembers the exact type of the
parameter the function accepts. When the call to the bound function is made, he actual input parameter
type is checked against the stored parameter type and an exception is thrown in case of mismatch.
*/
#include <boost/type_index.hpp>
#include <iostream>
#include <stdexcept>
#include <cstdlib>
//<-
// Making `#include <cassert>` visible in docs, while actually using hand-made check
// instead of `assert`. This is required to verify correct behavior even if NDEBUG
// is defined and to avoid `unused local variable` warnings with defined NDEBUG.
//
// 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::typeindex::type_index exact_param_t_;
public:
template <class ParamT>
type_erased_unary_function(void(*ptr)(ParamT))
: function_ptr_(reinterpret_cast<void*>(ptr)) // ptr - is a pointer to function returning `void` and accepting parameter of type `ParamT`
, exact_param_t_(boost::typeindex::type_id_with_cvr<ParamT>())
{}
template <class ParamT>
void call(ParamT v) {
if (exact_param_t_ != boost::typeindex::type_id_with_cvr<ParamT>()) {
throw std::runtime_error("Incorrect `ParamT`");
}
return (reinterpret_cast<void(*)(ParamT)>(function_ptr_))(v);
}
};
void foo(int){}
int main() {
type_erased_unary_function func(&foo);
func.call(100); // OK, `100` has type `int`
try {
int i = 100;
// An attempt to convert stored function to a function accepting reference
func.call<int&>(i); // Will throw, because types `int&` and `int` mismatch
assert(false);
} catch (const std::runtime_error& /*e*/) {}
}
//] [/type_index_exact_type_match_example]

47
examples/inheritance.cpp Normal file
View File

@@ -0,0 +1,47 @@
// Copyright 2013-2023 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() };
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-2023 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()
virtual ~A()
{}
};
struct B {
BOOST_TYPE_INDEX_REGISTER_RUNTIME_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-2023 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-2023 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-2023 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-2023 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() 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() 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) noexcept {
return type_index::type_id_runtime(runtime_val);
}
}} // namespace boost::typeindex
#endif // BOOST_TYPE_INDEX_HPP

View File

@@ -0,0 +1,204 @@
//
// Copyright 2013-2023 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 <type_traits>
#include <boost/container_hash/hash.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 {
public:
ctti_data() = delete;
ctti_data(const ctti_data&) = delete;
ctti_data& operator=(const ctti_data&) = delete;
};
} // namespace detail
/// Helper method for getting detail::ctti_data of a template parameter T.
template <class T>
inline const detail::ctti_data& ctti_construct() 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 noexcept;
BOOST_CXX14_CONSTEXPR inline explicit ctti_type_index(const char* data) noexcept
: data_(data)
{}
public:
typedef detail::ctti_data type_info_t;
BOOST_CXX14_CONSTEXPR inline ctti_type_index() noexcept
: data_(boost::detail::ctti<void>::n())
{}
inline ctti_type_index(const type_info_t& data) noexcept
: data_(reinterpret_cast<const char*>(&data))
{}
inline const type_info_t& type_info() const noexcept;
BOOST_CXX14_CONSTEXPR inline const char* raw_name() const noexcept;
BOOST_CXX14_CONSTEXPR inline const char* name() const noexcept;
inline std::string pretty_name() const;
inline std::size_t hash_code() const noexcept;
BOOST_CXX14_CONSTEXPR inline bool equal(const ctti_type_index& rhs) const noexcept;
BOOST_CXX14_CONSTEXPR inline bool before(const ctti_type_index& rhs) const noexcept;
template <class T>
BOOST_CXX14_CONSTEXPR inline static ctti_type_index type_id() noexcept;
template <class T>
BOOST_CXX14_CONSTEXPR inline static ctti_type_index type_id_with_cvr() noexcept;
template <class T>
inline static ctti_type_index type_id_runtime(const T& variable) noexcept;
};
inline const ctti_type_index::type_info_t& ctti_type_index::type_info() const noexcept {
return *reinterpret_cast<const detail::ctti_data*>(data_);
}
BOOST_CXX14_CONSTEXPR inline bool ctti_type_index::equal(const ctti_type_index& rhs) const 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 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() noexcept {
typedef typename std::remove_reference<T>::type no_ref_t;
typedef typename std::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() 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) noexcept {
return variable.boost_type_index_type_id_runtime_();
}
BOOST_CXX14_CONSTEXPR inline const char* ctti_type_index::raw_name() const noexcept {
return data_;
}
BOOST_CXX14_CONSTEXPR inline const char* ctti_type_index::name() const noexcept {
return data_;
}
inline std::size_t ctti_type_index::get_raw_name_length() const noexcept {
return std::strlen(raw_name() + detail::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 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,349 @@
//
// Copyright 2012-2023 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 <boost/config.hpp>
#include <cstring>
#include <type_traits>
#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
/// @endcond
namespace boost { namespace typeindex { namespace detail {
struct ctti_skip {
std::size_t size_at_begin;
std::size_t size_at_end;
const char* until_runtime;
std::size_t until_runtime_length;
};
template <std::size_t N>
constexpr ctti_skip make_ctti_skip(std::size_t size_at_begin,
std::size_t size_at_end,
bool more_at_runtime,
const char (&until_runtime)[N])
{
return ctti_skip{size_at_begin, size_at_end, until_runtime, more_at_runtime ? N - 1 : 0};
}
template <std::size_t N>
constexpr ctti_skip make_ctti_skip(std::size_t size_at_begin,
std::size_t size_at_end,
const char (&until_runtime)[N])
{
return ctti_skip{size_at_begin, size_at_end, until_runtime, N - 1};
}
#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)
constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip 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
constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(40, 10, ""); }
#elif defined(_MSC_VER) && !defined(__clang__) && !defined (BOOST_NO_CXX11_NOEXCEPT)
// sizeof("const char *__cdecl boost::detail::ctti<") - 1, sizeof(">::n(void) noexcept") - 1
constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(40, 19, ""); }
#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"
constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(39, 1, "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
constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(39, 6, ""); }
#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
constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(39, 1, "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
constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(58, 1, ""); }
#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
constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(57, 1, ""); }
#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
constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(81, 1, ""); }
#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
constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(80, 1, ""); }
#elif defined(__GNUC__) && defined(BOOST_NO_CXX14_CONSTEXPR)
// sizeof("static const char* boost::detail::ctti<T>::n() [with T = ") - 1, sizeof("]") - 1
constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(57, 1, ""); }
#elif defined(__ghs__)
// sizeof("static const char *boost::detail::ctti<T>::n() [with T = ") - 1, sizeof("]") - 1
constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(57, 1, ""); }
#else
// Deafult code for other platforms... Just skip nothing!
constexpr ctti_skip skip() noexcept { return detail::make_ctti_skip(0, 0, ""); }
#endif
template <bool Condition>
BOOST_CXX14_CONSTEXPR inline void assert_compile_time_legths() noexcept {
static_assert(
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() noexcept {
static_assert(
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) 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<class ForwardIterator1, class ForwardIterator2>
BOOST_CXX14_CONSTEXPR inline ForwardIterator1 constexpr_search(
ForwardIterator1 first1,
ForwardIterator1 last1,
ForwardIterator2 first2,
ForwardIterator2 last2) 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) 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) 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) noexcept {
const char* const it = detail::constexpr_search(
begin, begin + ArrayLength,
skip().until_runtime, skip().until_runtime + skip().until_runtime_length
);
return (it == begin + ArrayLength ? begin : it + skip().until_runtime_length);
}
template <unsigned int ArrayLength>
BOOST_CXX14_CONSTEXPR inline const char* skip_begining(const char* begin) noexcept {
detail::assert_compile_time_legths<(ArrayLength > skip().size_at_begin + skip().size_at_end)>();
return skip().until_runtime_length
? detail::skip_begining_runtime<ArrayLength - skip().size_at_begin>(begin + skip().size_at_begin)
: begin + skip().size_at_begin
;
}
#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() 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...> ) noexcept {
return ::boost::typeindex::detail::cstring<s<Indexes>()...>::data_;
}
template <unsigned int D = 0> // `D` means `Dummy`
constexpr static const char* n() 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::skip().size_at_begin + boost::typeindex::detail::skip().size_at_end + sizeof("const *") - 1)
>();
static_assert(!boost::typeindex::detail::skip().until_runtime_length, "Skipping for GCC in C++14 mode is unsupported");
typedef typename boost::typeindex::detail::make_index_seq_impl<
boost::typeindex::detail::skip().size_at_begin,
size - sizeof("const *") + 1 - boost::typeindex::detail::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() 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-2023 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*) noexcept {
return boost::typeindex::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 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-2023 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*) 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 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,50 @@
//
// 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 <type_traits>
#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(), std::is_base_of<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,58 @@
//
// 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 <type_traits>
#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, std::integral_constant<bool, true>) noexcept {
return u;
}
template<typename T, typename U>
T const* runtime_cast_impl(U const* u, std::integral_constant<bool, true>) noexcept {
return u;
}
template<typename T, typename U>
T* runtime_cast_impl(U* u, std::integral_constant<bool, false>) 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, std::integral_constant<bool, false>) 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,73 @@
//
// 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>
#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 nullptr.
template<typename T, typename U>
T runtime_cast(U* u) noexcept {
typedef typename std::remove_pointer<T>::type impl_type;
return detail::runtime_cast_impl<impl_type>(u, std::is_base_of<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 nullptr.
template<typename T, typename U>
T runtime_cast(U const* u) noexcept {
typedef typename std::remove_pointer<T>::type impl_type;
return detail::runtime_cast_impl<impl_type>(u, std::is_base_of<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 nullptr.
template<typename T, typename U>
T* runtime_pointer_cast(U* u) noexcept {
return detail::runtime_cast_impl<T>(u, std::is_base_of<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 nullptr.
template<typename T, typename U>
T const* runtime_pointer_cast(U const* u) noexcept {
return detail::runtime_cast_impl<T>(u, std::is_base_of<T, U>());
}
}} // namespace boost::typeindex
#endif // BOOST_TYPE_INDEX_RUNTIME_CAST_POINTER_CAST_HPP

View File

@@ -0,0 +1,65 @@
//
// 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/type_index/runtime_cast/detail/runtime_cast_impl.hpp>
#include <boost/throw_exception.hpp>
#include <memory>
#include <type_traits>
#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 BOOST_SYMBOL_VISIBLE 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 std::add_lvalue_reference<T>::type runtime_cast(U& u) {
typedef typename std::remove_reference<T>::type impl_type;
impl_type* value = detail::runtime_cast_impl<impl_type>(
std::addressof(u), std::is_base_of<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 std::add_lvalue_reference<const T>::type runtime_cast(U const& u) {
typedef typename std::remove_reference<T>::type impl_type;
impl_type* value = detail::runtime_cast_impl<impl_type>(
std::addressof(u), std::is_base_of<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,141 @@
//
// 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>
#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 boost::typeindex::type_id<T>();
}
template <class Self>
constexpr const void* find_instance(boost::typeindex::type_index const&, const Self*) noexcept {
return nullptr;
}
template <class Base, class... OtherBases, class Self>
const void* find_instance(boost::typeindex::type_index const& idx, const Self* self) noexcept {
if (const void* ptr = self->Base::boost_type_index_find_instance_(idx)) {
return ptr;
}
return boost::typeindex::detail::find_instance<OtherBases...>(idx, self);
}
}}} // namespace boost::typeindex::detail
/// \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()
/// virtual ~base1();
/// };
///
/// struct base2 {
/// BOOST_TYPE_INDEX_REGISTER_RUNTIME_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(...) \
BOOST_TYPE_INDEX_REGISTER_CLASS \
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(__VA_ARGS__)
/// \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()
/// virtual ~base1();
/// };
///
/// struct base2 {
/// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST()
/// 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(...) \
virtual void const* boost_type_index_find_instance_(boost::typeindex::type_index const& idx) const noexcept { \
if(idx == boost::typeindex::detail::runtime_class_construct_type_id(this)) \
return this; \
return boost::typeindex::detail::find_instance<__VA_ARGS__>(idx, this); \
}
/// \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.
/// \deprecated Just remove and use BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS() or BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST()
#define BOOST_TYPE_INDEX_NO_BASE_CLASS /**/
#endif // BOOST_TYPE_INDEX_RUNTIME_CAST_REGISTER_RUNTIME_CLASS_HPP

View File

@@ -0,0 +1,45 @@
//
// 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 <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(), std::is_base_of<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,234 @@
//
// Copyright 2013-2023 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 <type_traits>
#include <boost/throw_exception.hpp>
#include <boost/core/demangle.hpp>
#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() noexcept
: data_(&typeid(void))
{}
inline stl_type_index(const type_info_t& data) noexcept
: data_(&data)
{}
inline const type_info_t& type_info() const noexcept;
inline const char* raw_name() const noexcept;
inline const char* name() const noexcept;
inline std::string pretty_name() const;
inline std::size_t hash_code() const noexcept;
inline bool equal(const stl_type_index& rhs) const noexcept;
inline bool before(const stl_type_index& rhs) const noexcept;
template <class T>
inline static stl_type_index type_id() noexcept;
template <class T>
inline static stl_type_index type_id_with_cvr() noexcept;
template <class T>
inline static stl_type_index type_id_runtime(const T& value) noexcept;
};
inline const stl_type_index::type_info_t& stl_type_index::type_info() const noexcept {
return *data_;
}
inline const char* stl_type_index::raw_name() const noexcept {
#ifdef _MSC_VER
return data_->raw_name();
#else
return data_->name();
#endif
}
inline const char* stl_type_index::name() const 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 noexcept {
return data_->hash_code();
}
/// @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 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 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() noexcept {
typedef typename std::remove_reference<T>::type no_ref_t;
typedef typename std::remove_cv<no_ref_t>::type no_cvr_t;
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() noexcept {
typedef typename std::conditional<
std::is_reference<T>::value || std::is_const<T>::value || std::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) noexcept {
#ifdef BOOST_NO_RTTI
return value.boost_type_index_type_id_runtime_();
#else
return typeid(value);
#endif
}
}} // namespace boost::typeindex
#endif // BOOST_TYPE_INDEX_STL_TYPE_INDEX_HPP

View File

@@ -0,0 +1,280 @@
//
// Copyright 2013-2023 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>
#include <type_traits>
#include <iosfwd> // for std::basic_ostream
#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 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 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 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 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 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 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 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() 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() 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) 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) 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) 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) 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) 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) 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) 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) noexcept {
return Derived(lhs) == rhs;
}
template <class Derived, class TypeInfo>
inline bool operator < (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) noexcept {
return Derived(lhs) < rhs;
}
template <class Derived, class TypeInfo>
inline bool operator > (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) noexcept {
return rhs < Derived(lhs);
}
template <class Derived, class TypeInfo>
inline bool operator <= (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) noexcept {
return !(Derived(lhs) > rhs);
}
template <class Derived, class TypeInfo>
inline bool operator >= (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) noexcept {
return !(Derived(lhs) < rhs);
}
template <class Derived, class TypeInfo>
inline bool operator != (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) noexcept {
return !(Derived(lhs) == rhs);
}
template <class Derived, class TypeInfo>
inline bool operator == (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) noexcept {
return lhs == Derived(rhs);
}
template <class Derived, class TypeInfo>
inline bool operator < (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) noexcept {
return lhs < Derived(rhs);
}
template <class Derived, class TypeInfo>
inline bool operator > (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) noexcept {
return Derived(rhs) < lhs;
}
template <class Derived, class TypeInfo>
inline bool operator <= (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) noexcept {
return !(lhs > Derived(rhs));
}
template <class Derived, class TypeInfo>
inline bool operator >= (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) noexcept {
return !(lhs < Derived(rhs));
}
template <class Derived, class TypeInfo>
inline bool operator != (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) 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
/// 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_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) noexcept {
return static_cast<Derived const&>(lhs).hash_code();
}
}} // namespace boost::typeindex
#endif // BOOST_TYPE_INDEX_TYPE_INDEX_FACADE_HPP

37
index.html Normal file
View File

@@ -0,0 +1,37 @@
<!DOCTYPE html>
<!--
Copyright 2014-2023 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)
boost-no-inspect
-->
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="refresh" content="0; url=../../doc/html/boost_typeindex.html">
<title>Boost.TypeIndex</title>
<style>
body {
background: #fff;
color: #000;
}
a {
color: #00f;
text-decoration: none;
}
</style>
</head>
<body>
<p>
Automatic redirection failed, please go to
<a href="../../doc/html/boost_typeindex.html">../../doc/html/boost_typeindex.html</a>
</p>
<p>
&copy; 2014-2023 Antony Polukhin
</p>
</body>
</html>

View File

@@ -1,140 +0,0 @@
[library Boost.TypeIndex
[quickbook 1.5]
[version 1.0]
[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 was designed to work around all those issues.
[note `T` means type here. Think of it as of `T` in `template <class T>` ]
[warning This library is not accepted to Boost, it is currrently waiting for review. ]
[endsect]
[section Getting started]
`boost::type_index` can be used as a drop-in replacement for `std::type_index`, but
it usually does not require RTTI. It provides the full set of comparison operators,
hashing functions and ostream operators, so it can be used with any container class.
To start using it:
* Replace `std::type_index`, `const std::type_info&`, `const std::type_info*` with `boost::type_index`.
* If you do not want to save `const`, `volatile`, `&` and `&&`:
* Use `boost::type_id<T>()` instead of `typeid(T)`, `&typeid(T)`.
* If you want to save `const`, `volatile`, `&` and `&&`:
* Use `boost::type_id_with_cvr<T>()` instead of `typeid(T)`, `&typeid(T)`.
* To get nice human readable names, use the `name_demangled()` member function:
``
#include <boost/type_index/type_index_minimal.hpp>
type_index ti = type_id<T>();
std::string nice_name
= ti.name_demangled();
...
std::string nice_name_with_const_volatile_ref
= type_id_with_cvr<ParamT&>().name_demangled();
``
[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_index` uses the `BOOST_CURRENT_FUNCTION` macro which could lead to code bloat, so prefer using `type_index` 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()` for `type_index` do usually require dynamic memory allocation and some computations, so they are not recomended for usage in performance critical sections.
* Calls to `std::string name_demangled()` for `template_index` only require a single `std::strlen` call and are considerably faster than `std::string name_demangled()` for `type_index`.
[endsect]
[section Code bloat]
Without RTTI TypeIndex library will switch from using `boost::type_index` class to `boost::template_index`. `boost::template_index` uses the `BOOST_CURRENT_FUNCTION` 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 sucessfully work on MSVC2010, GCC-4.5, Clang-2.9. If your compiler is not in a list of tested compilers, you shall 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 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::detail::ctti<int>::n()`
# 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::detail::ctti<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_CTTI_BEGIN_SKIP` and `BOOST_TYPE_INDEX_CTTI_END_SKIP` numbers.
Consider the following example:
With `BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` and `BOOST_TYPE_INDEX_CTTI_END_SKIP` set to `0`, `boost::detail::ctti<int>::n()` 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_NORTTI_COMPATIBILITY` macro. This would lead to usage of `boost::template_index` instead of `boost::type_index` class.
[note Do not forget to rebuild *all* the projects with `BOOST_TYPE_INDEX_FORCE_NORTTI_COMPATIBILITY` macro defined ]
You must know that linking RTTI on and RTTI off binaries may succeed even without defining the `BOOST_TYPE_INDEX_FORCE_NORTTI_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.
[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_index_minimal.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,58 +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_exact_type_match_example
/*`
The following example shows that `boost::template_index` 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.
*/
#include <boost/type_index.hpp>
#include <iostream>
#include <stdexcept>
#include <cassert>
class type_erased_unary_function {
void* function_ptr_;
boost::template_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::template_id_with_cvr<ParamT>())
{}
template <class ParamT>
void call(ParamT v) {
if (exact_param_t_ != boost::template_id_with_cvr<ParamT>()) {
throw std::runtime_error("Incorrect `ParamT`");
}
return (reinterpret_cast<void(*)(ParamT)>(function_ptr_))(v);
}
};
void foo(int){}
int main() {
type_erased_unary_function func(&foo);
func.call(100); // OK, `100` has type `int`
try {
int i = 100;
// An attempt to convert stored function to a function accepting reference
func.call<int&>(i); // Will throw, because types `int&` and `int` missmatch
assert(false);
} catch (const std::runtime_error& /*e*/) {}
}
//] [/type_index_exact_type_match_example]

View File

@@ -1,33 +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_index` 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_index_minimal.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_minimal.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,63 +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_NORTTI_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 $(nortti) ;
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 $(nortti) ;
# 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_minimal.cpp $(tlib) ]
[ run testing_minimal_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 ]
[ 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,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 template_index_test_module
#include <boost/test/unit_test.hpp>
// Byapssing internal assertion for correct header inclusion
#define BOOST_TYPE_INDEX_TYPE_INDEX_MINIMAL_HPP
#include <boost/type_index/template_index_impl.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.
//
// 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_minimal.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,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 testing_both_test_module
#include <boost/test/unit_test.hpp>
#include <boost/type_index/type_index_minimal.hpp>
namespace my_namespace1 {
class my_class{};
}
namespace my_namespace2 {
class my_class{};
}
#include "type_index_tests.ipp"

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,25 +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>
// Byapssing internal assertion for correct header inclusion
#define BOOST_TYPE_INDEX_TYPE_INDEX_MINIMAL_HPP
#include <boost/type_index/type_index_impl.hpp>
namespace my_namespace1 {
class my_class{};
}
namespace my_namespace2 {
class my_class{};
}
#include "type_index_tests.ipp"

View File

@@ -1,301 +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": "11"
}

9
patched/README.md Normal file
View File

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

View File

@@ -1,239 +0,0 @@
// See http://www.boost.org/libs/any for Documentation.
#ifndef BOOST_ANY_INCLUDED
#define BOOST_ANY_INCLUDED
// what: variant type boost::any
// who: contributed by Kevlin Henney,
// with features contributed and bugs found by
// Ed Brey, Mark Rodgers, Peter Dimov, and James Curran
// when: July 2001
// where: tested with BCC 5.5, MSVC 6.0, and g++ 2.95
#include <algorithm>
#include <typeinfo>
#include "boost/config.hpp"
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/is_reference.hpp>
#include <boost/throw_exception.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_index.hpp>
namespace boost
{
class any
{
public: // structors
any()
: content(0)
{
}
template<typename ValueType>
any(const ValueType & value)
: content(new holder<ValueType>(value))
{
}
any(const any & other)
: content(other.content ? other.content->clone() : 0)
{
}
~any()
{
delete content;
}
public: // modifiers
any & swap(any & rhs)
{
std::swap(content, rhs.content);
return *this;
}
template<typename ValueType>
any & operator=(const ValueType & rhs)
{
any(rhs).swap(*this);
return *this;
}
any & operator=(any rhs)
{
rhs.swap(*this);
return *this;
}
public: // queries
bool empty() const
{
return !content;
}
type_index type() const
{
return content ? content->type() : type_id<void>();
}
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
private: // types
#else
public: // types (public so any_cast can be non-friend)
#endif
class placeholder
{
public: // structors
virtual ~placeholder()
{
}
public: // queries
virtual type_index type() const = 0;
virtual placeholder * clone() const = 0;
};
template<typename ValueType>
class holder : public placeholder
{
public: // structors
holder(const ValueType & value)
: held(value)
{
}
public: // queries
virtual type_index type() const
{
return type_id<ValueType>();
}
virtual placeholder * clone() const
{
return new holder(held);
}
public: // representation
ValueType held;
private: // intentionally left unimplemented
holder & operator=(const holder &);
};
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
private: // representation
template<typename ValueType>
friend ValueType * any_cast(any *);
template<typename ValueType>
friend ValueType * unsafe_any_cast(any *);
#else
public: // representation (public so any_cast can be non-friend)
#endif
placeholder * content;
};
class bad_any_cast : public std::bad_cast
{
public:
virtual const char * what() const throw()
{
return "boost::bad_any_cast: "
"failed conversion using boost::any_cast";
}
};
template<typename ValueType>
ValueType * any_cast(any * operand)
{
return operand &&
operand->type() == type_id<ValueType>()
? &static_cast<any::holder<ValueType> *>(operand->content)->held
: 0;
}
template<typename ValueType>
inline const ValueType * any_cast(const any * operand)
{
return any_cast<ValueType>(const_cast<any *>(operand));
}
template<typename ValueType>
ValueType any_cast(any & operand)
{
typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref;
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// If 'nonref' is still reference type, it means the user has not
// specialized 'remove_reference'.
// Please use BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION macro
// to generate specialization of remove_reference for your class
// See type traits library documentation for details
BOOST_STATIC_ASSERT(!is_reference<nonref>::value);
#endif
nonref * result = any_cast<nonref>(&operand);
if(!result)
boost::throw_exception(bad_any_cast());
return *result;
}
template<typename ValueType>
inline ValueType any_cast(const any & operand)
{
typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref;
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// The comment in the above version of 'any_cast' explains when this
// assert is fired and what to do.
BOOST_STATIC_ASSERT(!is_reference<nonref>::value);
#endif
return any_cast<const nonref &>(const_cast<any &>(operand));
}
// Note: The "unsafe" versions of any_cast are not part of the
// public interface and may be removed at any time. They are
// required where we know what type is stored in the any and can't
// use type_id<>() comparison, e.g., when our types may travel across
// different shared libraries.
template<typename ValueType>
inline ValueType * unsafe_any_cast(any * operand)
{
return &static_cast<any::holder<ValueType> *>(operand->content)->held;
}
template<typename ValueType>
inline const ValueType * unsafe_any_cast(const any * operand)
{
return unsafe_any_cast<ValueType>(const_cast<any *>(operand));
}
}
// Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
//
// 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)
#endif

View File

@@ -0,0 +1,151 @@
From b77c0af6af8bc4797defc3627878acc3cf7a6f39 Mon Sep 17 00:00:00 2001
From: Antony Polukhin <antoshkka@gmail.com>
Date: Thu, 20 Feb 2014 17:57:24 +0400
Subject: [PATCH] detail/sp_typeinfo.hpp now uses TypeIndex
---
include/boost/detail/sp_typeinfo.hpp | 123 +++--------------------------------
1 file changed, 8 insertions(+), 115 deletions(-)
diff --git a/include/boost/detail/sp_typeinfo.hpp b/include/boost/detail/sp_typeinfo.hpp
index 43fae78..fbdf86d 100644
--- a/include/boost/detail/sp_typeinfo.hpp
+++ b/include/boost/detail/sp_typeinfo.hpp
@@ -10,126 +10,19 @@
// detail/sp_typeinfo.hpp
//
// Copyright 2007 Peter Dimov
+// Copyright 2014 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#include <boost/config.hpp>
+#include <boost/type_index.hpp>
+namespace boost { namespace detail {
+
+typedef boost::typeind::type_info sp_typeinfo;
+
+}} // namespace boost::detail
-#if defined( BOOST_NO_TYPEID )
-
-#include <boost/current_function.hpp>
-#include <functional>
-
-namespace boost
-{
-
-namespace detail
-{
-
-class sp_typeinfo
-{
-private:
-
- sp_typeinfo( sp_typeinfo const& );
- sp_typeinfo& operator=( sp_typeinfo const& );
-
- char const * name_;
-
-public:
-
- explicit sp_typeinfo( char const * name ): name_( name )
- {
- }
-
- bool operator==( sp_typeinfo const& rhs ) const
- {
- return this == &rhs;
- }
-
- bool operator!=( sp_typeinfo const& rhs ) const
- {
- return this != &rhs;
- }
-
- bool before( sp_typeinfo const& rhs ) const
- {
- return std::less< sp_typeinfo const* >()( this, &rhs );
- }
-
- char const* name() const
- {
- return name_;
- }
-};
-
-template<class T> struct sp_typeid_
-{
- static sp_typeinfo ti_;
-
- static char const * name()
- {
- return BOOST_CURRENT_FUNCTION;
- }
-};
-
-#if defined(__SUNPRO_CC)
-// see #4199, the Sun Studio compiler gets confused about static initialization
-// constructor arguments. But an assignment works just fine.
-template<class T> sp_typeinfo sp_typeid_< T >::ti_ = sp_typeid_< T >::name();
-#else
-template<class T> sp_typeinfo sp_typeid_< T >::ti_(sp_typeid_< T >::name());
-#endif
-
-template<class T> struct sp_typeid_< T & >: sp_typeid_< T >
-{
-};
-
-template<class T> struct sp_typeid_< T const >: sp_typeid_< T >
-{
-};
-
-template<class T> struct sp_typeid_< T volatile >: sp_typeid_< T >
-{
-};
-
-template<class T> struct sp_typeid_< T const volatile >: sp_typeid_< T >
-{
-};
-
-} // namespace detail
-
-} // namespace boost
-
-#define BOOST_SP_TYPEID(T) (boost::detail::sp_typeid_<T>::ti_)
-
-#else
-
-#include <typeinfo>
-
-namespace boost
-{
-
-namespace detail
-{
-
-#if defined( BOOST_NO_STD_TYPEINFO )
-
-typedef ::type_info sp_typeinfo;
-
-#else
-
-typedef std::type_info sp_typeinfo;
-
-#endif
-
-} // namespace detail
-
-} // namespace boost
-
-#define BOOST_SP_TYPEID(T) typeid(T)
-
-#endif
+#define BOOST_SP_TYPEID(T) (boost::typeind::type_id<T>().type_info())
#endif // #ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED
--
1.8.5.3

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,135 +0,0 @@
#ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED
#define BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
// detail/sp_typeinfo.hpp
//
// Copyright 2007 Peter Dimov
//
// 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>
#if defined( BOOST_NO_TYPEID )
#include <boost/current_function.hpp>
#include <functional>
namespace boost
{
namespace detail
{
class sp_typeinfo
{
private:
sp_typeinfo( sp_typeinfo const& );
sp_typeinfo& operator=( sp_typeinfo const& );
char const * name_;
public:
explicit sp_typeinfo( char const * name ): name_( name )
{
}
bool operator==( sp_typeinfo const& rhs ) const
{
return this == &rhs;
}
bool operator!=( sp_typeinfo const& rhs ) const
{
return this != &rhs;
}
bool before( sp_typeinfo const& rhs ) const
{
return std::less< sp_typeinfo const* >()( this, &rhs );
}
char const* name() const
{
return name_;
}
};
template<class T> struct sp_typeid_
{
static sp_typeinfo ti_;
static char const * name()
{
return BOOST_CURRENT_FUNCTION;
}
};
#if defined(__SUNPRO_CC)
// see #4199, the Sun Studio compiler gets confused about static initialization
// constructor arguments. But an assignment works just fine.
template<class T> sp_typeinfo sp_typeid_< T >::ti_ = sp_typeid_< T >::name();
#else
template<class T> sp_typeinfo sp_typeid_< T >::ti_(sp_typeid_< T >::name());
#endif
template<class T> struct sp_typeid_< T & >: sp_typeid_< T >
{
};
template<class T> struct sp_typeid_< T const >: sp_typeid_< T >
{
};
template<class T> struct sp_typeid_< T volatile >: sp_typeid_< T >
{
};
template<class T> struct sp_typeid_< T const volatile >: sp_typeid_< T >
{
};
} // namespace detail
} // namespace boost
#define BOOST_SP_TYPEID(T) (boost::detail::sp_typeid_<T>::ti_)
#else
#include <typeinfo>
namespace boost
{
namespace detail
{
#if defined( BOOST_NO_STD_TYPEINFO )
typedef ::type_info sp_typeinfo;
#else
typedef std::type_info sp_typeinfo;
#endif
} // namespace detail
} // namespace boost
#define BOOST_SP_TYPEID(T) typeid(T)
#endif
#endif // #ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED

View File

@@ -1,352 +0,0 @@
// Copyright (C) 2006 Tiago de Paula Peixoto <tiago@forked.de>
// Copyright (C) 2004 The Trustees of Indiana University.
//
// Use, modification and distribution is 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)
//
// Authors: Douglas Gregor
// Andrew Lumsdaine
// Tiago de Paula Peixoto
#ifndef BOOST_GRAPH_GRAPHML_HPP
#define BOOST_GRAPH_GRAPHML_HPP
#include <boost/config.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/any.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/graph/dll_import_export.hpp>
#include <boost/graph/graphviz.hpp> // for exceptions
#include <boost/type_index.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/find.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/property_tree/detail/xml_parser_utils.hpp>
#include <boost/throw_exception.hpp>
#include <exception>
#include <sstream>
namespace boost
{
/////////////////////////////////////////////////////////////////////////////
// Graph reader exceptions
/////////////////////////////////////////////////////////////////////////////
struct parse_error: public graph_exception
{
parse_error(const std::string& err) {error = err; statement = "parse error: " + error;}
virtual ~parse_error() throw() {}
virtual const char* what() const throw() {return statement.c_str();}
std::string statement;
std::string error;
};
class mutate_graph
{
public:
virtual ~mutate_graph() {}
virtual bool is_directed() const = 0;
virtual boost::any do_add_vertex() = 0;
virtual std::pair<boost::any,bool> do_add_edge(boost::any source, boost::any target) = 0;
virtual void
set_graph_property(const std::string& name, const std::string& value, const std::string& value_type) = 0;
virtual void
set_vertex_property(const std::string& name, boost::any vertex, const std::string& value, const std::string& value_type) = 0;
virtual void
set_edge_property(const std::string& name, boost::any edge, const std::string& value, const std::string& value_type) = 0;
};
template<typename MutableGraph>
class mutate_graph_impl : public mutate_graph
{
typedef typename graph_traits<MutableGraph>::vertex_descriptor vertex_descriptor;
typedef typename graph_traits<MutableGraph>::edge_descriptor edge_descriptor;
public:
mutate_graph_impl(MutableGraph& g, dynamic_properties& dp)
: m_g(g), m_dp(dp) { }
bool is_directed() const
{
return is_convertible<typename graph_traits<MutableGraph>::directed_category,
directed_tag>::value;
}
virtual any do_add_vertex()
{
return any(add_vertex(m_g));
}
virtual std::pair<any,bool> do_add_edge(any source, any target)
{
std::pair<edge_descriptor,bool> retval = add_edge(any_cast<vertex_descriptor>(source),
any_cast<vertex_descriptor>(target), m_g);
return std::make_pair(any(retval.first), retval.second);
}
virtual void
set_graph_property(const std::string& name, const std::string& value, const std::string& value_type)
{
bool type_found = false;
try
{
mpl::for_each<value_types>(put_property<MutableGraph,value_types>
(name, m_dp, m_g, value, value_type, m_type_names, type_found));
}
catch (bad_lexical_cast)
{
BOOST_THROW_EXCEPTION(
parse_error("invalid value \"" + value + "\" for key " +
name + " of type " + value_type));
}
if (!type_found)
{
BOOST_THROW_EXCEPTION(
parse_error("unrecognized type \"" + value_type +
"\" for key " + name));
}
}
virtual void
set_vertex_property(const std::string& name, any vertex, const std::string& value, const std::string& value_type)
{
bool type_found = false;
try
{
mpl::for_each<value_types>(put_property<vertex_descriptor,value_types>
(name, m_dp, any_cast<vertex_descriptor>(vertex),
value, value_type, m_type_names, type_found));
}
catch (bad_lexical_cast)
{
BOOST_THROW_EXCEPTION(
parse_error("invalid value \"" + value + "\" for key " +
name + " of type " + value_type));
}
if (!type_found)
{
BOOST_THROW_EXCEPTION(
parse_error("unrecognized type \"" + value_type +
"\" for key " + name));
}
}
virtual void
set_edge_property(const std::string& name, any edge, const std::string& value, const std::string& value_type)
{
bool type_found = false;
try
{
mpl::for_each<value_types>(put_property<edge_descriptor,value_types>
(name, m_dp, any_cast<edge_descriptor>(edge),
value, value_type, m_type_names, type_found));
}
catch (bad_lexical_cast)
{
BOOST_THROW_EXCEPTION(
parse_error("invalid value \"" + value + "\" for key " +
name + " of type " + value_type));
}
if (!type_found)
{
BOOST_THROW_EXCEPTION(
parse_error("unrecognized type \"" + value_type +
"\" for key " + name));
}
}
template <typename Key, typename ValueVector>
class put_property
{
public:
put_property(const std::string& name, dynamic_properties& dp, const Key& key,
const std::string& value, const std::string& value_type,
const char** type_names, bool& type_found)
: m_name(name), m_dp(dp), m_key(key), m_value(value),
m_value_type(value_type), m_type_names(type_names),
m_type_found(type_found) {}
template <class Value>
void operator()(Value)
{
if (m_value_type == m_type_names[mpl::find<ValueVector,Value>::type::pos::value])
{
put(m_name, m_dp, m_key, lexical_cast<Value>(m_value));
m_type_found = true;
}
}
private:
const std::string& m_name;
dynamic_properties& m_dp;
const Key& m_key;
const std::string& m_value;
const std::string& m_value_type;
const char** m_type_names;
bool& m_type_found;
};
protected:
MutableGraph& m_g;
dynamic_properties& m_dp;
typedef mpl::vector<bool, int, long, float, double, std::string> value_types;
static const char* m_type_names[];
};
template<typename MutableGraph>
const char* mutate_graph_impl<MutableGraph>::m_type_names[] = {"boolean", "int", "long", "float", "double", "string"};
void BOOST_GRAPH_DECL
read_graphml(std::istream& in, mutate_graph& g);
template<typename MutableGraph>
void
read_graphml(std::istream& in, MutableGraph& g, dynamic_properties& dp)
{
mutate_graph_impl<MutableGraph> mg(g,dp);
read_graphml(in, mg);
}
template <typename Types>
class get_type_name
{
public:
get_type_name(const type_index& 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 (type_id<Type>() == m_type)
m_type_name = m_type_names[mpl::find<Types,Type>::type::pos::value];
}
private:
const type_index m_type;
const char** m_type_names;
std::string &m_type_name;
};
template <typename Graph, typename VertexIndexMap>
void
write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index,
const dynamic_properties& dp, bool ordered_vertices=false)
{
typedef typename graph_traits<Graph>::directed_category directed_category;
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
using boost::property_tree::xml_parser::encode_char_entities;
BOOST_STATIC_CONSTANT(bool,
graph_is_directed =
(is_convertible<directed_category*, directed_tag*>::value));
out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
<< "<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd\">\n";
typedef mpl::vector<bool, short, unsigned short, int, unsigned int, long, unsigned long, long long, unsigned long long, float, double, long double, std::string> value_types;
const char* type_names[] = {"boolean", "int", "int", "int", "int", "long", "long", "long", "long", "float", "double", "double", "string"};
std::map<std::string, std::string> graph_key_ids;
std::map<std::string, std::string> vertex_key_ids;
std::map<std::string, std::string> edge_key_ids;
int key_count = 0;
// Output keys
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() == type_id<Graph*>())
graph_key_ids[i->first] = key_id;
else if (i->second->key() == type_id<vertex_descriptor>())
vertex_key_ids[i->first] = key_id;
else if (i->second->key() == 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() == type_id<Graph*>() ? "graph" : (i->second->key() == type_id<vertex_descriptor>() ? "node" : "edge")) << "\""
<< " attr.name=\"" << i->first << "\""
<< " attr.type=\"" << type_name << "\""
<< " />\n";
}
out << " <graph id=\"G\" edgedefault=\""
<< (graph_is_directed ? "directed" : "undirected") << "\""
<< " parse.nodeids=\"" << (ordered_vertices ? "canonical" : "free") << "\""
<< " parse.edgeids=\"canonical\" parse.order=\"nodesfirst\">\n";
// Output graph data
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
{
if (i->second->key() == 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.
out << " <data key=\"" << graph_key_ids[i->first] << "\">"
<< encode_char_entities(i->second->get_string(const_cast<Graph*>(&g))) << "</data>\n";
}
}
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
vertex_iterator v, v_end;
for (boost::tie(v, v_end) = vertices(g); v != v_end; ++v)
{
out << " <node id=\"n" << get(vertex_index, *v) << "\">\n";
// Output data
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
{
if (i->second->key() == type_id<vertex_descriptor>())
{
out << " <data key=\"" << vertex_key_ids[i->first] << "\">"
<< encode_char_entities(i->second->get_string(*v)) << "</data>\n";
}
}
out << " </node>\n";
}
typedef typename graph_traits<Graph>::edge_iterator edge_iterator;
edge_iterator e, e_end;
typename graph_traits<Graph>::edges_size_type edge_count = 0;
for (boost::tie(e, e_end) = edges(g); e != e_end; ++e)
{
out << " <edge id=\"e" << edge_count++ << "\" source=\"n"
<< get(vertex_index, source(*e, g)) << "\" target=\"n"
<< get(vertex_index, target(*e, g)) << "\">\n";
// Output data
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
{
if (i->second->key() == type_id<edge_descriptor>())
{
out << " <data key=\"" << edge_key_ids[i->first] << "\">"
<< encode_char_entities(i->second->get_string(*e)) << "</data>\n";
}
}
out << " </edge>\n";
}
out << " </graph>\n"
<< "</graphml>\n";
}
template <typename Graph>
void
write_graphml(std::ostream& out, const Graph& g, const dynamic_properties& dp,
bool ordered_vertices=false)
{
write_graphml(out, g, get(vertex_index, g), dp, ordered_vertices);
}
} // boost namespace
#endif // BOOST_GRAPH_GRAPHML_HPP

View File

@@ -1,858 +0,0 @@
//=======================================================================
// Copyright 2001 University of Notre Dame.
// Copyright 2003 Jeremy Siek
// Authors: Lie-Quan Lee, Jeremy Siek, and Douglas Gregor
//
// 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_GRAPHVIZ_HPP
#define BOOST_GRAPHVIZ_HPP
#include <boost/config.hpp>
#include <string>
#include <map>
#include <iostream>
#include <fstream>
#include <stdio.h> // for FILE
#include <boost/property_map/property_map.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/properties.hpp>
#include <boost/graph/subgraph.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/property_map/dynamic_property_map.hpp>
#include <boost/graph/overloading.hpp>
#include <boost/graph/dll_import_export.hpp>
#include <boost/spirit/include/classic_multi_pass.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/xpressive/xpressive_static.hpp>
#include <boost/foreach.hpp>
#include <boost/type_index.hpp>
namespace boost {
template <typename directed_category>
struct graphviz_io_traits {
static std::string name() {
return "digraph";
}
static std::string delimiter() {
return "->";
} };
template <>
struct graphviz_io_traits <undirected_tag> {
static std::string name() {
return "graph";
}
static std::string delimiter() {
return "--";
}
};
struct default_writer {
void operator()(std::ostream&) const {
}
template <class VorE>
void operator()(std::ostream&, const VorE&) const {
}
};
template <typename T>
inline std::string escape_dot_string(const T& obj) {
using namespace boost::xpressive;
static sregex valid_unquoted_id = (((alpha | '_') >> *_w) | (!as_xpr('-') >> (('.' >> *_d) | (+_d >> !('.' >> *_d)))));
std::string s(boost::lexical_cast<std::string>(obj));
if (regex_match(s, valid_unquoted_id)) {
return s;
} else {
boost::algorithm::replace_all(s, "\"", "\\\"");
return "\"" + s + "\"";
}
}
template <class Name>
class label_writer {
public:
label_writer(Name _name) : name(_name) {}
template <class VertexOrEdge>
void operator()(std::ostream& out, const VertexOrEdge& v) const {
out << "[label=" << escape_dot_string(get(name, v)) << "]";
}
private:
Name name;
};
template <class Name>
inline label_writer<Name>
make_label_writer(Name n) {
return label_writer<Name>(n);
}
enum edge_attribute_t { edge_attribute = 1111 };
enum vertex_attribute_t { vertex_attribute = 2222 };
enum graph_graph_attribute_t { graph_graph_attribute = 3333 };
enum graph_vertex_attribute_t { graph_vertex_attribute = 4444 };
enum graph_edge_attribute_t { graph_edge_attribute = 5555 };
BOOST_INSTALL_PROPERTY(edge, attribute);
BOOST_INSTALL_PROPERTY(vertex, attribute);
BOOST_INSTALL_PROPERTY(graph, graph_attribute);
BOOST_INSTALL_PROPERTY(graph, vertex_attribute);
BOOST_INSTALL_PROPERTY(graph, edge_attribute);
template <class Attribute>
inline void write_attributes(const Attribute& attr, std::ostream& out) {
typename Attribute::const_iterator i, iend;
i = attr.begin();
iend = attr.end();
while ( i != iend ) {
out << i->first << "=" << escape_dot_string(i->second);
++i;
if ( i != iend )
out << ", ";
}
}
template<typename Attributes>
inline void write_all_attributes(Attributes attributes,
const std::string& name,
std::ostream& out)
{
typename Attributes::const_iterator i = attributes.begin(),
end = attributes.end();
if (i != end) {
out << name << " [\n";
write_attributes(attributes, out);
out << "];\n";
}
}
inline void write_all_attributes(detail::error_property_not_found,
const std::string&,
std::ostream&)
{
// Do nothing - no attributes exist
}
template <typename GraphGraphAttributes,
typename GraphNodeAttributes,
typename GraphEdgeAttributes>
struct graph_attributes_writer
{
graph_attributes_writer(GraphGraphAttributes gg,
GraphNodeAttributes gn,
GraphEdgeAttributes ge)
: g_attributes(gg), n_attributes(gn), e_attributes(ge) { }
void operator()(std::ostream& out) const {
write_all_attributes(g_attributes, "graph", out);
write_all_attributes(n_attributes, "node", out);
write_all_attributes(e_attributes, "edge", out);
}
GraphGraphAttributes g_attributes;
GraphNodeAttributes n_attributes;
GraphEdgeAttributes e_attributes;
};
template <typename GAttrMap, typename NAttrMap, typename EAttrMap>
graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap>
make_graph_attributes_writer(const GAttrMap& g_attr, const NAttrMap& n_attr,
const EAttrMap& e_attr) {
return graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap>
(g_attr, n_attr, e_attr);
}
template <typename Graph>
graph_attributes_writer
<typename graph_property<Graph, graph_graph_attribute_t>::type,
typename graph_property<Graph, graph_vertex_attribute_t>::type,
typename graph_property<Graph, graph_edge_attribute_t>::type>
make_graph_attributes_writer(const Graph& g)
{
typedef typename graph_property<Graph, graph_graph_attribute_t>::type
GAttrMap;
typedef typename graph_property<Graph, graph_vertex_attribute_t>::type
NAttrMap;
typedef typename graph_property<Graph, graph_edge_attribute_t>::type
EAttrMap;
GAttrMap gam = get_property(g, graph_graph_attribute);
NAttrMap nam = get_property(g, graph_vertex_attribute);
EAttrMap eam = get_property(g, graph_edge_attribute);
graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap> writer(gam, nam, eam);
return writer;
}
template <typename AttributeMap>
struct attributes_writer {
attributes_writer(AttributeMap attr)
: attributes(attr) { }
template <class VorE>
void operator()(std::ostream& out, const VorE& e) const {
this->write_attribute(out, attributes[e]);
}
private:
template<typename AttributeSequence>
void write_attribute(std::ostream& out,
const AttributeSequence& seq) const
{
if (!seq.empty()) {
out << "[";
write_attributes(seq, out);
out << "]";
}
}
void write_attribute(std::ostream&,
detail::error_property_not_found) const
{
}
AttributeMap attributes;
};
template <typename Graph>
attributes_writer
<typename property_map<Graph, edge_attribute_t>::const_type>
make_edge_attributes_writer(const Graph& g)
{
typedef typename property_map<Graph, edge_attribute_t>::const_type
EdgeAttributeMap;
return attributes_writer<EdgeAttributeMap>(get(edge_attribute, g));
}
template <typename Graph>
attributes_writer
<typename property_map<Graph, vertex_attribute_t>::const_type>
make_vertex_attributes_writer(const Graph& g)
{
typedef typename property_map<Graph, vertex_attribute_t>::const_type
VertexAttributeMap;
return attributes_writer<VertexAttributeMap>(get(vertex_attribute, g));
}
template <typename Graph, typename VertexPropertiesWriter,
typename EdgePropertiesWriter, typename GraphPropertiesWriter,
typename VertexID>
inline void
write_graphviz
(std::ostream& out, const Graph& g,
VertexPropertiesWriter vpw,
EdgePropertiesWriter epw,
GraphPropertiesWriter gpw,
VertexID vertex_id
BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag))
{
BOOST_CONCEPT_ASSERT((EdgeListGraphConcept<Graph>));
typedef typename graph_traits<Graph>::directed_category cat_type;
typedef graphviz_io_traits<cat_type> Traits;
std::string name = "G";
out << Traits::name() << " " << escape_dot_string(name) << " {" << std::endl;
gpw(out); //print graph properties
typename graph_traits<Graph>::vertex_iterator i, end;
for(boost::tie(i,end) = vertices(g); i != end; ++i) {
out << escape_dot_string(get(vertex_id, *i));
vpw(out, *i); //print vertex attributes
out << ";" << std::endl;
}
typename graph_traits<Graph>::edge_iterator ei, edge_end;
for(boost::tie(ei, edge_end) = edges(g); ei != edge_end; ++ei) {
out << escape_dot_string(get(vertex_id, source(*ei, g))) << Traits::delimiter() << escape_dot_string(get(vertex_id, target(*ei, g))) << " ";
epw(out, *ei); //print edge attributes
out << ";" << std::endl;
}
out << "}" << std::endl;
}
template <typename Graph, typename VertexPropertiesWriter,
typename EdgePropertiesWriter, typename GraphPropertiesWriter>
inline void
write_graphviz(std::ostream& out, const Graph& g,
VertexPropertiesWriter vpw,
EdgePropertiesWriter epw,
GraphPropertiesWriter gpw
BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag))
{ write_graphviz(out, g, vpw, epw, gpw, get(vertex_index, g)); }
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
// ambiguous overload problem with VC++
template <typename Graph>
inline void
write_graphviz(std::ostream& out, const Graph& g
BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag))
{
default_writer dw;
default_writer gw;
write_graphviz(out, g, dw, dw, gw);
}
#endif
template <typename Graph, typename VertexWriter>
inline void
write_graphviz(std::ostream& out, const Graph& g, VertexWriter vw
BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag))
{
default_writer dw;
default_writer gw;
write_graphviz(out, g, vw, dw, gw);
}
template <typename Graph, typename VertexWriter, typename EdgeWriter>
inline void
write_graphviz(std::ostream& out, const Graph& g,
VertexWriter vw, EdgeWriter ew
BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag))
{
default_writer gw;
write_graphviz(out, g, vw, ew, gw);
}
namespace detail {
template <class Graph_, class RandomAccessIterator, class VertexID>
void write_graphviz_subgraph (std::ostream& out,
const subgraph<Graph_>& g,
RandomAccessIterator vertex_marker,
RandomAccessIterator edge_marker,
VertexID vertex_id)
{
typedef subgraph<Graph_> Graph;
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
typedef typename graph_traits<Graph>::directed_category cat_type;
typedef graphviz_io_traits<cat_type> Traits;
typedef typename graph_property<Graph, graph_name_t>::type NameType;
const NameType& g_name = get_property(g, graph_name);
if ( g.is_root() )
out << Traits::name() ;
else
out << "subgraph";
out << " " << escape_dot_string(g_name) << " {" << std::endl;
typename Graph::const_children_iterator i_child, j_child;
//print graph/node/edge attributes
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
typedef typename graph_property<Graph, graph_graph_attribute_t>::type
GAttrMap;
typedef typename graph_property<Graph, graph_vertex_attribute_t>::type
NAttrMap;
typedef typename graph_property<Graph, graph_edge_attribute_t>::type
EAttrMap;
GAttrMap gam = get_property(g, graph_graph_attribute);
NAttrMap nam = get_property(g, graph_vertex_attribute);
EAttrMap eam = get_property(g, graph_edge_attribute);
graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap> writer(gam, nam, eam);
writer(out);
#else
make_graph_attributes_writer(g)(out);
#endif
//print subgraph
for ( boost::tie(i_child,j_child) = g.children();
i_child != j_child; ++i_child )
write_graphviz_subgraph(out, *i_child, vertex_marker, edge_marker,
vertex_id);
// Print out vertices and edges not in the subgraphs.
typename graph_traits<Graph>::vertex_iterator i, end;
typename graph_traits<Graph>::edge_iterator ei, edge_end;
for(boost::tie(i,end) = vertices(g); i != end; ++i) {
Vertex v = g.local_to_global(*i);
int pos = get(vertex_id, v);
if ( vertex_marker[pos] ) {
vertex_marker[pos] = false;
out << escape_dot_string(pos);
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
typedef typename property_map<Graph, vertex_attribute_t>::const_type
VertexAttributeMap;
attributes_writer<VertexAttributeMap> vawriter(get(vertex_attribute,
g.root()));
vawriter(out, v);
#else
make_vertex_attributes_writer(g.root())(out, v);
#endif
out << ";" << std::endl;
}
}
for (boost::tie(ei, edge_end) = edges(g); ei != edge_end; ++ei) {
Vertex u = g.local_to_global(source(*ei,g)),
v = g.local_to_global(target(*ei, g));
int pos = get(get(edge_index, g.root()), g.local_to_global(*ei));
if ( edge_marker[pos] ) {
edge_marker[pos] = false;
out << escape_dot_string(get(vertex_id, u)) << " " << Traits::delimiter()
<< " " << escape_dot_string(get(vertex_id, v));
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
typedef typename property_map<Graph, edge_attribute_t>::const_type
EdgeAttributeMap;
attributes_writer<EdgeAttributeMap> eawriter(get(edge_attribute, g));
eawriter(out, *ei);
#else
make_edge_attributes_writer(g)(out, *ei); //print edge properties
#endif
out << ";" << std::endl;
}
}
out << "}" << std::endl;
}
} // namespace detail
// requires graph_name graph property
template <typename Graph>
void write_graphviz(std::ostream& out, const subgraph<Graph>& g) {
std::vector<bool> edge_marker(num_edges(g), true);
std::vector<bool> vertex_marker(num_vertices(g), true);
detail::write_graphviz_subgraph(out, g,
vertex_marker.begin(),
edge_marker.begin(),
get(vertex_index, g));
}
template <typename Graph>
void write_graphviz(const std::string& filename, const subgraph<Graph>& g) {
std::ofstream out(filename.c_str());
std::vector<bool> edge_marker(num_edges(g), true);
std::vector<bool> vertex_marker(num_vertices(g), true);
detail::write_graphviz_subgraph(out, g,
vertex_marker.begin(),
edge_marker.begin(),
get(vertex_index, g));
}
template <typename Graph, typename VertexID>
void write_graphviz(std::ostream& out, const subgraph<Graph>& g,
VertexID vertex_id)
{
std::vector<bool> edge_marker(num_edges(g), true);
std::vector<bool> vertex_marker(num_vertices(g), true);
detail::write_graphviz_subgraph(out, g,
vertex_marker.begin(),
edge_marker.begin(),
vertex_id);
}
template <typename Graph, typename VertexID>
void write_graphviz(const std::string& filename, const subgraph<Graph>& g,
VertexID vertex_id)
{
std::ofstream out(filename.c_str());
std::vector<bool> edge_marker(num_edges(g), true);
std::vector<bool> vertex_marker(num_vertices(g), true);
detail::write_graphviz_subgraph(out, g,
vertex_marker.begin(),
edge_marker.begin(),
vertex_id);
}
#if 0
// This interface has not worked for a long time
typedef std::map<std::string, std::string> GraphvizAttrList;
typedef property<vertex_attribute_t, GraphvizAttrList>
GraphvizVertexProperty;
typedef property<edge_attribute_t, GraphvizAttrList,
property<edge_index_t, int> >
GraphvizEdgeProperty;
typedef property<graph_graph_attribute_t, GraphvizAttrList,
property<graph_vertex_attribute_t, GraphvizAttrList,
property<graph_edge_attribute_t, GraphvizAttrList,
property<graph_name_t, std::string> > > >
GraphvizGraphProperty;
typedef subgraph<adjacency_list<vecS,
vecS, directedS,
GraphvizVertexProperty,
GraphvizEdgeProperty,
GraphvizGraphProperty> >
GraphvizDigraph;
typedef subgraph<adjacency_list<vecS,
vecS, undirectedS,
GraphvizVertexProperty,
GraphvizEdgeProperty,
GraphvizGraphProperty> >
GraphvizGraph;
// These four require linking the BGL-Graphviz library: libbgl-viz.a
// from the /src directory.
// Library has not existed for a while
extern void read_graphviz(const std::string& file, GraphvizDigraph& g);
extern void read_graphviz(FILE* file, GraphvizDigraph& g);
extern void read_graphviz(const std::string& file, GraphvizGraph& g);
extern void read_graphviz(FILE* file, GraphvizGraph& g);
#endif
class dynamic_properties_writer
{
public:
dynamic_properties_writer(const dynamic_properties& dp) : dp(&dp) { }
template<typename Descriptor>
void operator()(std::ostream& out, Descriptor key) const
{
bool first = true;
for (dynamic_properties::const_iterator i = dp->begin();
i != dp->end(); ++i) {
if (type_id<Descriptor>() == i->second->key()) {
if (first) out << " [";
else out << ", ";
first = false;
out << i->first << "=" << escape_dot_string(i->second->get_string(key));
}
}
if (!first) out << "]";
}
private:
const dynamic_properties* dp;
};
class dynamic_vertex_properties_writer
{
public:
dynamic_vertex_properties_writer(const dynamic_properties& dp,
const std::string& node_id)
: dp(&dp), node_id(&node_id) { }
template<typename Descriptor>
void operator()(std::ostream& out, Descriptor key) const
{
bool first = true;
for (dynamic_properties::const_iterator i = dp->begin();
i != dp->end(); ++i) {
if (type_id<Descriptor>(key) == i->second->key()
&& i->first != *node_id) {
if (first) out << " [";
else out << ", ";
first = false;
out << i->first << "=" << escape_dot_string(i->second->get_string(key));
}
}
if (!first) out << "]";
}
private:
const dynamic_properties* dp;
const std::string* node_id;
};
namespace graph { namespace detail {
template<typename Vertex>
struct node_id_property_map
{
typedef std::string value_type;
typedef value_type reference;
typedef Vertex key_type;
typedef readable_property_map_tag category;
node_id_property_map() {}
node_id_property_map(const dynamic_properties& dp,
const std::string& node_id)
: dp(&dp), node_id(&node_id) { }
const dynamic_properties* dp;
const std::string* node_id;
};
template<typename Vertex>
inline std::string
get(node_id_property_map<Vertex> pm,
typename node_id_property_map<Vertex>::key_type v)
{ return get(*pm.node_id, *pm.dp, v); }
} } // end namespace graph::detail
template<typename Graph>
inline void
write_graphviz_dp(std::ostream& out, const Graph& g,
const dynamic_properties& dp,
const std::string& node_id = "node_id"
BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag))
{
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
write_graphviz_dp(out, g, dp, node_id,
graph::detail::node_id_property_map<Vertex>(dp, node_id));
}
template<typename Graph, typename VertexID>
void
write_graphviz_dp(std::ostream& out, const Graph& g,
const dynamic_properties& dp, const std::string& node_id,
VertexID id
BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag))
{
write_graphviz
(out, g,
/*vertex_writer=*/dynamic_vertex_properties_writer(dp, node_id),
/*edge_writer=*/dynamic_properties_writer(dp),
/*graph_writer=*/default_writer(),
id);
}
/////////////////////////////////////////////////////////////////////////////
// Graph reader exceptions
/////////////////////////////////////////////////////////////////////////////
struct graph_exception : public std::exception {
virtual ~graph_exception() throw() {}
virtual const char* what() const throw() = 0;
};
struct bad_parallel_edge : public graph_exception {
std::string from;
std::string to;
mutable std::string statement;
bad_parallel_edge(const std::string& i, const std::string& j) :
from(i), to(j) {}
virtual ~bad_parallel_edge() throw() {}
const char* what() const throw() {
if(statement.empty())
statement =
std::string("Failed to add parallel edge: (")
+ from + "," + to + ")\n";
return statement.c_str();
}
};
struct directed_graph_error : public graph_exception {
virtual ~directed_graph_error() throw() {}
virtual const char* what() const throw() {
return
"read_graphviz: "
"Tried to read a directed graph into an undirected graph.";
}
};
struct undirected_graph_error : public graph_exception {
virtual ~undirected_graph_error() throw() {}
virtual const char* what() const throw() {
return
"read_graphviz: "
"Tried to read an undirected graph into a directed graph.";
}
};
struct bad_graphviz_syntax: public graph_exception {
std::string errmsg;
bad_graphviz_syntax(const std::string& errmsg)
: errmsg(errmsg) {}
const char* what() const throw () {return errmsg.c_str();}
~bad_graphviz_syntax() throw () {};
};
namespace detail { namespace graph {
typedef std::string id_t;
typedef id_t node_t;
// edges are not uniquely determined by adjacent nodes
class edge_t {
int idx_;
explicit edge_t(int i) : idx_(i) {}
public:
static edge_t new_edge() {
static int idx = 0;
return edge_t(idx++);
};
bool operator==(const edge_t& rhs) const {
return idx_ == rhs.idx_;
}
bool operator<(const edge_t& rhs) const {
return idx_ < rhs.idx_;
}
};
class mutate_graph
{
public:
virtual ~mutate_graph() {}
virtual bool is_directed() const = 0;
virtual void do_add_vertex(const node_t& node) = 0;
virtual void
do_add_edge(const edge_t& edge, const node_t& source, const node_t& target)
= 0;
virtual void
set_node_property(const id_t& key, const node_t& node, const id_t& value) = 0;
virtual void
set_edge_property(const id_t& key, const edge_t& edge, const id_t& value) = 0;
virtual void // RG: need new second parameter to support BGL subgraphs
set_graph_property(const id_t& key, const id_t& value) = 0;
};
template<typename MutableGraph>
class mutate_graph_impl : public mutate_graph
{
typedef typename graph_traits<MutableGraph>::vertex_descriptor bgl_vertex_t;
typedef typename graph_traits<MutableGraph>::edge_descriptor bgl_edge_t;
public:
mutate_graph_impl(MutableGraph& graph, dynamic_properties& dp,
std::string node_id_prop)
: graph_(graph), dp_(dp), node_id_prop_(node_id_prop) { }
~mutate_graph_impl() {}
bool is_directed() const
{
return
boost::is_convertible<
typename boost::graph_traits<MutableGraph>::directed_category,
boost::directed_tag>::value;
}
virtual void do_add_vertex(const node_t& node)
{
// Add the node to the graph.
bgl_vertex_t v = add_vertex(graph_);
// Set up a mapping from name to BGL vertex.
bgl_nodes.insert(std::make_pair(node, v));
// node_id_prop_ allows the caller to see the real id names for nodes.
put(node_id_prop_, dp_, v, node);
}
void
do_add_edge(const edge_t& edge, const node_t& source, const node_t& target)
{
std::pair<bgl_edge_t, bool> result =
add_edge(bgl_nodes[source], bgl_nodes[target], graph_);
if(!result.second) {
// In the case of no parallel edges allowed
boost::throw_exception(bad_parallel_edge(source, target));
} else {
bgl_edges.insert(std::make_pair(edge, result.first));
}
}
void
set_node_property(const id_t& key, const node_t& node, const id_t& value)
{
put(key, dp_, bgl_nodes[node], value);
}
void
set_edge_property(const id_t& key, const edge_t& edge, const id_t& value)
{
put(key, dp_, bgl_edges[edge], value);
}
void
set_graph_property(const id_t& key, const id_t& value)
{
/* RG: pointer to graph prevents copying */
put(key, dp_, &graph_, value);
}
protected:
MutableGraph& graph_;
dynamic_properties& dp_;
std::string node_id_prop_;
std::map<node_t, bgl_vertex_t> bgl_nodes;
std::map<edge_t, bgl_edge_t> bgl_edges;
};
} } } // end namespace boost::detail::graph
#ifdef BOOST_GRAPH_USE_SPIRIT_PARSER
# ifndef BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS
# define BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS
# endif
# include <boost/graph/detail/read_graphviz_spirit.hpp>
#else // New default parser
# include <boost/graph/detail/read_graphviz_new.hpp>
#endif // BOOST_GRAPH_USE_SPIRIT_PARSER
namespace boost {
// Parse the passed string as a GraphViz dot file.
template <typename MutableGraph>
bool read_graphviz(const std::string& data,
MutableGraph& graph,
dynamic_properties& dp,
std::string const& node_id = "node_id") {
#ifdef BOOST_GRAPH_USE_SPIRIT_PARSER
return read_graphviz_spirit(data.begin(), data.end(), graph, dp, node_id);
#else // Non-Spirit parser
return read_graphviz_new(data,graph,dp,node_id);
#endif
}
// Parse the passed iterator range as a GraphViz dot file.
template <typename InputIterator, typename MutableGraph>
bool read_graphviz(InputIterator user_first,
InputIterator user_last,
MutableGraph& graph,
dynamic_properties& dp,
std::string const& node_id = "node_id") {
#ifdef BOOST_GRAPH_USE_SPIRIT_PARSER
typedef InputIterator is_t;
typedef boost::spirit::classic::multi_pass<is_t> iterator_t;
iterator_t first(boost::spirit::classic::make_multi_pass(user_first));
iterator_t last(boost::spirit::classic::make_multi_pass(user_last));
return read_graphviz_spirit(first, last, graph, dp, node_id);
#else // Non-Spirit parser
return read_graphviz_new(std::string(user_first, user_last), graph, dp, node_id);
#endif
}
// Parse the passed stream as a GraphViz dot file.
template <typename MutableGraph>
bool read_graphviz(std::istream& in, MutableGraph& graph,
dynamic_properties& dp,
std::string const& node_id = "node_id")
{
typedef std::istream_iterator<char> is_t;
in >> std::noskipws;
return read_graphviz(is_t(in), is_t(), graph, dp, node_id);
}
} // namespace boost
#ifdef BOOST_GRAPH_USE_MPI
# include <boost/graph/distributed/graphviz.hpp>
#endif
#endif // BOOST_GRAPHVIZ_HPP

View File

@@ -1,615 +0,0 @@
// Copyright 2004 The Trustees of Indiana University.
// Use, modification and distribution is 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)
// Authors: Douglas Gregor
// Peter Gottschling
// Andrew Lumsdaine
#ifndef BOOST_PARALLEL_DISTRIBUTION_HPP
#define BOOST_PARALLEL_DISTRIBUTION_HPP
#ifndef BOOST_GRAPH_USE_MPI
#error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
#endif
#include <cstddef>
#include <vector>
#include <algorithm>
#include <numeric>
#include <boost/assert.hpp>
#include <boost/iterator/counting_iterator.hpp>
#include <boost/random/uniform_int.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/type_index.hpp>
namespace boost { namespace parallel {
template<typename ProcessGroup, typename SizeType = std::size_t>
class variant_distribution
{
public:
typedef typename ProcessGroup::process_id_type process_id_type;
typedef typename ProcessGroup::process_size_type process_size_type;
typedef SizeType size_type;
private:
struct basic_distribution
{
virtual ~basic_distribution() {}
virtual size_type block_size(process_id_type, size_type) const = 0;
virtual process_id_type in_process(size_type) const = 0;
virtual size_type local(size_type) const = 0;
virtual size_type global(size_type) const = 0;
virtual size_type global(process_id_type, size_type) const = 0;
virtual void* address() = 0;
virtual const void* address() const = 0;
virtual type_index type() const = 0;
};
template<typename Distribution>
struct poly_distribution : public basic_distribution
{
explicit poly_distribution(const Distribution& distribution)
: distribution_(distribution) { }
virtual size_type block_size(process_id_type id, size_type n) const
{ return distribution_.block_size(id, n); }
virtual process_id_type in_process(size_type i) const
{ return distribution_(i); }
virtual size_type local(size_type i) const
{ return distribution_.local(i); }
virtual size_type global(size_type n) const
{ return distribution_.global(n); }
virtual size_type global(process_id_type id, size_type n) const
{ return distribution_.global(id, n); }
virtual void* address() { return &distribution_; }
virtual const void* address() const { return &distribution_; }
virtual type_index type() const { return type_id<Distribution>(); }
private:
Distribution distribution_;
};
public:
variant_distribution() { }
template<typename Distribution>
variant_distribution(const Distribution& distribution)
: distribution_(new poly_distribution<Distribution>(distribution)) { }
size_type block_size(process_id_type id, size_type n) const
{ return distribution_->block_size(id, n); }
process_id_type operator()(size_type i) const
{ return distribution_->in_process(i); }
size_type local(size_type i) const
{ return distribution_->local(i); }
size_type global(size_type n) const
{ return distribution_->global(n); }
size_type global(process_id_type id, size_type n) const
{ return distribution_->global(id, n); }
operator bool() const { return distribution_; }
void clear() { distribution_.reset(); }
template<typename T>
T* as()
{
if (distribution_->type() == type_id<T>())
return static_cast<T*>(distribution_->address());
else
return 0;
}
template<typename T>
const T* as() const
{
if (distribution_->type() == type_id<T>())
return static_cast<T*>(distribution_->address());
else
return 0;
}
private:
shared_ptr<basic_distribution> distribution_;
};
struct block
{
template<typename LinearProcessGroup>
explicit block(const LinearProcessGroup& pg, std::size_t n)
: id(process_id(pg)), p(num_processes(pg)), n(n) { }
// If there are n elements in the distributed data structure, returns the number of elements stored locally.
template<typename SizeType>
SizeType block_size(SizeType n) const
{ return (n / p) + ((std::size_t)(n % p) > id? 1 : 0); }
// If there are n elements in the distributed data structure, returns the number of elements stored on processor ID
template<typename SizeType, typename ProcessID>
SizeType block_size(ProcessID id, SizeType n) const
{ return (n / p) + ((ProcessID)(n % p) > id? 1 : 0); }
// Returns the processor on which element with global index i is stored
template<typename SizeType>
SizeType operator()(SizeType i) const
{
SizeType cutoff_processor = n % p;
SizeType cutoff = cutoff_processor * (n / p + 1);
if (i < cutoff) return i / (n / p + 1);
else return cutoff_processor + (i - cutoff) / (n / p);
}
// Find the starting index for processor with the given id
template<typename ID>
std::size_t start(ID id) const
{
std::size_t estimate = id * (n / p + 1);
ID cutoff_processor = n % p;
if (id < cutoff_processor) return estimate;
else return estimate - (id - cutoff_processor);
}
// Find the local index for the ith global element
template<typename SizeType>
SizeType local(SizeType i) const
{
SizeType owner = (*this)(i);
return i - start(owner);
}
// Returns the global index of local element i
template<typename SizeType>
SizeType global(SizeType i) const
{ return global(id, i); }
// Returns the global index of the ith local element on processor id
template<typename ProcessID, typename SizeType>
SizeType global(ProcessID id, SizeType i) const
{ return i + start(id); }
private:
std::size_t id; //< The ID number of this processor
std::size_t p; //< The number of processors
std::size_t n; //< The size of the problem space
};
// Block distribution with arbitrary block sizes
struct uneven_block
{
typedef std::vector<std::size_t> size_vector;
template<typename LinearProcessGroup>
explicit uneven_block(const LinearProcessGroup& pg, const std::vector<std::size_t>& local_sizes)
: id(process_id(pg)), p(num_processes(pg)), local_sizes(local_sizes)
{
BOOST_ASSERT(local_sizes.size() == p);
local_starts.resize(p + 1);
local_starts[0] = 0;
std::partial_sum(local_sizes.begin(), local_sizes.end(), &local_starts[1]);
n = local_starts[p];
}
// To do maybe: enter local size in each process and gather in constructor (much handier)
// template<typename LinearProcessGroup>
// explicit uneven_block(const LinearProcessGroup& pg, std::size_t my_local_size)
// If there are n elements in the distributed data structure, returns the number of elements stored locally.
template<typename SizeType>
SizeType block_size(SizeType) const
{ return local_sizes[id]; }
// If there are n elements in the distributed data structure, returns the number of elements stored on processor ID
template<typename SizeType, typename ProcessID>
SizeType block_size(ProcessID id, SizeType) const
{ return local_sizes[id]; }
// Returns the processor on which element with global index i is stored
template<typename SizeType>
SizeType operator()(SizeType i) const
{
BOOST_ASSERT (i >= (SizeType) 0 && i < (SizeType) n); // check for valid range
size_vector::const_iterator lb = std::lower_bound(local_starts.begin(), local_starts.end(), (std::size_t) i);
return ((SizeType)(*lb) == i ? lb : --lb) - local_starts.begin();
}
// Find the starting index for processor with the given id
template<typename ID>
std::size_t start(ID id) const
{
return local_starts[id];
}
// Find the local index for the ith global element
template<typename SizeType>
SizeType local(SizeType i) const
{
SizeType owner = (*this)(i);
return i - start(owner);
}
// Returns the global index of local element i
template<typename SizeType>
SizeType global(SizeType i) const
{ return global(id, i); }
// Returns the global index of the ith local element on processor id
template<typename ProcessID, typename SizeType>
SizeType global(ProcessID id, SizeType i) const
{ return i + start(id); }
private:
std::size_t id; //< The ID number of this processor
std::size_t p; //< The number of processors
std::size_t n; //< The size of the problem space
std::vector<std::size_t> local_sizes; //< The sizes of all blocks
std::vector<std::size_t> local_starts; //< Lowest global index of each block
};
struct oned_block_cyclic
{
template<typename LinearProcessGroup>
explicit oned_block_cyclic(const LinearProcessGroup& pg, std::size_t size)
: id(process_id(pg)), p(num_processes(pg)), size(size) { }
template<typename SizeType>
SizeType block_size(SizeType n) const
{
return block_size(id, n);
}
template<typename SizeType, typename ProcessID>
SizeType block_size(ProcessID id, SizeType n) const
{
SizeType all_blocks = n / size;
SizeType extra_elements = n % size;
SizeType everyone_gets = all_blocks / p;
SizeType extra_blocks = all_blocks % p;
SizeType my_blocks = everyone_gets + (p < extra_blocks? 1 : 0);
SizeType my_elements = my_blocks * size
+ (p == extra_blocks? extra_elements : 0);
return my_elements;
}
template<typename SizeType>
SizeType operator()(SizeType i) const
{
return (i / size) % p;
}
template<typename SizeType>
SizeType local(SizeType i) const
{
return ((i / size) / p) * size + i % size;
}
template<typename SizeType>
SizeType global(SizeType i) const
{ return global(id, i); }
template<typename ProcessID, typename SizeType>
SizeType global(ProcessID id, SizeType i) const
{
return ((i / size) * p + id) * size + i % size;
}
private:
std::size_t id; //< The ID number of this processor
std::size_t p; //< The number of processors
std::size_t size; //< Block size
};
struct twod_block_cyclic
{
template<typename LinearProcessGroup>
explicit twod_block_cyclic(const LinearProcessGroup& pg,
std::size_t block_rows, std::size_t block_columns,
std::size_t data_columns_per_row)
: id(process_id(pg)), p(num_processes(pg)),
block_rows(block_rows), block_columns(block_columns),
data_columns_per_row(data_columns_per_row)
{ }
template<typename SizeType>
SizeType block_size(SizeType n) const
{
return block_size(id, n);
}
template<typename SizeType, typename ProcessID>
SizeType block_size(ProcessID id, SizeType n) const
{
// TBD: This is really lame :)
int result = -1;
while (n > 0) {
--n;
if ((*this)(n) == id && (int)local(n) > result) result = local(n);
}
++result;
// std::cerr << "Block size of id " << id << " is " << result << std::endl;
return result;
}
template<typename SizeType>
SizeType operator()(SizeType i) const
{
SizeType result = get_block_num(i) % p;
// std::cerr << "Item " << i << " goes on processor " << result << std::endl;
return result;
}
template<typename SizeType>
SizeType local(SizeType i) const
{
// Compute the start of the block
std::size_t block_num = get_block_num(i);
// std::cerr << "Item " << i << " is in block #" << block_num << std::endl;
std::size_t local_block_num = block_num / p;
std::size_t block_start = local_block_num * block_rows * block_columns;
// Compute the offset into the block
std::size_t data_row = i / data_columns_per_row;
std::size_t data_col = i % data_columns_per_row;
std::size_t block_offset = (data_row % block_rows) * block_columns
+ (data_col % block_columns);
// std::cerr << "Item " << i << " maps to local index " << block_start+block_offset << std::endl;
return block_start + block_offset;
}
template<typename SizeType>
SizeType global(SizeType i) const
{
// Compute the (global) block in which this element resides
SizeType local_block_num = i / (block_rows * block_columns);
SizeType block_offset = i % (block_rows * block_columns);
SizeType block_num = local_block_num * p + id;
// Compute the position of the start of the block (globally)
SizeType block_start = block_num * block_rows * block_columns;
std::cerr << "Block " << block_num << " starts at index " << block_start
<< std::endl;
// Compute the row and column of this block
SizeType block_row = block_num / (data_columns_per_row / block_columns);
SizeType block_col = block_num % (data_columns_per_row / block_columns);
SizeType row_in_block = block_offset / block_columns;
SizeType col_in_block = block_offset % block_columns;
std::cerr << "Local index " << i << " is in block at row " << block_row
<< ", column " << block_col << ", in-block row " << row_in_block
<< ", in-block col " << col_in_block << std::endl;
SizeType result = block_row * block_rows + block_col * block_columns
+ row_in_block * block_rows + col_in_block;
std::cerr << "global(" << i << "@" << id << ") = " << result
<< " =? " << local(result) << std::endl;
BOOST_ASSERT(i == local(result));
return result;
}
private:
template<typename SizeType>
std::size_t get_block_num(SizeType i) const
{
std::size_t data_row = i / data_columns_per_row;
std::size_t data_col = i % data_columns_per_row;
std::size_t block_row = data_row / block_rows;
std::size_t block_col = data_col / block_columns;
std::size_t blocks_in_row = data_columns_per_row / block_columns;
std::size_t block_num = block_col * blocks_in_row + block_row;
return block_num;
}
std::size_t id; //< The ID number of this processor
std::size_t p; //< The number of processors
std::size_t block_rows; //< The # of rows in each block
std::size_t block_columns; //< The # of columns in each block
std::size_t data_columns_per_row; //< The # of columns per row of data
};
class twod_random
{
template<typename RandomNumberGen>
struct random_int
{
explicit random_int(RandomNumberGen& gen) : gen(gen) { }
template<typename T>
T operator()(T n) const
{
uniform_int<T> distrib(0, n-1);
return distrib(gen);
}
private:
RandomNumberGen& gen;
};
public:
template<typename LinearProcessGroup, typename RandomNumberGen>
explicit twod_random(const LinearProcessGroup& pg,
std::size_t block_rows, std::size_t block_columns,
std::size_t data_columns_per_row,
std::size_t n,
RandomNumberGen& gen)
: id(process_id(pg)), p(num_processes(pg)),
block_rows(block_rows), block_columns(block_columns),
data_columns_per_row(data_columns_per_row),
global_to_local(n / (block_rows * block_columns))
{
std::copy(make_counting_iterator(std::size_t(0)),
make_counting_iterator(global_to_local.size()),
global_to_local.begin());
random_int<RandomNumberGen> rand(gen);
std::random_shuffle(global_to_local.begin(), global_to_local.end(), rand);
}
template<typename SizeType>
SizeType block_size(SizeType n) const
{
return block_size(id, n);
}
template<typename SizeType, typename ProcessID>
SizeType block_size(ProcessID id, SizeType n) const
{
// TBD: This is really lame :)
int result = -1;
while (n > 0) {
--n;
if ((*this)(n) == id && (int)local(n) > result) result = local(n);
}
++result;
// std::cerr << "Block size of id " << id << " is " << result << std::endl;
return result;
}
template<typename SizeType>
SizeType operator()(SizeType i) const
{
SizeType result = get_block_num(i) % p;
// std::cerr << "Item " << i << " goes on processor " << result << std::endl;
return result;
}
template<typename SizeType>
SizeType local(SizeType i) const
{
// Compute the start of the block
std::size_t block_num = get_block_num(i);
// std::cerr << "Item " << i << " is in block #" << block_num << std::endl;
std::size_t local_block_num = block_num / p;
std::size_t block_start = local_block_num * block_rows * block_columns;
// Compute the offset into the block
std::size_t data_row = i / data_columns_per_row;
std::size_t data_col = i % data_columns_per_row;
std::size_t block_offset = (data_row % block_rows) * block_columns
+ (data_col % block_columns);
// std::cerr << "Item " << i << " maps to local index " << block_start+block_offset << std::endl;
return block_start + block_offset;
}
private:
template<typename SizeType>
std::size_t get_block_num(SizeType i) const
{
std::size_t data_row = i / data_columns_per_row;
std::size_t data_col = i % data_columns_per_row;
std::size_t block_row = data_row / block_rows;
std::size_t block_col = data_col / block_columns;
std::size_t blocks_in_row = data_columns_per_row / block_columns;
std::size_t block_num = block_col * blocks_in_row + block_row;
return global_to_local[block_num];
}
std::size_t id; //< The ID number of this processor
std::size_t p; //< The number of processors
std::size_t block_rows; //< The # of rows in each block
std::size_t block_columns; //< The # of columns in each block
std::size_t data_columns_per_row; //< The # of columns per row of data
std::vector<std::size_t> global_to_local;
};
class random_distribution
{
template<typename RandomNumberGen>
struct random_int
{
explicit random_int(RandomNumberGen& gen) : gen(gen) { }
template<typename T>
T operator()(T n) const
{
uniform_int<T> distrib(0, n-1);
return distrib(gen);
}
private:
RandomNumberGen& gen;
};
public:
template<typename LinearProcessGroup, typename RandomNumberGen>
random_distribution(const LinearProcessGroup& pg, RandomNumberGen& gen,
std::size_t n)
: base(pg, n), local_to_global(n), global_to_local(n)
{
std::copy(make_counting_iterator(std::size_t(0)),
make_counting_iterator(n),
local_to_global.begin());
random_int<RandomNumberGen> rand(gen);
std::random_shuffle(local_to_global.begin(), local_to_global.end(), rand);
for (std::vector<std::size_t>::size_type i = 0; i < n; ++i)
global_to_local[local_to_global[i]] = i;
}
template<typename SizeType>
SizeType block_size(SizeType n) const
{ return base.block_size(n); }
template<typename SizeType, typename ProcessID>
SizeType block_size(ProcessID id, SizeType n) const
{ return base.block_size(id, n); }
template<typename SizeType>
SizeType operator()(SizeType i) const
{
return base(global_to_local[i]);
}
template<typename SizeType>
SizeType local(SizeType i) const
{
return base.local(global_to_local[i]);
}
template<typename ProcessID, typename SizeType>
SizeType global(ProcessID p, SizeType i) const
{
return local_to_global[base.global(p, i)];
}
template<typename SizeType>
SizeType global(SizeType i) const
{
return local_to_global[base.global(i)];
}
private:
block base;
std::vector<std::size_t> local_to_global;
std::vector<std::size_t> global_to_local;
};
} } // end namespace boost::parallel
#endif // BOOST_PARALLEL_DISTRIBUTION_HPP

View File

@@ -1,163 +0,0 @@
// Copyright John Maddock 2010.
// 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)
#ifdef _MSC_VER
# pragma once
#endif
#ifndef BOOST_MATH_CONSTANTS_INFO_INCLUDED
#define BOOST_MATH_CONSTANTS_INFO_INCLUDED
#include <boost/math/constants/constants.hpp>
#include <boost/type_index.hpp>
#include <iostream>
#include <iomanip>
namespace boost{ namespace math{ namespace constants{
namespace detail{
template <class T>
const char* nameof(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T))
{
return type_id<T>().name_demangled();
}
template <>
const char* nameof<float>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(float))
{
return "float";
}
template <>
const char* nameof<double>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(double))
{
return "double";
}
template <>
const char* nameof<long double>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(long double))
{
return "long double";
}
}
template <class T, class Policy>
void print_info_on_type(std::ostream& os = std::cout BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T) BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(Policy))
{
using detail::nameof;
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4127)
#endif
os <<
"Information on the Implementation and Handling of \n"
"Mathematical Constants for Type " << nameof<T>() <<
"\n\n"
"Checking for std::numeric_limits<" << nameof<T>() << "> specialisation: " <<
(std::numeric_limits<T>::is_specialized ? "yes" : "no") << std::endl;
if(std::numeric_limits<T>::is_specialized)
{
os <<
"std::numeric_limits<" << nameof<T>() << ">::digits reports that the radix is " << std::numeric_limits<T>::radix << ".\n";
if (std::numeric_limits<T>::radix == 2)
{
os <<
"std::numeric_limits<" << nameof<T>() << ">::digits reports that the precision is \n" << std::numeric_limits<T>::digits << " binary digits.\n";
}
else if (std::numeric_limits<T>::radix == 10)
{
os <<
"std::numeric_limits<" << nameof<T>() << ">::digits reports that the precision is \n" << std::numeric_limits<T>::digits10 << " decimal digits.\n";
os <<
"std::numeric_limits<" << nameof<T>() << ">::digits reports that the precision is \n"
<< std::numeric_limits<T>::digits * 1000L /301L << " binary digits.\n"; // divide by log2(10) - about 3 bits per decimal digit.
}
else
{
os << "Unknown radix = " << std::numeric_limits<T>::radix << "\n";
}
}
typedef typename boost::math::policies::precision<T, Policy>::type precision_type;
if(precision_type::value)
{
if (std::numeric_limits<T>::radix == 2)
{
os <<
"boost::math::policies::precision<" << nameof<T>() << ", " << nameof<Policy>() << " reports that the compile time precision is \n" << precision_type::value << " binary digits.\n";
}
else if (std::numeric_limits<T>::radix == 10)
{
os <<
"boost::math::policies::precision<" << nameof<T>() << ", " << nameof<Policy>() << " reports that the compile time precision is \n" << precision_type::value << " binary digits.\n";
}
else
{
os << "Unknown radix = " << std::numeric_limits<T>::radix << "\n";
}
}
else
{
os <<
"boost::math::policies::precision<" << nameof<T>() << ", Policy> \n"
"reports that there is no compile type precision available.\n"
"boost::math::tools::digits<" << nameof<T>() << ">() \n"
"reports that the current runtime precision is \n" <<
boost::math::tools::digits<T>() << " binary digits.\n";
}
typedef typename construction_traits<T, Policy>::type construction_type;
switch(construction_type::value)
{
case 0:
os <<
"No compile time precision is available, the construction method \n"
"will be decided at runtime and results will not be cached \n"
"- this may lead to poor runtime performance.\n"
"Current runtime precision indicates that\n";
if(boost::math::tools::digits<T>() > max_string_digits)
{
os << "the constant will be recalculated on each call.\n";
}
else
{
os << "the constant will be constructed from a string on each call.\n";
}
break;
case 1:
os <<
"The constant will be constructed from a float.\n";
break;
case 2:
os <<
"The constant will be constructed from a double.\n";
break;
case 3:
os <<
"The constant will be constructed from a long double.\n";
break;
case 4:
os <<
"The constant will be constructed from a string (and the result cached).\n";
break;
default:
os <<
"The constant will be calculated (and the result cached).\n";
break;
}
os << std::endl;
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
}
template <class T>
void print_info_on_type(std::ostream& os = std::cout BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T))
{
print_info_on_type<T, boost::math::policies::policy<> >(os);
}
}}} // namespaces
#endif // BOOST_MATH_CONSTANTS_INFO_INCLUDED

View File

@@ -1,488 +0,0 @@
// Copyright 2008 Gautam Sewani
// Copyright 2008 John Maddock
//
// 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)
#ifndef BOOST_MATH_DISTRIBUTIONS_DETAIL_HG_PDF_HPP
#define BOOST_MATH_DISTRIBUTIONS_DETAIL_HG_PDF_HPP
#include <boost/math/constants/constants.hpp>
#include <boost/math/special_functions/lanczos.hpp>
#include <boost/math/special_functions/gamma.hpp>
#include <boost/math/special_functions/pow.hpp>
#include <boost/math/special_functions/prime.hpp>
#include <boost/math/policies/error_handling.hpp>
#ifdef BOOST_MATH_INSTRUMENT
#include <boost/type_index.hpp>
#endif
namespace boost{ namespace math{ namespace detail{
template <class T, class Func>
void bubble_down_one(T* first, T* last, Func f)
{
using std::swap;
T* next = first;
++next;
while((next != last) && (!f(*first, *next)))
{
swap(*first, *next);
++first;
++next;
}
}
template <class T>
struct sort_functor
{
sort_functor(const T* exponents) : m_exponents(exponents){}
bool operator()(int i, int j)
{
return m_exponents[i] > m_exponents[j];
}
private:
const T* m_exponents;
};
template <class T, class Lanczos, class Policy>
T hypergeometric_pdf_lanczos_imp(T /*dummy*/, unsigned x, unsigned r, unsigned n, unsigned N, const Lanczos&, const Policy&)
{
BOOST_MATH_STD_USING
BOOST_MATH_INSTRUMENT_FPU
BOOST_MATH_INSTRUMENT_VARIABLE(x);
BOOST_MATH_INSTRUMENT_VARIABLE(r);
BOOST_MATH_INSTRUMENT_VARIABLE(n);
BOOST_MATH_INSTRUMENT_VARIABLE(N);
BOOST_MATH_INSTRUMENT_VARIABLE(type_id<Lanczos>().name_demangled());
T bases[9] = {
T(n) + Lanczos::g() + 0.5f,
T(r) + Lanczos::g() + 0.5f,
T(N - n) + Lanczos::g() + 0.5f,
T(N - r) + Lanczos::g() + 0.5f,
1 / (T(N) + Lanczos::g() + 0.5f),
1 / (T(x) + Lanczos::g() + 0.5f),
1 / (T(n - x) + Lanczos::g() + 0.5f),
1 / (T(r - x) + Lanczos::g() + 0.5f),
1 / (T(N - n - r + x) + Lanczos::g() + 0.5f)
};
T exponents[9] = {
n + T(0.5f),
r + T(0.5f),
N - n + T(0.5f),
N - r + T(0.5f),
N + T(0.5f),
x + T(0.5f),
n - x + T(0.5f),
r - x + T(0.5f),
N - n - r + x + T(0.5f)
};
int base_e_factors[9] = {
-1, -1, -1, -1, 1, 1, 1, 1, 1
};
int sorted_indexes[9] = {
0, 1, 2, 3, 4, 5, 6, 7, 8
};
#ifdef BOOST_MATH_INSTRUMENT
BOOST_MATH_INSTRUMENT_FPU
for(unsigned i = 0; i < 9; ++i)
{
BOOST_MATH_INSTRUMENT_VARIABLE(i);
BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]);
}
#endif
std::sort(sorted_indexes, sorted_indexes + 9, sort_functor<T>(exponents));
#ifdef BOOST_MATH_INSTRUMENT
BOOST_MATH_INSTRUMENT_FPU
for(unsigned i = 0; i < 9; ++i)
{
BOOST_MATH_INSTRUMENT_VARIABLE(i);
BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]);
}
#endif
do{
exponents[sorted_indexes[0]] -= exponents[sorted_indexes[1]];
bases[sorted_indexes[1]] *= bases[sorted_indexes[0]];
if((bases[sorted_indexes[1]] < tools::min_value<T>()) && (exponents[sorted_indexes[1]] != 0))
{
return 0;
}
base_e_factors[sorted_indexes[1]] += base_e_factors[sorted_indexes[0]];
bubble_down_one(sorted_indexes, sorted_indexes + 9, sort_functor<T>(exponents));
#ifdef BOOST_MATH_INSTRUMENT
for(unsigned i = 0; i < 9; ++i)
{
BOOST_MATH_INSTRUMENT_VARIABLE(i);
BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]);
}
#endif
}while(exponents[sorted_indexes[1]] > 1);
//
// Combine equal powers:
//
int j = 8;
while(exponents[sorted_indexes[j]] == 0) --j;
while(j)
{
while(j && (exponents[sorted_indexes[j-1]] == exponents[sorted_indexes[j]]))
{
bases[sorted_indexes[j-1]] *= bases[sorted_indexes[j]];
exponents[sorted_indexes[j]] = 0;
base_e_factors[sorted_indexes[j-1]] += base_e_factors[sorted_indexes[j]];
bubble_down_one(sorted_indexes + j, sorted_indexes + 9, sort_functor<T>(exponents));
--j;
}
--j;
#ifdef BOOST_MATH_INSTRUMENT
BOOST_MATH_INSTRUMENT_VARIABLE(j);
for(unsigned i = 0; i < 9; ++i)
{
BOOST_MATH_INSTRUMENT_VARIABLE(i);
BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]);
}
#endif
}
#ifdef BOOST_MATH_INSTRUMENT
BOOST_MATH_INSTRUMENT_FPU
for(unsigned i = 0; i < 9; ++i)
{
BOOST_MATH_INSTRUMENT_VARIABLE(i);
BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]);
}
#endif
T result;
BOOST_MATH_INSTRUMENT_VARIABLE(bases[sorted_indexes[0]] * exp(static_cast<T>(base_e_factors[sorted_indexes[0]])));
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[sorted_indexes[0]]);
{
BOOST_FPU_EXCEPTION_GUARD
result = pow(bases[sorted_indexes[0]] * exp(static_cast<T>(base_e_factors[sorted_indexes[0]])), exponents[sorted_indexes[0]]);
}
BOOST_MATH_INSTRUMENT_VARIABLE(result);
for(unsigned i = 1; (i < 9) && (exponents[sorted_indexes[i]] > 0); ++i)
{
BOOST_FPU_EXCEPTION_GUARD
if(result < tools::min_value<T>())
return 0; // short circuit further evaluation
if(exponents[sorted_indexes[i]] == 1)
result *= bases[sorted_indexes[i]] * exp(static_cast<T>(base_e_factors[sorted_indexes[i]]));
else if(exponents[sorted_indexes[i]] == 0.5f)
result *= sqrt(bases[sorted_indexes[i]] * exp(static_cast<T>(base_e_factors[sorted_indexes[i]])));
else
result *= pow(bases[sorted_indexes[i]] * exp(static_cast<T>(base_e_factors[sorted_indexes[i]])), exponents[sorted_indexes[i]]);
BOOST_MATH_INSTRUMENT_VARIABLE(result);
}
result *= Lanczos::lanczos_sum_expG_scaled(static_cast<T>(n + 1))
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(r + 1))
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(N - n + 1))
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(N - r + 1))
/
( Lanczos::lanczos_sum_expG_scaled(static_cast<T>(N + 1))
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(x + 1))
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(n - x + 1))
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(r - x + 1))
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(N - n - r + x + 1)));
BOOST_MATH_INSTRUMENT_VARIABLE(result);
return result;
}
template <class T, class Policy>
T hypergeometric_pdf_lanczos_imp(T /*dummy*/, unsigned x, unsigned r, unsigned n, unsigned N, const boost::math::lanczos::undefined_lanczos&, const Policy& pol)
{
BOOST_MATH_STD_USING
return exp(
boost::math::lgamma(T(n + 1), pol)
+ boost::math::lgamma(T(r + 1), pol)
+ boost::math::lgamma(T(N - n + 1), pol)
+ boost::math::lgamma(T(N - r + 1), pol)
- boost::math::lgamma(T(N + 1), pol)
- boost::math::lgamma(T(x + 1), pol)
- boost::math::lgamma(T(n - x + 1), pol)
- boost::math::lgamma(T(r - x + 1), pol)
- boost::math::lgamma(T(N - n - r + x + 1), pol));
}
template <class T>
inline T integer_power(const T& x, int ex)
{
if(ex < 0)
return 1 / integer_power(x, -ex);
switch(ex)
{
case 0:
return 1;
case 1:
return x;
case 2:
return x * x;
case 3:
return x * x * x;
case 4:
return boost::math::pow<4>(x);
case 5:
return boost::math::pow<5>(x);
case 6:
return boost::math::pow<6>(x);
case 7:
return boost::math::pow<7>(x);
case 8:
return boost::math::pow<8>(x);
}
BOOST_MATH_STD_USING
#ifdef __SUNPRO_CC
return pow(x, T(ex));
#else
return pow(x, ex);
#endif
}
template <class T>
struct hypergeometric_pdf_prime_loop_result_entry
{
T value;
const hypergeometric_pdf_prime_loop_result_entry* next;
};
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4510 4512 4610)
#endif
struct hypergeometric_pdf_prime_loop_data
{
const unsigned x;
const unsigned r;
const unsigned n;
const unsigned N;
unsigned prime_index;
unsigned current_prime;
};
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
template <class T>
T hypergeometric_pdf_prime_loop_imp(hypergeometric_pdf_prime_loop_data& data, hypergeometric_pdf_prime_loop_result_entry<T>& result)
{
while(data.current_prime <= data.N)
{
unsigned base = data.current_prime;
int prime_powers = 0;
while(base <= data.N)
{
prime_powers += data.n / base;
prime_powers += data.r / base;
prime_powers += (data.N - data.n) / base;
prime_powers += (data.N - data.r) / base;
prime_powers -= data.N / base;
prime_powers -= data.x / base;
prime_powers -= (data.n - data.x) / base;
prime_powers -= (data.r - data.x) / base;
prime_powers -= (data.N - data.n - data.r + data.x) / base;
base *= data.current_prime;
}
if(prime_powers)
{
T p = integer_power<T>(data.current_prime, prime_powers);
if((p > 1) && (tools::max_value<T>() / p < result.value))
{
//
// The next calculation would overflow, use recursion
// to sidestep the issue:
//
hypergeometric_pdf_prime_loop_result_entry<T> t = { p, &result };
data.current_prime = prime(++data.prime_index);
return hypergeometric_pdf_prime_loop_imp<T>(data, t);
}
if((p < 1) && (tools::min_value<T>() / p > result.value))
{
//
// The next calculation would underflow, use recursion
// to sidestep the issue:
//
hypergeometric_pdf_prime_loop_result_entry<T> t = { p, &result };
data.current_prime = prime(++data.prime_index);
return hypergeometric_pdf_prime_loop_imp<T>(data, t);
}
result.value *= p;
}
data.current_prime = prime(++data.prime_index);
}
//
// When we get to here we have run out of prime factors,
// the overall result is the product of all the partial
// results we have accumulated on the stack so far, these
// are in a linked list starting with "data.head" and ending
// with "result".
//
// All that remains is to multiply them together, taking
// care not to overflow or underflow.
//
// Enumerate partial results >= 1 in variable i
// and partial results < 1 in variable j:
//
hypergeometric_pdf_prime_loop_result_entry<T> const *i, *j;
i = &result;
while(i && i->value < 1)
i = i->next;
j = &result;
while(j && j->value >= 1)
j = j->next;
T prod = 1;
while(i || j)
{
while(i && ((prod <= 1) || (j == 0)))
{
prod *= i->value;
i = i->next;
while(i && i->value < 1)
i = i->next;
}
while(j && ((prod >= 1) || (i == 0)))
{
prod *= j->value;
j = j->next;
while(j && j->value >= 1)
j = j->next;
}
}
return prod;
}
template <class T, class Policy>
inline T hypergeometric_pdf_prime_imp(unsigned x, unsigned r, unsigned n, unsigned N, const Policy&)
{
hypergeometric_pdf_prime_loop_result_entry<T> result = { 1, 0 };
hypergeometric_pdf_prime_loop_data data = { x, r, n, N, 0, prime(0) };
return hypergeometric_pdf_prime_loop_imp<T>(data, result);
}
template <class T, class Policy>
T hypergeometric_pdf_factorial_imp(unsigned x, unsigned r, unsigned n, unsigned N, const Policy&)
{
BOOST_MATH_STD_USING
BOOST_ASSERT(N < boost::math::max_factorial<T>::value);
T result = boost::math::unchecked_factorial<T>(n);
T num[3] = {
boost::math::unchecked_factorial<T>(r),
boost::math::unchecked_factorial<T>(N - n),
boost::math::unchecked_factorial<T>(N - r)
};
T denom[5] = {
boost::math::unchecked_factorial<T>(N),
boost::math::unchecked_factorial<T>(x),
boost::math::unchecked_factorial<T>(n - x),
boost::math::unchecked_factorial<T>(r - x),
boost::math::unchecked_factorial<T>(N - n - r + x)
};
int i = 0;
int j = 0;
while((i < 3) || (j < 5))
{
while((j < 5) && ((result >= 1) || (i >= 3)))
{
result /= denom[j];
++j;
}
while((i < 3) && ((result <= 1) || (j >= 5)))
{
result *= num[i];
++i;
}
}
return result;
}
template <class T, class Policy>
inline typename tools::promote_args<T>::type
hypergeometric_pdf(unsigned x, unsigned r, unsigned n, unsigned N, const Policy&)
{
BOOST_FPU_EXCEPTION_GUARD
typedef typename tools::promote_args<T>::type result_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
value_type result;
if(N <= boost::math::max_factorial<value_type>::value)
{
//
// If N is small enough then we can evaluate the PDF via the factorials
// directly: table lookup of the factorials gives the best performance
// of the methods available:
//
result = detail::hypergeometric_pdf_factorial_imp<value_type>(x, r, n, N, forwarding_policy());
}
else if(N <= boost::math::prime(boost::math::max_prime - 1))
{
//
// If N is no larger than the largest prime number in our lookup table
// (104729) then we can use prime factorisation to evaluate the PDF,
// this is slow but accurate:
//
result = detail::hypergeometric_pdf_prime_imp<value_type>(x, r, n, N, forwarding_policy());
}
else
{
//
// Catch all case - use the lanczos approximation - where available -
// to evaluate the ratio of factorials. This is reasonably fast
// (almost as quick as using logarithmic evaluation in terms of lgamma)
// but only a few digits better in accuracy than using lgamma:
//
result = detail::hypergeometric_pdf_lanczos_imp(value_type(), x, r, n, N, evaluation_type(), forwarding_policy());
}
if(result > 1)
{
result = 1;
}
if(result < 0)
{
result = 0;
}
return policies::checked_narrowing_cast<result_type, forwarding_policy>(result, "boost::math::hypergeometric_pdf<%1%>(%1%,%1%,%1%,%1%)");
}
}}} // namespaces
#endif

View File

@@ -1,692 +0,0 @@
// Copyright John Maddock 2007.
// Copyright Paul A. Bristow 2007.
// 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)
#ifndef BOOST_MATH_POLICY_ERROR_HANDLING_HPP
#define BOOST_MATH_POLICY_ERROR_HANDLING_HPP
#include <stdexcept>
#include <iomanip>
#include <string>
#include <cerrno>
#include <complex>
#include <boost/config/no_tr1/cmath.hpp>
#include <stdexcept>
#include <boost/math/tools/config.hpp>
#include <boost/math/policies/policy.hpp>
#include <boost/math/tools/precision.hpp>
#include <boost/cstdint.hpp>
#ifdef BOOST_MSVC
# pragma warning(push) // Quiet warnings in boost/format.hpp
# pragma warning(disable: 4996) // _SCL_SECURE_NO_DEPRECATE
# pragma warning(disable: 4512) // assignment operator could not be generated.
// And warnings in error handling:
# pragma warning(disable: 4702) // unreachable code
// Note that this only occurs when the compiler can deduce code is unreachable,
// for example when policy macros are used to ignore errors rather than throw.
#endif
#include <boost/format.hpp>
#include <boost/type_index.hpp>
namespace boost{ namespace math{
class evaluation_error : public std::runtime_error
{
public:
evaluation_error(const std::string& s) : std::runtime_error(s){}
};
class rounding_error : public std::runtime_error
{
public:
rounding_error(const std::string& s) : std::runtime_error(s){}
};
namespace policies{
//
// Forward declarations of user error handlers,
// it's up to the user to provide the definition of these:
//
template <class T>
T user_domain_error(const char* function, const char* message, const T& val);
template <class T>
T user_pole_error(const char* function, const char* message, const T& val);
template <class T>
T user_overflow_error(const char* function, const char* message, const T& val);
template <class T>
T user_underflow_error(const char* function, const char* message, const T& val);
template <class T>
T user_denorm_error(const char* function, const char* message, const T& val);
template <class T>
T user_evaluation_error(const char* function, const char* message, const T& val);
template <class T, class TargetType>
T user_rounding_error(const char* function, const char* message, const T& val, const TargetType& t);
template <class T>
T user_indeterminate_result_error(const char* function, const char* message, const T& val);
namespace detail
{
//
// Helper function to avoid binding rvalue to non-const-reference,
// in other words a warning suppression mechansim:
//
template <class Formatter, class Group>
inline std::string do_format(Formatter f, const Group& g)
{
return (f % g).str();
}
template <class E, class T>
void raise_error(const char* function, const char* message)
{
if(function == 0)
function = "Unknown function operating on type %1%";
if(message == 0)
message = "Cause unknown";
std::string msg("Error in function ");
msg += (boost::format(function) % type_id<T>().name_demangled()).str();
msg += ": ";
msg += message;
E e(msg);
boost::throw_exception(e);
}
template <class E, class T>
void raise_error(const char* function, const char* message, const T& val)
{
if(function == 0)
function = "Unknown function operating on type %1%";
if(message == 0)
message = "Cause unknown: error caused by bad argument with value %1%";
std::string msg("Error in function ");
msg += (boost::format(function) % type_id<T>().name_demangled()).str();
msg += ": ";
msg += message;
int prec = 2 + (boost::math::policies::digits<T, boost::math::policies::policy<> >() * 30103UL) / 100000UL;
msg = do_format(boost::format(msg), boost::io::group(std::setprecision(prec), val));
E e(msg);
boost::throw_exception(e);
}
template <class T>
inline T raise_domain_error(
const char* function,
const char* message,
const T& val,
const ::boost::math::policies::domain_error< ::boost::math::policies::throw_on_error>&)
{
raise_error<std::domain_error, T>(function, message, val);
// we never get here:
return std::numeric_limits<T>::quiet_NaN();
}
template <class T>
inline T raise_domain_error(
const char* ,
const char* ,
const T& ,
const ::boost::math::policies::domain_error< ::boost::math::policies::ignore_error>&)
{
// This may or may not do the right thing, but the user asked for the error
// to be ignored so here we go anyway:
return std::numeric_limits<T>::quiet_NaN();
}
template <class T>
inline T raise_domain_error(
const char* ,
const char* ,
const T& ,
const ::boost::math::policies::domain_error< ::boost::math::policies::errno_on_error>&)
{
errno = EDOM;
// This may or may not do the right thing, but the user asked for the error
// to be silent so here we go anyway:
return std::numeric_limits<T>::quiet_NaN();
}
template <class T>
inline T raise_domain_error(
const char* function,
const char* message,
const T& val,
const ::boost::math::policies::domain_error< ::boost::math::policies::user_error>&)
{
return user_domain_error(function, message, val);
}
template <class T>
inline T raise_pole_error(
const char* function,
const char* message,
const T& val,
const ::boost::math::policies::pole_error< ::boost::math::policies::throw_on_error>&)
{
return boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::throw_on_error>());
}
template <class T>
inline T raise_pole_error(
const char* function,
const char* message,
const T& val,
const ::boost::math::policies::pole_error< ::boost::math::policies::ignore_error>&)
{
return ::boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::ignore_error>());
}
template <class T>
inline T raise_pole_error(
const char* function,
const char* message,
const T& val,
const ::boost::math::policies::pole_error< ::boost::math::policies::errno_on_error>&)
{
return ::boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::errno_on_error>());
}
template <class T>
inline T raise_pole_error(
const char* function,
const char* message,
const T& val,
const ::boost::math::policies::pole_error< ::boost::math::policies::user_error>&)
{
return user_pole_error(function, message, val);
}
template <class T>
inline T raise_overflow_error(
const char* function,
const char* message,
const ::boost::math::policies::overflow_error< ::boost::math::policies::throw_on_error>&)
{
raise_error<std::overflow_error, T>(function, message ? message : "numeric overflow");
// we never get here:
return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
}
template <class T>
inline T raise_overflow_error(
const char* ,
const char* ,
const ::boost::math::policies::overflow_error< ::boost::math::policies::ignore_error>&)
{
// This may or may not do the right thing, but the user asked for the error
// to be ignored so here we go anyway:
return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
}
template <class T>
inline T raise_overflow_error(
const char* ,
const char* ,
const ::boost::math::policies::overflow_error< ::boost::math::policies::errno_on_error>&)
{
errno = ERANGE;
// This may or may not do the right thing, but the user asked for the error
// to be silent so here we go anyway:
return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
}
template <class T>
inline T raise_overflow_error(
const char* function,
const char* message,
const ::boost::math::policies::overflow_error< ::boost::math::policies::user_error>&)
{
return user_overflow_error(function, message, std::numeric_limits<T>::infinity());
}
template <class T>
inline T raise_underflow_error(
const char* function,
const char* message,
const ::boost::math::policies::underflow_error< ::boost::math::policies::throw_on_error>&)
{
raise_error<std::underflow_error, T>(function, message ? message : "numeric underflow");
// we never get here:
return 0;
}
template <class T>
inline T raise_underflow_error(
const char* ,
const char* ,
const ::boost::math::policies::underflow_error< ::boost::math::policies::ignore_error>&)
{
// This may or may not do the right thing, but the user asked for the error
// to be ignored so here we go anyway:
return T(0);
}
template <class T>
inline T raise_underflow_error(
const char* /* function */,
const char* /* message */,
const ::boost::math::policies::underflow_error< ::boost::math::policies::errno_on_error>&)
{
errno = ERANGE;
// This may or may not do the right thing, but the user asked for the error
// to be silent so here we go anyway:
return T(0);
}
template <class T>
inline T raise_underflow_error(
const char* function,
const char* message,
const ::boost::math::policies::underflow_error< ::boost::math::policies::user_error>&)
{
return user_underflow_error(function, message, T(0));
}
template <class T>
inline T raise_denorm_error(
const char* function,
const char* message,
const T& /* val */,
const ::boost::math::policies::denorm_error< ::boost::math::policies::throw_on_error>&)
{
raise_error<std::underflow_error, T>(function, message ? message : "denormalised result");
// we never get here:
return T(0);
}
template <class T>
inline T raise_denorm_error(
const char* ,
const char* ,
const T& val,
const ::boost::math::policies::denorm_error< ::boost::math::policies::ignore_error>&)
{
// This may or may not do the right thing, but the user asked for the error
// to be ignored so here we go anyway:
return val;
}
template <class T>
inline T raise_denorm_error(
const char* ,
const char* ,
const T& val,
const ::boost::math::policies::denorm_error< ::boost::math::policies::errno_on_error>&)
{
errno = ERANGE;
// This may or may not do the right thing, but the user asked for the error
// to be silent so here we go anyway:
return val;
}
template <class T>
inline T raise_denorm_error(
const char* function,
const char* message,
const T& val,
const ::boost::math::policies::denorm_error< ::boost::math::policies::user_error>&)
{
return user_denorm_error(function, message, val);
}
template <class T>
inline T raise_evaluation_error(
const char* function,
const char* message,
const T& val,
const ::boost::math::policies::evaluation_error< ::boost::math::policies::throw_on_error>&)
{
raise_error<boost::math::evaluation_error, T>(function, message, val);
// we never get here:
return T(0);
}
template <class T>
inline T raise_evaluation_error(
const char* ,
const char* ,
const T& val,
const ::boost::math::policies::evaluation_error< ::boost::math::policies::ignore_error>&)
{
// This may or may not do the right thing, but the user asked for the error
// to be ignored so here we go anyway:
return val;
}
template <class T>
inline T raise_evaluation_error(
const char* ,
const char* ,
const T& val,
const ::boost::math::policies::evaluation_error< ::boost::math::policies::errno_on_error>&)
{
errno = EDOM;
// This may or may not do the right thing, but the user asked for the error
// to be silent so here we go anyway:
return val;
}
template <class T>
inline T raise_evaluation_error(
const char* function,
const char* message,
const T& val,
const ::boost::math::policies::evaluation_error< ::boost::math::policies::user_error>&)
{
return user_evaluation_error(function, message, val);
}
template <class T, class TargetType>
inline T raise_rounding_error(
const char* function,
const char* message,
const T& val,
const TargetType&,
const ::boost::math::policies::rounding_error< ::boost::math::policies::throw_on_error>&)
{
raise_error<boost::math::rounding_error, T>(function, message, val);
// we never get here:
return T(0);
}
template <class T, class TargetType>
inline T raise_rounding_error(
const char* ,
const char* ,
const T& val,
const TargetType&,
const ::boost::math::policies::rounding_error< ::boost::math::policies::ignore_error>&)
{
// This may or may not do the right thing, but the user asked for the error
// to be ignored so here we go anyway:
return std::numeric_limits<T>::is_specialized ? (val > 0 ? (std::numeric_limits<T>::max)() : -(std::numeric_limits<T>::max)()): val;
}
template <class T, class TargetType>
inline T raise_rounding_error(
const char* ,
const char* ,
const T& val,
const TargetType&,
const ::boost::math::policies::rounding_error< ::boost::math::policies::errno_on_error>&)
{
errno = ERANGE;
// This may or may not do the right thing, but the user asked for the error
// to be silent so here we go anyway:
return std::numeric_limits<T>::is_specialized ? (val > 0 ? (std::numeric_limits<T>::max)() : -(std::numeric_limits<T>::max)()): val;
}
template <class T, class TargetType>
inline T raise_rounding_error(
const char* function,
const char* message,
const T& val,
const TargetType& t,
const ::boost::math::policies::rounding_error< ::boost::math::policies::user_error>&)
{
return user_rounding_error(function, message, val, t);
}
template <class T, class R>
inline T raise_indeterminate_result_error(
const char* function,
const char* message,
const T& val,
const R& ,
const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::throw_on_error>&)
{
raise_error<std::domain_error, T>(function, message, val);
// we never get here:
return std::numeric_limits<T>::quiet_NaN();
}
template <class T, class R>
inline T raise_indeterminate_result_error(
const char* ,
const char* ,
const T& ,
const R& result,
const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::ignore_error>&)
{
// This may or may not do the right thing, but the user asked for the error
// to be ignored so here we go anyway:
return result;
}
template <class T, class R>
inline T raise_indeterminate_result_error(
const char* ,
const char* ,
const T& ,
const R& result,
const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::errno_on_error>&)
{
errno = EDOM;
// This may or may not do the right thing, but the user asked for the error
// to be silent so here we go anyway:
return result;
}
template <class T, class R>
inline T raise_indeterminate_result_error(
const char* function,
const char* message,
const T& val,
const R& ,
const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::user_error>&)
{
return user_indeterminate_result_error(function, message, val);
}
} // namespace detail
template <class T, class Policy>
inline T raise_domain_error(const char* function, const char* message, const T& val, const Policy&)
{
typedef typename Policy::domain_error_type policy_type;
return detail::raise_domain_error(
function, message ? message : "Domain Error evaluating function at %1%",
val, policy_type());
}
template <class T, class Policy>
inline T raise_pole_error(const char* function, const char* message, const T& val, const Policy&)
{
typedef typename Policy::pole_error_type policy_type;
return detail::raise_pole_error(
function, message ? message : "Evaluation of function at pole %1%",
val, policy_type());
}
template <class T, class Policy>
inline T raise_overflow_error(const char* function, const char* message, const Policy&)
{
typedef typename Policy::overflow_error_type policy_type;
return detail::raise_overflow_error<T>(
function, message ? message : "Overflow Error",
policy_type());
}
template <class T, class Policy>
inline T raise_underflow_error(const char* function, const char* message, const Policy&)
{
typedef typename Policy::underflow_error_type policy_type;
return detail::raise_underflow_error<T>(
function, message ? message : "Underflow Error",
policy_type());
}
template <class T, class Policy>
inline T raise_denorm_error(const char* function, const char* message, const T& val, const Policy&)
{
typedef typename Policy::denorm_error_type policy_type;
return detail::raise_denorm_error<T>(
function, message ? message : "Denorm Error",
val,
policy_type());
}
template <class T, class Policy>
inline T raise_evaluation_error(const char* function, const char* message, const T& val, const Policy&)
{
typedef typename Policy::evaluation_error_type policy_type;
return detail::raise_evaluation_error(
function, message ? message : "Internal Evaluation Error, best value so far was %1%",
val, policy_type());
}
template <class T, class TargetType, class Policy>
inline T raise_rounding_error(const char* function, const char* message, const T& val, const TargetType& t, const Policy&)
{
typedef typename Policy::rounding_error_type policy_type;
return detail::raise_rounding_error(
function, message ? message : "Value %1% can not be represented in the target integer type.",
val, t, policy_type());
}
template <class T, class R, class Policy>
inline T raise_indeterminate_result_error(const char* function, const char* message, const T& val, const R& result, const Policy&)
{
typedef typename Policy::indeterminate_result_error_type policy_type;
return detail::raise_indeterminate_result_error(
function, message ? message : "Indeterminate result with value %1%",
val, result, policy_type());
}
//
// checked_narrowing_cast:
//
namespace detail
{
template <class R, class T, class Policy>
inline bool check_overflow(T val, R* result, const char* function, const Policy& pol)
{
BOOST_MATH_STD_USING
if(fabs(val) > tools::max_value<R>())
{
*result = static_cast<R>(boost::math::policies::detail::raise_overflow_error<R>(function, 0, pol));
return true;
}
return false;
}
template <class R, class T, class Policy>
inline bool check_overflow(std::complex<T> val, R* result, const char* function, const Policy& pol)
{
typedef typename R::value_type r_type;
r_type re, im;
bool r = check_overflow<r_type>(val.real(), &re, function, pol) || check_overflow<r_type>(val.imag(), &im, function, pol);
*result = R(re, im);
return r;
}
template <class R, class T, class Policy>
inline bool check_underflow(T val, R* result, const char* function, const Policy& pol)
{
if((val != 0) && (static_cast<R>(val) == 0))
{
*result = static_cast<R>(boost::math::policies::detail::raise_underflow_error<R>(function, 0, pol));
return true;
}
return false;
}
template <class R, class T, class Policy>
inline bool check_underflow(std::complex<T> val, R* result, const char* function, const Policy& pol)
{
typedef typename R::value_type r_type;
r_type re, im;
bool r = check_underflow<r_type>(val.real(), &re, function, pol) || check_underflow<r_type>(val.imag(), &im, function, pol);
*result = R(re, im);
return r;
}
template <class R, class T, class Policy>
inline bool check_denorm(T val, R* result, const char* function, const Policy& pol)
{
BOOST_MATH_STD_USING
if((fabs(val) < static_cast<T>(tools::min_value<R>())) && (static_cast<R>(val) != 0))
{
*result = static_cast<R>(boost::math::policies::detail::raise_denorm_error<R>(function, 0, static_cast<R>(val), pol));
return true;
}
return false;
}
template <class R, class T, class Policy>
inline bool check_denorm(std::complex<T> val, R* result, const char* function, const Policy& pol)
{
typedef typename R::value_type r_type;
r_type re, im;
bool r = check_denorm<r_type>(val.real(), &re, function, pol) || check_denorm<r_type>(val.imag(), &im, function, pol);
*result = R(re, im);
return r;
}
// Default instantiations with ignore_error policy.
template <class R, class T>
inline bool check_overflow(T /* val */, R* /* result */, const char* /* function */, const overflow_error<ignore_error>&){ return false; }
template <class R, class T>
inline bool check_overflow(std::complex<T> /* val */, R* /* result */, const char* /* function */, const overflow_error<ignore_error>&){ return false; }
template <class R, class T>
inline bool check_underflow(T /* val */, R* /* result */, const char* /* function */, const underflow_error<ignore_error>&){ return false; }
template <class R, class T>
inline bool check_underflow(std::complex<T> /* val */, R* /* result */, const char* /* function */, const underflow_error<ignore_error>&){ return false; }
template <class R, class T>
inline bool check_denorm(T /* val */, R* /* result*/, const char* /* function */, const denorm_error<ignore_error>&){ return false; }
template <class R, class T>
inline bool check_denorm(std::complex<T> /* val */, R* /* result*/, const char* /* function */, const denorm_error<ignore_error>&){ return false; }
} // namespace detail
template <class R, class Policy, class T>
inline R checked_narrowing_cast(T val, const char* function)
{
typedef typename Policy::overflow_error_type overflow_type;
typedef typename Policy::underflow_error_type underflow_type;
typedef typename Policy::denorm_error_type denorm_type;
//
// Most of what follows will evaluate to a no-op:
//
R result = 0;
if(detail::check_overflow<R>(val, &result, function, overflow_type()))
return result;
if(detail::check_underflow<R>(val, &result, function, underflow_type()))
return result;
if(detail::check_denorm<R>(val, &result, function, denorm_type()))
return result;
return static_cast<R>(val);
}
template <class T, class Policy>
inline void check_series_iterations(const char* function, boost::uintmax_t max_iter, const Policy& pol)
{
if(max_iter >= policies::get_max_series_iterations<Policy>())
raise_evaluation_error<T>(
function,
"Series evaluation exceeded %1% iterations, giving up now.", static_cast<T>(static_cast<double>(max_iter)), pol);
}
template <class T, class Policy>
inline void check_root_iterations(const char* function, boost::uintmax_t max_iter, const Policy& pol)
{
if(max_iter >= policies::get_max_root_iterations<Policy>())
raise_evaluation_error<T>(
function,
"Root finding evaluation exceeded %1% iterations, giving up now.", static_cast<T>(static_cast<double>(max_iter)), pol);
}
} //namespace policies
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
}} // namespaces boost/math
#endif // BOOST_MATH_POLICY_ERROR_HANDLING_HPP

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,69 +0,0 @@
// Copyright 2008 Christophe Henry
// henry UNDERSCORE christophe AT hotmail DOT com
// This is an extended version of the state machine available in the boost::mpl library
// Distributed under the same license as the original.
// Copyright for the original version:
// Copyright 2005 David Abrahams and Aleksey Gurtovoy. 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_MSM_BACK_TOOLS_H
#define BOOST_MSM_BACK_TOOLS_H
#include <string>
#include <iostream>
#include <boost/msm/back/common_types.hpp>
#include <boost/msm/back/metafunctions.hpp>
#include <boost/type_index.hpp>
namespace boost { namespace msm { namespace back
{
// fills the array passed in with the state names in the correct order
// the array must be big enough. To know the needed size, use mpl::size
// on fsm::generate_state_set
template <class stt>
struct fill_state_names
{
fill_state_names(char const** names):m_names(names){}
template <class StateType>
void operator()(boost::msm::wrap<StateType> const&)
{
m_names[get_state_id<stt,StateType>::value]= type_id<StateType>().name_demangled();
}
private:
char const** m_names;
};
// fills the typeid-generated name of the given state in the string passed as argument
template <class stt>
struct get_state_name
{
get_state_name(std::string& name_to_fill, int state_id):m_name(name_to_fill),m_state_id(state_id){}
template <class StateType>
void operator()(boost::msm::wrap<StateType> const&)
{
if (get_state_id<stt,StateType>::value == m_state_id)
{
m_name = type_id<StateType>().name_demangled();
}
}
private:
std::string& m_name;
int m_state_id;
};
// displays the typeid of the given Type
struct display_type
{
template <class Type>
void operator()(boost::msm::wrap<Type> const&)
{
std::cout << type_id<Type>().name_demangled() << std::endl;
}
};
} } }//boost::msm::back
#endif //BOOST_MSM_BACK_TOOLS_H

View File

@@ -1,345 +0,0 @@
#ifndef DYNAMIC_PROPERTY_MAP_RG09302004_HPP
#define DYNAMIC_PROPERTY_MAP_RG09302004_HPP
// Copyright 2004-5 The Trustees of Indiana University.
// Use, modification and distribution is 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)
// dynamic_property_map.hpp -
// Support for runtime-polymorphic property maps. This header is factored
// out of Doug Gregor's routines for reading GraphML files for use in reading
// GraphViz graph files.
// Authors: Doug Gregor
// Ronald Garcia
//
#include <boost/config.hpp>
#include <boost/throw_exception.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/any.hpp>
#include <boost/function/function3.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <typeinfo>
#include <boost/mpl/bool.hpp>
#include <stdexcept>
#include <sstream>
#include <map>
#include <boost/type.hpp>
#include <boost/smart_ptr.hpp>
#include <boost/type_index.hpp>
namespace boost {
namespace detail {
// read_value -
// A wrapper around lexical_cast, which does not behave as
// desired for std::string types.
template<typename Value>
inline Value read_value(const std::string& value)
{ return boost::lexical_cast<Value>(value); }
template<>
inline std::string read_value<std::string>(const std::string& value)
{ return value; }
}
// dynamic_property_map -
// This interface supports polymorphic manipulation of property maps.
class dynamic_property_map
{
public:
virtual ~dynamic_property_map() { }
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 type_index key() const = 0;
virtual type_index value() const = 0;
};
//////////////////////////////////////////////////////////////////////
// Property map exceptions
//////////////////////////////////////////////////////////////////////
struct dynamic_property_exception : public std::exception {
virtual ~dynamic_property_exception() throw() {}
virtual const char* what() const throw() = 0;
};
struct property_not_found : public dynamic_property_exception {
std::string property;
mutable std::string statement;
property_not_found(const std::string& property) : property(property) {}
virtual ~property_not_found() throw() {}
const char* what() const throw() {
if(statement.empty())
statement =
std::string("Property not found: ") + property + ".";
return statement.c_str();
}
};
struct dynamic_get_failure : public dynamic_property_exception {
std::string property;
mutable std::string statement;
dynamic_get_failure(const std::string& property) : property(property) {}
virtual ~dynamic_get_failure() throw() {}
const char* what() const throw() {
if(statement.empty())
statement =
std::string(
"dynamic property get cannot retrieve value for property: ")
+ property + ".";
return statement.c_str();
}
};
struct dynamic_const_put_error : public dynamic_property_exception {
virtual ~dynamic_const_put_error() throw() {}
const char* what() const throw() {
return "Attempt to put a value into a const property map: ";
}
};
namespace detail {
// Trying to work around VC++ problem that seems to relate to having too many
// functions named "get"
template <typename PMap, typename Key>
typename boost::property_traits<PMap>::reference
get_wrapper_xxx(const PMap& pmap, const Key& key) {
using boost::get;
return get(pmap, key);
}
//
// dynamic_property_map_adaptor -
// property-map adaptor to support runtime polymorphism.
template<typename PropertyMap>
class dynamic_property_map_adaptor : public dynamic_property_map
{
typedef typename property_traits<PropertyMap>::key_type key_type;
typedef typename property_traits<PropertyMap>::value_type value_type;
typedef typename property_traits<PropertyMap>::category category;
// do_put - overloaded dispatches from the put() member function.
// Attempts to "put" to a property map that does not model
// WritablePropertyMap result in a runtime exception.
// in_value must either hold an object of value_type or a string that
// can be converted to value_type via iostreams.
void do_put(const any& in_key, const any& in_value, mpl::bool_<true>)
{
using boost::put;
key_type key = any_cast<key_type>(in_key);
if (in_value.type() == 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.
std::string v = any_cast<std::string>(in_value);
if (v.empty()) {
put(property_map_, key, value_type());
} else {
put(property_map_, key, detail::read_value<value_type>(v));
}
}
}
void do_put(const any&, const any&, mpl::bool_<false>)
{
BOOST_THROW_EXCEPTION(dynamic_const_put_error());
}
public:
explicit dynamic_property_map_adaptor(const PropertyMap& property_map_)
: property_map_(property_map_) { }
virtual boost::any get(const any& key)
{
return get_wrapper_xxx(property_map_, any_cast<key_type>(key));
}
virtual std::string get_string(const any& key)
{
std::ostringstream out;
out << get_wrapper_xxx(property_map_, any_cast<key_type>(key));
return out.str();
}
virtual void put(const any& in_key, const any& in_value)
{
do_put(in_key, in_value,
mpl::bool_<(is_convertible<category*,
writable_property_map_tag*>::value)>());
}
virtual type_index key() const { return type_id<key_type>(); }
virtual type_index value() const { return type_id<value_type>(); }
PropertyMap& base() { return property_map_; }
const PropertyMap& base() const { return property_map_; }
private:
PropertyMap property_map_;
};
} // namespace detail
//
// dynamic_properties -
// container for dynamic property maps
//
struct dynamic_properties
{
typedef std::multimap<std::string, boost::shared_ptr<dynamic_property_map> >
property_maps_type;
typedef boost::function3<boost::shared_ptr<dynamic_property_map>,
const std::string&,
const boost::any&,
const boost::any&> generate_fn_type;
public:
typedef property_maps_type::iterator iterator;
typedef property_maps_type::const_iterator const_iterator;
dynamic_properties() : generate_fn() { }
dynamic_properties(const generate_fn_type& g) : generate_fn(g) {}
~dynamic_properties() {}
template<typename PropertyMap>
dynamic_properties&
property(const std::string& name, PropertyMap property_map_)
{
boost::shared_ptr<dynamic_property_map> pm(
boost::make_shared<detail::dynamic_property_map_adaptor<PropertyMap> >(property_map_));
property_maps.insert(property_maps_type::value_type(name, pm));
return *this;
}
iterator begin() { return property_maps.begin(); }
const_iterator begin() const { return property_maps.begin(); }
iterator end() { return property_maps.end(); }
const_iterator end() const { return property_maps.end(); }
iterator lower_bound(const std::string& name)
{ return property_maps.lower_bound(name); }
const_iterator lower_bound(const std::string& name) const
{ return property_maps.lower_bound(name); }
void
insert(const std::string& name, boost::shared_ptr<dynamic_property_map> pm)
{
property_maps.insert(property_maps_type::value_type(name, pm));
}
template<typename Key, typename Value>
boost::shared_ptr<dynamic_property_map>
generate(const std::string& name, const Key& key, const Value& value)
{
if(!generate_fn) {
BOOST_THROW_EXCEPTION(property_not_found(name));
} else {
return generate_fn(name,key,value);
}
}
private:
property_maps_type property_maps;
generate_fn_type generate_fn;
};
template<typename Key, typename Value>
bool
put(const std::string& name, dynamic_properties& dp, const Key& key,
const Value& value)
{
for (dynamic_properties::iterator i = dp.lower_bound(name);
i != dp.end() && i->first == name; ++i) {
if (i->second->key() == type_id<key>()) {
i->second->put(key, value);
return true;
}
}
boost::shared_ptr<dynamic_property_map> new_map = dp.generate(name, key, value);
if (new_map.get()) {
new_map->put(key, value);
dp.insert(name, new_map);
return true;
} else {
return false;
}
}
#ifndef BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS
template<typename Value, typename Key>
Value
get(const std::string& name, const dynamic_properties& dp, const Key& key)
{
for (dynamic_properties::const_iterator i = dp.lower_bound(name);
i != dp.end() && i->first == name; ++i) {
if (i->second->key() == type_id<key>())
return any_cast<Value>(i->second->get(key));
}
BOOST_THROW_EXCEPTION(dynamic_get_failure(name));
}
#endif
template<typename Value, typename Key>
Value
get(const std::string& name, const dynamic_properties& dp, const Key& key, type<Value>)
{
for (dynamic_properties::const_iterator i = dp.lower_bound(name);
i != dp.end() && i->first == name; ++i) {
if (i->second->key() == type_id<key>())
return any_cast<Value>(i->second->get(key));
}
BOOST_THROW_EXCEPTION(dynamic_get_failure(name));
}
template<typename Key>
std::string
get(const std::string& name, const dynamic_properties& dp, const Key& key)
{
for (dynamic_properties::const_iterator i = dp.lower_bound(name);
i != dp.end() && i->first == name; ++i) {
if (i->second->key() == type_id<key>())
return i->second->get_string(key);
}
BOOST_THROW_EXCEPTION(dynamic_get_failure(name));
}
// The easy way to ignore properties.
inline
boost::shared_ptr<boost::dynamic_property_map>
ignore_other_properties(const std::string&,
const boost::any&,
const boost::any&) {
return boost::shared_ptr<boost::dynamic_property_map>();
}
} // namespace boost
#endif // DYNAMIC_PROPERTY_MAP_RG09302004_HPP

View File

@@ -1,915 +0,0 @@
// ----------------------------------------------------------------------------
// Copyright (C) 2002-2006 Marcin Kalicinski
// Copyright (C) 2009 Sebastian Redl
//
// 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)
//
// For more information, see www.boost.org
// ----------------------------------------------------------------------------
#ifndef BOOST_PROPERTY_TREE_DETAIL_PTREE_IMPLEMENTATION_HPP_INCLUDED
#define BOOST_PROPERTY_TREE_DETAIL_PTREE_IMPLEMENTATION_HPP_INCLUDED
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/iterator/reverse_iterator.hpp>
#include <boost/assert.hpp>
#include <boost/type_index.hpp>
#include <boost/utility/swap.hpp>
#include <memory>
#if (defined(BOOST_MSVC) && \
(_MSC_FULL_VER >= 160000000 && _MSC_FULL_VER < 170000000)) || \
(defined(BOOST_INTEL_WIN) && \
defined(BOOST_DINKUMWARE_STDLIB))
#define BOOST_PROPERTY_TREE_PAIR_BUG
#endif
namespace boost { namespace property_tree
{
template <class K, class D, class C>
struct basic_ptree<K, D, C>::subs
{
struct by_name {};
// The actual child container.
#if defined(BOOST_PROPERTY_TREE_PAIR_BUG)
// MSVC 10 has moved std::pair's members to a base
// class. Unfortunately this does break the interface.
BOOST_STATIC_CONSTANT(unsigned,
first_offset = offsetof(value_type, first));
#endif
typedef multi_index_container<value_type,
multi_index::indexed_by<
multi_index::sequenced<>,
multi_index::ordered_non_unique<multi_index::tag<by_name>,
#if defined(BOOST_PROPERTY_TREE_PAIR_BUG)
multi_index::member_offset<value_type, const key_type,
first_offset>,
#else
multi_index::member<value_type, const key_type,
&value_type::first>,
#endif
key_compare
>
>
> base_container;
// The by-name lookup index.
typedef typename base_container::template index<by_name>::type
by_name_index;
// Access functions for getting to the children of a tree.
static base_container& ch(self_type *s) {
return *static_cast<base_container*>(s->m_children);
}
static const base_container& ch(const self_type *s) {
return *static_cast<const base_container*>(s->m_children);
}
static by_name_index& assoc(self_type *s) {
return ch(s).BOOST_NESTED_TEMPLATE get<by_name>();
}
static const by_name_index& assoc(const self_type *s) {
return ch(s).BOOST_NESTED_TEMPLATE get<by_name>();
}
};
template <class K, class D, class C>
class basic_ptree<K, D, C>::iterator : public boost::iterator_adaptor<
iterator, typename subs::base_container::iterator, value_type>
{
friend class boost::iterator_core_access;
typedef boost::iterator_adaptor<
iterator, typename subs::base_container::iterator, value_type>
baset;
public:
typedef typename baset::reference reference;
iterator() {}
explicit iterator(typename iterator::base_type b)
: iterator::iterator_adaptor_(b)
{}
reference dereference() const
{
// multi_index doesn't allow modification of its values, because
// indexes could sort by anything, and modification screws that up.
// However, we only sort by the key, and it's protected against
// modification in the value_type, so this const_cast is safe.
return const_cast<reference>(*this->base_reference());
}
};
template <class K, class D, class C>
class basic_ptree<K, D, C>::const_iterator : public boost::iterator_adaptor<
const_iterator, typename subs::base_container::const_iterator>
{
public:
const_iterator() {}
explicit const_iterator(typename const_iterator::base_type b)
: const_iterator::iterator_adaptor_(b)
{}
const_iterator(iterator b)
: const_iterator::iterator_adaptor_(b.base())
{}
};
template <class K, class D, class C>
class basic_ptree<K, D, C>::reverse_iterator
: public boost::reverse_iterator<iterator>
{
public:
reverse_iterator() {}
explicit reverse_iterator(iterator b)
: boost::reverse_iterator<iterator>(b)
{}
};
template <class K, class D, class C>
class basic_ptree<K, D, C>::const_reverse_iterator
: public boost::reverse_iterator<const_iterator>
{
public:
const_reverse_iterator() {}
explicit const_reverse_iterator(const_iterator b)
: boost::reverse_iterator<const_iterator>(b)
{}
const_reverse_iterator(
typename basic_ptree<K, D, C>::reverse_iterator b)
: boost::reverse_iterator<const_iterator>(b)
{}
};
template <class K, class D, class C>
class basic_ptree<K, D, C>::assoc_iterator
: public boost::iterator_adaptor<assoc_iterator,
typename subs::by_name_index::iterator,
value_type>
{
friend class boost::iterator_core_access;
typedef boost::iterator_adaptor<assoc_iterator,
typename subs::by_name_index::iterator,
value_type>
baset;
public:
typedef typename baset::reference reference;
assoc_iterator() {}
explicit assoc_iterator(typename assoc_iterator::base_type b)
: assoc_iterator::iterator_adaptor_(b)
{}
reference dereference() const
{
return const_cast<reference>(*this->base_reference());
}
};
template <class K, class D, class C>
class basic_ptree<K, D, C>::const_assoc_iterator
: public boost::iterator_adaptor<const_assoc_iterator,
typename subs::by_name_index::const_iterator>
{
public:
const_assoc_iterator() {}
explicit const_assoc_iterator(
typename const_assoc_iterator::base_type b)
: const_assoc_iterator::iterator_adaptor_(b)
{}
const_assoc_iterator(assoc_iterator b)
: const_assoc_iterator::iterator_adaptor_(b.base())
{}
};
// Big five
// Perhaps the children collection could be created on-demand only, to
// reduce heap traffic. But that's a lot more work to implement.
template<class K, class D, class C> inline
basic_ptree<K, D, C>::basic_ptree()
: m_children(new typename subs::base_container)
{
}
template<class K, class D, class C> inline
basic_ptree<K, D, C>::basic_ptree(const data_type &d)
: m_data(d), m_children(new typename subs::base_container)
{
}
template<class K, class D, class C> inline
basic_ptree<K, D, C>::basic_ptree(const basic_ptree<K, D, C> &rhs)
: m_data(rhs.m_data),
m_children(new typename subs::base_container(subs::ch(&rhs)))
{
}
template<class K, class D, class C>
basic_ptree<K, D, C> &
basic_ptree<K, D, C>::operator =(const basic_ptree<K, D, C> &rhs)
{
self_type(rhs).swap(*this);
return *this;
}
template<class K, class D, class C>
basic_ptree<K, D, C>::~basic_ptree()
{
delete &subs::ch(this);
}
template<class K, class D, class C> inline
void basic_ptree<K, D, C>::swap(basic_ptree<K, D, C> &rhs)
{
boost::swap(m_data, rhs.m_data);
// Void pointers, no ADL necessary
std::swap(m_children, rhs.m_children);
}
// Container view
template<class K, class D, class C> inline
typename basic_ptree<K, D, C>::size_type
basic_ptree<K, D, C>::size() const
{
return subs::ch(this).size();
}
template<class K, class D, class C> inline
typename basic_ptree<K, D, C>::size_type
basic_ptree<K, D, C>::max_size() const
{
return subs::ch(this).max_size();
}
template<class K, class D, class C> inline
bool basic_ptree<K, D, C>::empty() const
{
return subs::ch(this).empty();
}
template<class K, class D, class C> inline
typename basic_ptree<K, D, C>::iterator
basic_ptree<K, D, C>::begin()
{
return iterator(subs::ch(this).begin());
}
template<class K, class D, class C> inline
typename basic_ptree<K, D, C>::const_iterator
basic_ptree<K, D, C>::begin() const
{
return const_iterator(subs::ch(this).begin());
}
template<class K, class D, class C> inline
typename basic_ptree<K, D, C>::iterator
basic_ptree<K, D, C>::end()
{
return iterator(subs::ch(this).end());
}
template<class K, class D, class C> inline
typename basic_ptree<K, D, C>::const_iterator
basic_ptree<K, D, C>::end() const
{
return const_iterator(subs::ch(this).end());
}
template<class K, class D, class C> inline
typename basic_ptree<K, D, C>::reverse_iterator
basic_ptree<K, D, C>::rbegin()
{
return reverse_iterator(this->end());
}
template<class K, class D, class C> inline
typename basic_ptree<K, D, C>::const_reverse_iterator
basic_ptree<K, D, C>::rbegin() const
{
return const_reverse_iterator(this->end());
}
template<class K, class D, class C> inline
typename basic_ptree<K, D, C>::reverse_iterator
basic_ptree<K, D, C>::rend()
{
return reverse_iterator(this->begin());
}
template<class K, class D, class C> inline
typename basic_ptree<K, D, C>::const_reverse_iterator
basic_ptree<K, D, C>::rend() const
{
return const_reverse_iterator(this->begin());
}
template<class K, class D, class C> inline
typename basic_ptree<K, D, C>::value_type &
basic_ptree<K, D, C>::front()
{
return const_cast<value_type&>(subs::ch(this).front());
}
template<class K, class D, class C> inline
const typename basic_ptree<K, D, C>::value_type &
basic_ptree<K, D, C>::front() const
{
return subs::ch(this).front();
}
template<class K, class D, class C> inline
typename basic_ptree<K, D, C>::value_type &
basic_ptree<K, D, C>::back()
{
return const_cast<value_type&>(subs::ch(this).back());
}
template<class K, class D, class C> inline
const typename basic_ptree<K, D, C>::value_type &
basic_ptree<K, D, C>::back() const
{
return subs::ch(this).back();
}
template<class K, class D, class C> inline
typename basic_ptree<K, D, C>::iterator
basic_ptree<K, D, C>::insert(iterator where, const value_type &value)
{
return iterator(subs::ch(this).insert(where.base(), value).first);
}
template<class K, class D, class C>
template<class It> inline
void basic_ptree<K, D, C>::insert(iterator where, It first, It last)
{
subs::ch(this).insert(where.base(), first, last);
}
template<class K, class D, class C> inline
typename basic_ptree<K, D, C>::iterator
basic_ptree<K, D, C>::erase(iterator where)
{
return iterator(subs::ch(this).erase(where.base()));
}
template<class K, class D, class C> inline
typename basic_ptree<K, D, C>::iterator
basic_ptree<K, D, C>::erase(iterator first, iterator last)
{
return iterator(subs::ch(this).erase(first.base(), last.base()));
}
template<class K, class D, class C> inline
typename basic_ptree<K, D, C>::iterator
basic_ptree<K, D, C>::push_front(const value_type &value)
{
return iterator(subs::ch(this).push_front(value).first);
}
template<class K, class D, class C> inline
typename basic_ptree<K, D, C>::iterator
basic_ptree<K, D, C>::push_back(const value_type &value)
{
return iterator(subs::ch(this).push_back(value).first);
}
template<class K, class D, class C> inline
void basic_ptree<K, D, C>::pop_front()
{
subs::ch(this).pop_front();
}
template<class K, class D, class C> inline
void basic_ptree<K, D, C>::pop_back()
{
subs::ch(this).pop_back();
}
template<class K, class D, class C> inline
void basic_ptree<K, D, C>::reverse()
{
subs::ch(this).reverse();
}
namespace impl
{
struct by_first
{
template <typename P>
bool operator ()(const P& lhs, const P& rhs) const {
return lhs.first < rhs.first;
}
};
}
template<class K, class D, class C> inline
void basic_ptree<K, D, C>::sort()
{
sort(impl::by_first());
}
template<class K, class D, class C>
template<class Compare> inline
void basic_ptree<K, D, C>::sort(Compare comp)
{
subs::ch(this).sort(comp);
}
// Equality
template<class K, class D, class C> inline
bool basic_ptree<K, D, C>::operator ==(
const basic_ptree<K, D, C> &rhs) const
{
// The size test is cheap, so add it as an optimization
return size() == rhs.size() && data() == rhs.data() &&
subs::ch(this) == subs::ch(&rhs);
}
template<class K, class D, class C> inline
bool basic_ptree<K, D, C>::operator !=(
const basic_ptree<K, D, C> &rhs) const
{
return !(*this == rhs);
}
// Associative view
template<class K, class D, class C> inline
typename basic_ptree<K, D, C>::assoc_iterator
basic_ptree<K, D, C>::ordered_begin()
{
return assoc_iterator(subs::assoc(this).begin());
}
template<class K, class D, class C> inline
typename basic_ptree<K, D, C>::const_assoc_iterator
basic_ptree<K, D, C>::ordered_begin() const
{
return const_assoc_iterator(subs::assoc(this).begin());
}
template<class K, class D, class C> inline
typename basic_ptree<K, D, C>::assoc_iterator
basic_ptree<K, D, C>::not_found()
{
return assoc_iterator(subs::assoc(this).end());
}
template<class K, class D, class C> inline
typename basic_ptree<K, D, C>::const_assoc_iterator
basic_ptree<K, D, C>::not_found() const
{
return const_assoc_iterator(subs::assoc(this).end());
}
template<class K, class D, class C> inline
typename basic_ptree<K, D, C>::assoc_iterator
basic_ptree<K, D, C>::find(const key_type &key)
{
return assoc_iterator(subs::assoc(this).find(key));
}
template<class K, class D, class C> inline
typename basic_ptree<K, D, C>::const_assoc_iterator
basic_ptree<K, D, C>::find(const key_type &key) const
{
return const_assoc_iterator(subs::assoc(this).find(key));
}
template<class K, class D, class C> inline
std::pair<
typename basic_ptree<K, D, C>::assoc_iterator,
typename basic_ptree<K, D, C>::assoc_iterator
> basic_ptree<K, D, C>::equal_range(const key_type &key)
{
std::pair<typename subs::by_name_index::iterator,
typename subs::by_name_index::iterator> r(
subs::assoc(this).equal_range(key));
return std::pair<assoc_iterator, assoc_iterator>(
assoc_iterator(r.first), assoc_iterator(r.second));
}
template<class K, class D, class C> inline
std::pair<
typename basic_ptree<K, D, C>::const_assoc_iterator,
typename basic_ptree<K, D, C>::const_assoc_iterator
> basic_ptree<K, D, C>::equal_range(const key_type &key) const
{
std::pair<typename subs::by_name_index::const_iterator,
typename subs::by_name_index::const_iterator> r(
subs::assoc(this).equal_range(key));
return std::pair<const_assoc_iterator, const_assoc_iterator>(
const_assoc_iterator(r.first), const_assoc_iterator(r.second));
}
template<class K, class D, class C> inline
typename basic_ptree<K, D, C>::size_type
basic_ptree<K, D, C>::count(const key_type &key) const
{
return subs::assoc(this).count(key);
}
template<class K, class D, class C> inline
typename basic_ptree<K, D, C>::size_type
basic_ptree<K, D, C>::erase(const key_type &key)
{
return subs::assoc(this).erase(key);
}
template<class K, class D, class C> inline
typename basic_ptree<K, D, C>::iterator
basic_ptree<K, D, C>::to_iterator(assoc_iterator ai)
{
return iterator(subs::ch(this).
BOOST_NESTED_TEMPLATE project<0>(ai.base()));
}
template<class K, class D, class C> inline
typename basic_ptree<K, D, C>::const_iterator
basic_ptree<K, D, C>::to_iterator(const_assoc_iterator ai) const
{
return const_iterator(subs::ch(this).
BOOST_NESTED_TEMPLATE project<0>(ai.base()));
}
// Property tree view
template<class K, class D, class C> inline
typename basic_ptree<K, D, C>::data_type &
basic_ptree<K, D, C>::data()
{
return m_data;
}
template<class K, class D, class C> inline
const typename basic_ptree<K, D, C>::data_type &
basic_ptree<K, D, C>::data() const
{
return m_data;
}
template<class K, class D, class C> inline
void basic_ptree<K, D, C>::clear()
{
m_data = data_type();
subs::ch(this).clear();
}
template<class K, class D, class C>
basic_ptree<K, D, C> &
basic_ptree<K, D, C>::get_child(const path_type &path)
{
path_type p(path);
self_type *n = walk_path(p);
if (!n) {
BOOST_PROPERTY_TREE_THROW(ptree_bad_path("No such node", path));
}
return *n;
}
template<class K, class D, class C> inline
const basic_ptree<K, D, C> &
basic_ptree<K, D, C>::get_child(const path_type &path) const
{
return const_cast<self_type*>(this)->get_child(path);
}
template<class K, class D, class C> inline
basic_ptree<K, D, C> &
basic_ptree<K, D, C>::get_child(const path_type &path,
self_type &default_value)
{
path_type p(path);
self_type *n = walk_path(p);
return n ? *n : default_value;
}
template<class K, class D, class C> inline
const basic_ptree<K, D, C> &
basic_ptree<K, D, C>::get_child(const path_type &path,
const self_type &default_value) const
{
return const_cast<self_type*>(this)->get_child(path,
const_cast<self_type&>(default_value));
}
template<class K, class D, class C>
optional<basic_ptree<K, D, C> &>
basic_ptree<K, D, C>::get_child_optional(const path_type &path)
{
path_type p(path);
self_type *n = walk_path(p);
if (!n) {
return optional<self_type&>();
}
return *n;
}
template<class K, class D, class C>
optional<const basic_ptree<K, D, C> &>
basic_ptree<K, D, C>::get_child_optional(const path_type &path) const
{
path_type p(path);
self_type *n = walk_path(p);
if (!n) {
return optional<const self_type&>();
}
return *n;
}
template<class K, class D, class C>
basic_ptree<K, D, C> &
basic_ptree<K, D, C>::put_child(const path_type &path,
const self_type &value)
{
path_type p(path);
self_type &parent = force_path(p);
// Got the parent. Now get the correct child.
key_type fragment = p.reduce();
assoc_iterator el = parent.find(fragment);
// If the new child exists, replace it.
if(el != parent.not_found()) {
return el->second = value;
} else {
return parent.push_back(value_type(fragment, value))->second;
}
}
template<class K, class D, class C>
basic_ptree<K, D, C> &
basic_ptree<K, D, C>::add_child(const path_type &path,
const self_type &value)
{
path_type p(path);
self_type &parent = force_path(p);
// Got the parent.
key_type fragment = p.reduce();
return parent.push_back(value_type(fragment, value))->second;
}
template<class K, class D, class C>
template<class Type, class Translator>
typename boost::enable_if<detail::is_translator<Translator>, Type>::type
basic_ptree<K, D, C>::get_value(Translator tr) const
{
if(boost::optional<Type> o = get_value_optional<Type>(tr)) {
return *o;
}
BOOST_PROPERTY_TREE_THROW(ptree_bad_data(
std::string("conversion of data to type \"") +
type_id<Type>().name_demangled() + "\" failed", data()));
}
template<class K, class D, class C>
template<class Type> inline
Type basic_ptree<K, D, C>::get_value() const
{
return get_value<Type>(
typename translator_between<data_type, Type>::type());
}
template<class K, class D, class C>
template<class Type, class Translator> inline
Type basic_ptree<K, D, C>::get_value(const Type &default_value,
Translator tr) const
{
return get_value_optional<Type>(tr).get_value_or(default_value);
}
template<class K, class D, class C>
template <class Ch, class Translator>
typename boost::enable_if<
detail::is_character<Ch>,
std::basic_string<Ch>
>::type
basic_ptree<K, D, C>::get_value(const Ch *default_value, Translator tr)const
{
return get_value<std::basic_string<Ch>, Translator>(default_value, tr);
}
template<class K, class D, class C>
template<class Type> inline
typename boost::disable_if<detail::is_translator<Type>, Type>::type
basic_ptree<K, D, C>::get_value(const Type &default_value) const
{
return get_value(default_value,
typename translator_between<data_type, Type>::type());
}
template<class K, class D, class C>
template <class Ch>
typename boost::enable_if<
detail::is_character<Ch>,
std::basic_string<Ch>
>::type
basic_ptree<K, D, C>::get_value(const Ch *default_value) const
{
return get_value< std::basic_string<Ch> >(default_value);
}
template<class K, class D, class C>
template<class Type, class Translator> inline
optional<Type> basic_ptree<K, D, C>::get_value_optional(
Translator tr) const
{
return tr.get_value(data());
}
template<class K, class D, class C>
template<class Type> inline
optional<Type> basic_ptree<K, D, C>::get_value_optional() const
{
return get_value_optional<Type>(
typename translator_between<data_type, Type>::type());
}
template<class K, class D, class C>
template<class Type, class Translator> inline
typename boost::enable_if<detail::is_translator<Translator>, Type>::type
basic_ptree<K, D, C>::get(const path_type &path,
Translator tr) const
{
return get_child(path).BOOST_NESTED_TEMPLATE get_value<Type>(tr);
}
template<class K, class D, class C>
template<class Type> inline
Type basic_ptree<K, D, C>::get(const path_type &path) const
{
return get_child(path).BOOST_NESTED_TEMPLATE get_value<Type>();
}
template<class K, class D, class C>
template<class Type, class Translator> inline
Type basic_ptree<K, D, C>::get(const path_type &path,
const Type &default_value,
Translator tr) const
{
return get_optional<Type>(path, tr).get_value_or(default_value);
}
template<class K, class D, class C>
template <class Ch, class Translator>
typename boost::enable_if<
detail::is_character<Ch>,
std::basic_string<Ch>
>::type
basic_ptree<K, D, C>::get(
const path_type &path, const Ch *default_value, Translator tr) const
{
return get<std::basic_string<Ch>, Translator>(path, default_value, tr);
}
template<class K, class D, class C>
template<class Type> inline
typename boost::disable_if<detail::is_translator<Type>, Type>::type
basic_ptree<K, D, C>::get(const path_type &path,
const Type &default_value) const
{
return get_optional<Type>(path).get_value_or(default_value);
}
template<class K, class D, class C>
template <class Ch>
typename boost::enable_if<
detail::is_character<Ch>,
std::basic_string<Ch>
>::type
basic_ptree<K, D, C>::get(
const path_type &path, const Ch *default_value) const
{
return get< std::basic_string<Ch> >(path, default_value);
}
template<class K, class D, class C>
template<class Type, class Translator>
optional<Type> basic_ptree<K, D, C>::get_optional(const path_type &path,
Translator tr) const
{
if (optional<const self_type&> child = get_child_optional(path))
return child.get().
BOOST_NESTED_TEMPLATE get_value_optional<Type>(tr);
else
return optional<Type>();
}
template<class K, class D, class C>
template<class Type>
optional<Type> basic_ptree<K, D, C>::get_optional(
const path_type &path) const
{
if (optional<const self_type&> child = get_child_optional(path))
return child.get().BOOST_NESTED_TEMPLATE get_value_optional<Type>();
else
return optional<Type>();
}
template<class K, class D, class C>
template<class Type, class Translator>
void basic_ptree<K, D, C>::put_value(const Type &value, Translator tr)
{
if(optional<data_type> o = tr.put_value(value)) {
data() = *o;
} else {
BOOST_PROPERTY_TREE_THROW(ptree_bad_data(
std::string("conversion of type \"") + type_id<Type>().name_demangled() +
"\" to data failed", boost::any()));
}
}
template<class K, class D, class C>
template<class Type> inline
void basic_ptree<K, D, C>::put_value(const Type &value)
{
put_value(value, typename translator_between<data_type, Type>::type());
}
template<class K, class D, class C>
template<class Type, typename Translator>
basic_ptree<K, D, C> & basic_ptree<K, D, C>::put(
const path_type &path, const Type &value, Translator tr)
{
if(optional<self_type &> child = get_child_optional(path)) {
child.get().put_value(value, tr);
return *child;
} else {
self_type &child2 = put_child(path, self_type());
child2.put_value(value, tr);
return child2;
}
}
template<class K, class D, class C>
template<class Type> inline
basic_ptree<K, D, C> & basic_ptree<K, D, C>::put(
const path_type &path, const Type &value)
{
return put(path, value,
typename translator_between<data_type, Type>::type());
}
template<class K, class D, class C>
template<class Type, typename Translator> inline
basic_ptree<K, D, C> & basic_ptree<K, D, C>::add(
const path_type &path, const Type &value, Translator tr)
{
self_type &child = add_child(path, self_type());
child.put_value(value, tr);
return child;
}
template<class K, class D, class C>
template<class Type> inline
basic_ptree<K, D, C> & basic_ptree<K, D, C>::add(
const path_type &path, const Type &value)
{
return add(path, value,
typename translator_between<data_type, Type>::type());
}
template<class K, class D, class C>
basic_ptree<K, D, C> *
basic_ptree<K, D, C>::walk_path(path_type &p) const
{
if(p.empty()) {
// I'm the child we're looking for.
return const_cast<basic_ptree*>(this);
}
// Recurse down the tree to find the path.
key_type fragment = p.reduce();
const_assoc_iterator el = find(fragment);
if(el == not_found()) {
// No such child.
return 0;
}
// Not done yet, recurse.
return el->second.walk_path(p);
}
template<class K, class D, class C>
basic_ptree<K, D, C> & basic_ptree<K, D, C>::force_path(path_type &p)
{
BOOST_ASSERT(!p.empty() && "Empty path not allowed for put_child.");
if(p.single()) {
// I'm the parent we're looking for.
return *this;
}
key_type fragment = p.reduce();
assoc_iterator el = find(fragment);
// If we've found an existing child, go down that path. Else
// create a new one.
self_type& child = el == not_found() ?
push_back(value_type(fragment, self_type()))->second : el->second;
return child.force_path(p);
}
// Free functions
template<class K, class D, class C>
inline void swap(basic_ptree<K, D, C> &pt1, basic_ptree<K, D, C> &pt2)
{
pt1.swap(pt2);
}
} }
#if defined(BOOST_PROPERTY_TREE_PAIR_BUG)
#undef BOOST_PROPERTY_TREE_PAIR_BUG
#endif
#endif

89
test/Jamfile.v2 Normal file
View File

@@ -0,0 +1,89 @@
# Copyright 2012-2023 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 ;
import ../../config/checks/config : requires ;
project
: source-location .
: requirements
[ requires cxx11_rvalue_references ]
;
# 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) ] ;
}
}

87
test/appveyor.yml Normal file
View File

@@ -0,0 +1,87 @@
# 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-2023 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 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-2023 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-2023 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-2023 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-2023 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-2023 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-2023 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-2023 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-2023 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-2023 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-2023 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()
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()
IMPLEMENT_CLASS(base1)
};
struct base2 {
BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST()
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()
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()
};
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-2023 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-2023 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-2023 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-2023 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;
}