Compare commits

...

189 Commits

Author SHA1 Message Date
Peter Dimov
4959611e09 Avoid msvc-14.0 constexpr errors in enum_to_string 2025-12-15 19:39:46 +02:00
Peter Dimov
a722380b2a Update revision history 2025-12-15 13:16:33 +02:00
Peter Dimov
dfd9182bf3 Replace the lambda in enum_to_string with a struct to enable C++14 constexpr. Refs #60. Refs #61. 2025-12-15 12:37:40 +02:00
Peter Dimov
f1774f3d02 Make enum_to_string constexpr; add enum_to_string_test_cx.cpp. Refs #60. Refs #61. 2025-12-15 12:28:44 +02:00
Peter Dimov
7c0d234267 Update ci.yml 2025-12-11 15:49:41 +02:00
Peter Dimov
6e4b7f5a07 Update .drone.jsonnet 2025-11-14 23:19:03 +02:00
Peter Dimov
0a40d3b824 Move C++20 detection to detail/config.hpp; disable C++20 use for Clang < 13. 2025-11-14 23:10:11 +02:00
Peter Dimov
644a984a61 Avoid https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122688 2025-11-14 23:10:11 +02:00
Peter Dimov
43ee545507 Move enum descriptors computation into decltype under C++20. Fixes #58. 2025-11-14 23:10:11 +02:00
Peter Dimov
54b73c7ca7 Add test for describe_enumerators on a nested enum before the enclosing class is complete. Refs #58. 2025-11-14 23:10:11 +02:00
Peter Dimov
ee215421cb Update appveyor.yml 2025-11-14 14:32:49 +02:00
Peter Dimov
2864875eef Disable C4996 from JSON on msvc-14.0 2025-10-22 16:03:41 +03:00
Peter Dimov
1a63fc6ffb Update cmake_subdir_test/CMakeLists.txt to reflect Core changes 2025-10-22 11:24:17 +03:00
Peter Dimov
373db78411 Make mod_any_access an inline variable, because of modules. Closes #57. 2025-10-22 11:00:36 +03:00
Peter Dimov
5858ccb775 Merge pull request #56 from sigbjorn/feature/extend-pp-for-each-limit
Extended limit for describe/detail/pp_for_each.hpp from 52 to 64
2025-08-17 10:18:55 +03:00
Peter Dimov
ba01c60d56 Update .drone.jsonnet 2025-08-17 01:16:13 +03:00
Peter Dimov
ecd2b0456b Remove windows-2019 from GHA 2025-08-16 21:35:16 +03:00
sigbjorn
362a266b7d Extended limit for describe/detail/pp_for_each.hpp from 52 to 64 including test, #55 2025-08-08 10:52:00 +02:00
Peter Dimov
b64177c39f Update ci.yml 2025-05-25 17:11:44 +03:00
Peter Dimov
ddff876eea Update .drone.jsonnet 2024-12-13 13:47:35 +02:00
Peter Dimov
112c33a793 Apply Node20 workaround 2024-12-13 13:46:26 +02:00
Peter Dimov
22f497d1ad Update ci.yml 2024-12-13 13:45:37 +02:00
Peter Dimov
3da6a1e295 Update ci.yml 2024-10-14 02:06:21 +03:00
Peter Dimov
ff76bbb90b Merge pull request #47 from qchateau/develop
Support parameter packs for bases in BOOST_DESCRIBE_CLASS
2024-10-14 01:51:27 +03:00
Peter Dimov
18e7c01359 Update JSON examples for JSON 1.81+ 2024-09-09 20:23:58 +03:00
Peter Dimov
777bdec2e9 Update examples.adoc for JSON 1.81+ 2024-09-09 20:21:03 +03:00
Peter Dimov
f39d32150d Use link=static for JSON, Serialization under UBSan 2024-08-22 01:53:28 +03:00
Peter Dimov
f8f7af29d5 Update .drone.jsonnet 2024-08-21 21:51:41 +03:00
Peter Dimov
89b5caef8d Add VERBATIM to add_custom_target 2024-08-21 21:49:52 +03:00
Peter Dimov
2fb95498ea Update build.jam, test/Jamfile 2024-08-21 20:59:01 +03:00
Peter Dimov
8a0ade0ad0 Merge branch 'modular' of https://github.com/grafikrobot/boostorg.describe into feature/modular-b2 2024-08-21 20:54:19 +03:00
Peter Dimov
1508f66184 Update .drone.jsonnet 2024-08-21 19:01:46 +03:00
Peter Dimov
ac298922b0 Update ci.yml 2024-08-21 18:18:20 +03:00
Rene Rivera
86099f1d78 Move inter-lib dependencies to a project variable and into the build targets. 2024-07-23 22:34:24 -05:00
Rene Rivera
d25e48348e Update copyright dates. 2024-07-20 22:52:05 -05:00
Rene Rivera
76c036a2d7 Change all <source> references to <library>. 2024-07-20 19:38:12 -05:00
Rene Rivera
879d4b2a22 Bump B2 require to 5.2 2024-06-14 11:33:55 -05:00
Rene Rivera
202203112b Add requires-b2 check to top-level build file. 2024-05-05 09:00:01 -05:00
Rene Rivera
882b168de8 Sync from upstream. 2024-04-20 15:34:25 -05:00
Peter Dimov
1ddee6c39a Revert "Update doc/Jamfile"
This reverts commit 9899acb4c9.
2024-04-16 22:36:26 +03:00
Peter Dimov
9899acb4c9 Update doc/Jamfile 2024-04-16 22:17:19 +03:00
Rene Rivera
84ce044885 Switch to library requirements instead of source. As source puts extra source in install targets. 2024-03-29 21:15:58 -05:00
Rene Rivera
120b9edaed Sync from upstream. 2024-03-23 16:03:15 -05:00
Peter Dimov
50719b2123 Update .drone.jsonnet 2024-03-23 20:27:08 +02:00
Peter Dimov
8f3b04a3d9 Disable warnings-as-errors=on in serialization.cpp for MSVC as well 2024-03-23 20:22:22 +02:00
Quentin Chateau
2e63564776 Support parameter packs for bases in BOOST_DESCRIBE_CLASS 2024-03-22 22:47:46 +01:00
Rene Rivera
9da33c4629 Make the library modular usable. 2024-03-11 08:32:57 -05:00
Peter Dimov
fad199e782 Merge pull request #44 from denzor200/actualize_fmt
Actualize examples to build with latest `fmt`
2023-12-13 17:29:06 +02:00
Peter Dimov
e005f6950c Update ci.yml 2023-12-13 17:12:12 +02:00
Denis Mikhailov
2e5dcc80b2 Update fmtlib_enum_formatter.cpp 2023-11-25 22:22:10 +01:00
Denis Mikhailov
ba1459ac84 Update fmtlib_class_formatter.cpp 2023-11-25 22:21:33 +01:00
Peter Dimov
c89e4dd3db Update json_rpc example to work on both versions of Boost.JSON 2023-09-26 00:53:40 +03:00
Peter Dimov
3047e5a72f Document the new overload of enum_from_string 2023-09-09 19:07:05 +03:00
Peter Dimov
cfddb57d3a Add an overload of enum_from_string that takes a string-like type (such as string_view). Fixes #41. 2023-09-09 18:52:41 +03:00
Peter Dimov
6e7d49c6e1 Do not use -Werror with Serialization under GCC 2023-09-09 17:57:18 +03:00
Peter Dimov
cc2281054e {"world"} is now string in Boost.JSON, not array 2023-09-09 17:23:26 +03:00
Peter Dimov
215042b480 Update ci.yml 2023-09-09 17:03:54 +03:00
Peter Dimov
a0eafb0810 Merge branch 'fix-deprecated-inline-static-variables' of https://github.com/Romain-Geissler-1A/describe into feature/pr-40 2023-05-21 04:51:35 +03:00
Peter Dimov
1692c3e5d6 Update ci.yml 2023-05-21 04:05:26 +03:00
Romain Geissler
b54fda5469 Fix -Wdeprecated warnings when compiling with C++ >= 17 (ie with inline variables).
Example of warning we get:
/data/mwrep/res/osp/Boost/23-0-0-0/include/boost/describe/members.hpp:89:81: error: redundant redeclaration of 'constexpr' static data member 'boost::describe::detail::update_modifiers<T, Bm>::fn<D>::pointer' [-Werror=deprecated]
 89 | template<class T, unsigned Bm> template<class D> constexpr decltype(D::pointer) update_modifiers<T, Bm>::fn<D>::pointer;
    | ^~~~~~~~~~~~~~~~~~~~~~~ /data/mwrep/res/osp/Boost/23-0-0-0/include/boost/describe/members.hpp:83:47: note: previous declaration of 'boost::describe::detail::update_modifiers<T, Bm>::fn<D>::pointer'
 83 | static constexpr decltype(D::pointer) pointer = D::pointer;
    | ^~~~~~~
2023-05-20 23:41:18 +00:00
Peter Dimov
311cab7565 Update documentation 2022-10-30 02:02:43 +03:00
Peter Dimov
b5df0b2ee9 Reorder includes to work around an odd msvc-14.0 bug 2022-10-29 04:08:38 +03:00
Peter Dimov
1e32c60dff Update hash_value example for 1.81 2022-10-29 03:36:47 +03:00
Peter Dimov
0d8de0aae7 Enable JSON tests with msvc-14.0, as it's supported now 2022-10-28 07:01:24 +03:00
Peter Dimov
8ff96dcd9e Add pedantic_members_test 2022-10-28 06:31:01 +03:00
Peter Dimov
7a06d512dc Move BOOST_DESCRIBE_ENUM(modifiers) to modifier_description.hpp, to allow modifiers.hpp inclusion under -pedantic 2022-10-28 06:28:16 +03:00
Peter Dimov
2deab4c35c Add pedantic_bases_test 2022-10-28 06:19:17 +03:00
Peter Dimov
8a982de483 Add pedantic_enumerators_test 2022-10-28 06:06:24 +03:00
Peter Dimov
f8c2b7d2d9 Add comments to unnamed_namespace_test, unnamed_namespace_test2 2022-10-28 05:56:46 +03:00
Peter Dimov
5d13049e06 Use __attribute__((unused)) instead of [[maybe_unused]]; earlier Clangs don't have [[maybe_unused]], and it's a pedantic warning before C++17 2022-10-28 05:29:31 +03:00
Peter Dimov
df0f16a85b Do not set BOOST_DESCRIBE_CXX11 for g++ 4.7, as its C++11 support is not good enough 2022-10-28 05:24:46 +03:00
Peter Dimov
81d924fff2 Add Drone support 2022-10-28 04:28:58 +03:00
Peter Dimov
a1557028b3 Update ci.yml 2022-10-20 18:42:54 +03:00
Peter Dimov
6bf8045bac Disable warning 4100 under msvc-14.0 2022-10-20 18:27:14 +03:00
Peter Dimov
973bdf1725 Remove global -wd4100 2022-10-20 18:23:00 +03:00
Peter Dimov
f6bf0c4f1e Replace macos-10.15 with macos-11 in ci.yml 2022-09-29 20:40:21 +03:00
Peter Dimov
c156466e2b Fix operator test failures 2022-09-29 20:11:07 +03:00
Peter Dimov
9273e7c0af Add member functions to X in operator_eq_test, operator_lt_test 2022-09-29 20:07:59 +03:00
Peter Dimov
ef9c38f90c Update documentation 2022-06-21 20:19:56 +03:00
Peter Dimov
6749a0f46a Disable msvc-12.0 and below warnings in bases_test.cpp 2022-06-21 19:31:06 +03:00
Peter Dimov
c8c46bfdf7 Disable -Wrestrict in pm_to_string.cpp for GCC 12 2022-06-21 18:02:06 +03:00
Peter Dimov
ccfed27ddd Update .yml files 2022-06-21 17:06:42 +03:00
Peter Dimov
21de045f39 Remove extra semicolons in tests 2022-06-21 16:34:26 +03:00
Peter Dimov
4b65c35009 Remove extra semicolon in modifiers.hpp 2022-06-21 16:28:22 +03:00
Peter Dimov
574c1736a3 Merge pull request #28 from ecatmur/nested-poison
Poison BOOST_DESCRIBE_ENUM in class scope
2022-02-19 03:46:58 +02:00
Peter Dimov
c0fd54e1f7 Update documentation and README 2022-02-19 03:17:58 +02:00
Peter Dimov
2a50e32645 Add CMake jobs to ci.yml 2022-02-19 02:50:35 +02:00
Peter Dimov
71c9a5100e Update fmtlib examples 2022-02-14 06:48:59 +02:00
Peter Dimov
1614c16be7 Update ci.yml 2022-02-13 03:35:13 +02:00
Peter Dimov
dd950f77fe Use [listing] for sample outputs 2022-02-13 03:07:58 +02:00
Peter Dimov
0be3b2833d Add sample outputs to examples 2022-02-13 01:55:11 +02:00
Peter Dimov
3ac03da76f Added example/fmtlib_enum_formatter.cpp 2022-02-13 01:36:39 +02:00
Peter Dimov
0eb2c9eb25 Rename fmtlib_formatter.cpp to fmtlib_class_formatter.cpp 2022-02-13 01:30:22 +02:00
Peter Dimov
4ccae397a7 Update revision history 2022-02-02 20:47:02 +02:00
Peter Dimov
dae1e8246a Add printing member pointers example 2022-02-02 20:40:01 +02:00
Peter Dimov
8d10118745 Add fmtlib formatter example 2022-02-01 06:22:24 +02:00
Peter Dimov
74089b76c3 Update appveyor.yml 2021-12-22 06:57:16 +02:00
Ed Catmur
d64c9fb141 Create nested_enum_fail.cpp 2021-12-21 17:11:43 +00:00
Ed Catmur
abc8b0236d Create enum_nested_fail.cpp 2021-12-21 17:11:19 +00:00
Ed Catmur
dd76e316d3 Update Jamfile 2021-12-21 17:08:53 +00:00
Ed Catmur
acf2e56c34 Poison BOOST_DESCRIBE_ENUM in class scope
try to inform the user that they should use BOOST_DESCRIBE_NESTED_ENUM instead
2021-12-21 17:07:14 +00:00
Peter Dimov
811003ea0c g++ 4.8 doesn't like static union members either 2021-12-15 03:40:34 +02:00
Peter Dimov
bd8be41591 Add !is_union<T>::value to examples 2021-12-15 02:14:56 +02:00
Peter Dimov
f9477bc177 Disable operators for unions because their behavior is undefined 2021-12-15 02:00:20 +02:00
Peter Dimov
d98f4d1f40 Disable union tests for C++03 because static members are not allowed 2021-12-15 01:49:52 +02:00
Peter Dimov
2e3b6a6791 Test BOOST_DESCRIBE_CLASS with a union 2021-12-15 01:41:54 +02:00
Peter Dimov
fabf5c7115 Allow unions in BOOST_DESCRIBE_STRUCT (refs #21) 2021-12-15 01:33:06 +02:00
Peter Dimov
ec7aec2b3d Add msvc-14.0 to GHA 2021-12-11 20:15:03 +02:00
Peter Dimov
fc458d48c7 Change internal functions to take T** instead of T* to prevent derived to base conversions (closes #22) 2021-12-11 19:28:16 +02:00
Peter Dimov
6cc4ddafd7 Test non-described classes derived from described ones (refs #22) 2021-12-11 19:14:19 +02:00
Peter Dimov
ed1175b33a Merge branch 'maybe-unused' of https://github.com/ecatmur/describe into feature/pr-24 2021-11-17 02:22:16 +02:00
Peter Dimov
d4ebe0943e Add test for enums and classes in unnamed namespaces (refs #23) 2021-11-17 02:20:22 +02:00
Ed Catmur
1fa144623d Sprinkle [[maybe_unused]] on descriptors
Suppresses Wunused-function / Wunneeded-internal-declaration (clang) on internal-linkage types

https://github.com/boostorg/describe/issues/23
2021-11-16 21:35:33 +00:00
Peter Dimov
5032f55ac1 Update categories in libraries.json 2021-11-08 00:34:30 +02:00
Peter Dimov
71bfb07be2 Add example/struct_to_tuple.cpp 2021-10-28 01:28:07 +03:00
Peter Dimov
fc15f03c34 Add {zwsp} to long header names 2021-10-27 06:51:54 +03:00
Peter Dimov
2fc0e817ad Document descriptor_by_pointer 2021-10-27 06:24:09 +03:00
Peter Dimov
84fe8aa21e Add descriptor_by_pointer 2021-10-27 06:09:54 +03:00
Peter Dimov
003b2bdc50 Document descriptor_by_name 2021-10-27 05:42:38 +03:00
Peter Dimov
8437f2e62e Fix msvc-14.0 2021-10-27 04:31:35 +03:00
Peter Dimov
448174f346 Add descriptor_by_name 2021-10-27 04:13:29 +03:00
Peter Dimov
2935bca3b1 Update README, implementation section 2021-10-26 18:46:12 +03:00
Peter Dimov
e407d4da19 Document operators 2021-10-26 17:39:59 +03:00
Peter Dimov
2accb05ce5 Reset os.width in operator<< 2021-10-26 17:32:21 +03:00
Peter Dimov
128e3667d6 Add operators.hpp 2021-10-26 07:09:30 +03:00
Peter Dimov
8cf28d7b6e Include enum_from_string.hpp in describe.hpp 2021-10-26 06:21:56 +03:00
Peter Dimov
7397e8d66a Document enum_from_string 2021-10-26 05:40:26 +03:00
Peter Dimov
c3f16f3332 Add enum_from_string.hpp 2021-10-26 05:33:14 +03:00
Peter Dimov
890c1afcda Bump workaround in class_template_test.cpp 2021-10-26 04:18:37 +03:00
Peter Dimov
caa4cb6bf0 Bump workarounds in members_test7.cpp 2021-10-26 04:17:26 +03:00
Peter Dimov
ffa4790292 Add msvc-14.3 to ci.yml 2021-10-26 04:15:50 +03:00
Peter Dimov
f7d2f12cd4 Document enum_to_string 2021-10-26 04:13:18 +03:00
Peter Dimov
53d577428e Make enum_to_string noexcept 2021-10-26 04:12:58 +03:00
Peter Dimov
9c351a463f Add enum_to_string.hpp 2021-10-25 20:22:14 +03:00
Peter Dimov
af01484087 Document has_* 2021-10-25 20:08:13 +03:00
Peter Dimov
d5e79ee67d Remove superfluous semicolons 2021-10-25 19:53:53 +03:00
Peter Dimov
300ea0bebe Add has_describe_members 2021-10-25 18:45:26 +03:00
Peter Dimov
5a4c425f32 Add has_describe_bases 2021-10-25 18:40:38 +03:00
Peter Dimov
fe23aeeee4 Update ci.yml 2021-10-25 18:01:19 +03:00
Peter Dimov
daaec68db6 Update ci.yml 2021-10-25 17:40:36 +03:00
Peter Dimov
b6c41956ec Add has_describe_enumerators 2021-10-25 17:36:58 +03:00
Peter Dimov
7e6f861f89 Document mod_any_member 2021-06-16 22:39:45 +03:00
Peter Dimov
4a4dd302cb Add mod_any_member 2021-06-16 22:33:02 +03:00
Peter Dimov
be5bf613e6 Add test/CMakeLists.txt 2021-06-16 05:39:59 +03:00
Peter Dimov
57e62f34b8 Avoid g++ error 2021-06-16 05:19:57 +03:00
Peter Dimov
7e9f1f0eb9 Add class_template_test 2021-06-16 04:57:14 +03:00
Peter Dimov
0b65ca3229 Update ci.yml 2021-06-08 20:30:43 +03:00
Peter Dimov
f66002254b Add CMakeLists.txt 2021-05-28 00:14:09 +03:00
Peter Dimov
abbc5bec0c Fix example to compile on VS2015 2021-05-03 08:52:17 +03:00
Peter Dimov
ef93d95e71 Fix capitalization, MSVC warning 2021-05-03 05:38:05 +03:00
Peter Dimov
c48ef40b1d Add example/console.cpp 2021-05-03 04:53:07 +03:00
Peter Dimov
78c861d0bc Add example/equality.cpp 2021-05-03 04:05:03 +03:00
Peter Dimov
23cc0011ad Remove doc/html 2021-05-03 03:53:34 +03:00
Peter Dimov
245c2de80a Add example/hash_value.cpp 2021-05-03 03:52:36 +03:00
Peter Dimov
22eaa99867 Update GHA 2021-04-26 01:31:39 +03:00
Peter Dimov
53d7313731 Update README 2021-04-26 00:05:32 +03:00
Peter Dimov
65066cd2d0 Update documentation 2021-03-20 21:53:41 +02:00
Peter Dimov
94a80a6812 Add BOOST_DESCRIBE_NESTED_ENUM 2021-03-20 02:28:22 +02:00
Peter Dimov
62c032ff22 Add static_asserts in BOOST_DESCRIBE_ENUM and BOOST_DESCRIBE_STRUCT (fixes #8) 2021-03-17 16:42:58 +02:00
Peter Dimov
bef1e45cb0 Add compile-fail tests for describing enums as structs and vice versa (refs #8) 2021-03-17 16:29:37 +02:00
Peter Dimov
92afba2c39 Disable MS warning 5104 (ntverp.h under new pp) for JSON examples 2021-03-17 15:08:42 +02:00
Peter Dimov
031c55b392 Update GHA handling of cxxflags 2021-03-17 14:43:37 +02:00
Peter Dimov
36c52dcbd6 Add -Zc:preprocessor configurations to GHA and Appveyor 2021-03-17 14:29:54 +02:00
Peter Dimov
4ca49a6af2 Remove noexcept from functions to avoid g++-7 warning and enable C++03 compilation 2021-03-16 06:34:12 +02:00
Peter Dimov
1bf6dddac0 Add a test for overloaded functions returning std::pair 2021-03-16 06:20:20 +02:00
Peter Dimov
39cf63cee1 Update documentation 2021-03-16 05:08:03 +02:00
Peter Dimov
5ebca2615a Merge branch 'develop' into feature/overloaded 2021-03-16 01:52:02 +02:00
Peter Dimov
7f36a2c798 Add a protected base to members_test5.cpp 2021-03-16 01:51:47 +02:00
Peter Dimov
564f849629 Use PP_NAME, PP_POINTER when describing members; add overloaded_test 2021-03-16 01:44:53 +02:00
Peter Dimov
ed26d4c495 Add BOOST_DESCRIBE_PP_NAME, BOOST_DESCRIBE_PP_POINTER 2021-03-16 01:21:20 +02:00
Peter Dimov
8aa347b171 Update supported compilers 2021-03-15 17:19:02 +02:00
Peter Dimov
acf14803ba Enable syntax highlighting 2021-03-14 20:39:36 +02:00
Peter Dimov
ffb6787d28 Add -std g++ 5/6/7 configurations to Travis 2021-03-14 07:34:09 +02:00
Peter Dimov
e15c09c848 Reenable BOOST_DESCRIBE_CXX14 for -std=c++14 on g++ 5, 6, 7 2021-03-14 06:49:02 +02:00
Peter Dimov
c9f780cbfb Allow trailing comma in enum descriptions and definitions 2021-03-14 06:47:14 +02:00
Peter Dimov
ae5c3c862f Add detail/pp_utilities.hpp 2021-03-14 06:30:01 +02:00
Peter Dimov
c6fa6f125e Fix handling of empty enums 2021-03-14 01:30:59 +02:00
Peter Dimov
e503b32c51 Add empty_enum_test 2021-03-14 01:24:33 +02:00
Peter Dimov
ee415d4001 Rename internal classes from D to _boost_desc 2021-03-14 01:14:58 +02:00
Peter Dimov
b1e0566668 Add a test using various entities named D 2021-03-14 01:11:03 +02:00
Peter Dimov
f251e6f320 Add a boost prefix to descriptor functions 2021-03-14 01:00:45 +02:00
Peter Dimov
70eadd17a7 Update enumerators_test.cpp to use the macros even when C++14 is not available 2021-03-14 00:53:26 +02:00
Peter Dimov
02cdf8734f Update documentation 2021-03-14 00:46:24 +02:00
Peter Dimov
6f8e4c879b Remove BOOST_DESCRIBE_ENUM_CLASS; use BOOST_DESCRIBE_ENUM_BEGIN, BOOST_DESCRIBE_ENUM_ENTRY, BOOST_DESCRIBE_ENUM_END 2021-03-14 00:44:25 +02:00
Peter Dimov
f76971d52c Update documentation 2021-03-14 00:30:05 +02:00
Peter Dimov
fe26439f39 Update bases_test.cpp 2021-03-13 21:45:24 +02:00
Peter Dimov
a876e619b7 Use detail/compute_base_modifiers.hpp in detail/bases.hpp 2021-03-13 21:39:53 +02:00
Peter Dimov
19bb4254bc Add a final class test to test/compute_base_modifiers 2021-03-13 21:29:49 +02:00
Peter Dimov
109bb07163 Add detail/compute_base_modifiers.hpp 2021-03-13 21:23:27 +02:00
102 changed files with 6037 additions and 2289 deletions

455
.drone.jsonnet Normal file
View File

@@ -0,0 +1,455 @@
# Copyright 2022 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# https://www.boost.org/LICENSE_1_0.txt
local library = "describe";
local triggers =
{
branch: [ "master", "develop", "feature/*" ]
};
local ubsan = { UBSAN: '1', UBSAN_OPTIONS: 'print_stacktrace=1' };
local asan = { ASAN: '1' };
local linux_pipeline(name, image, environment, packages = "", sources = [], arch = "amd64") =
{
name: name,
kind: "pipeline",
type: "docker",
trigger: triggers,
platform:
{
os: "linux",
arch: arch
},
steps:
[
{
name: "everything",
image: image,
environment: environment,
commands:
[
'set -e',
'uname -a',
'echo $DRONE_STAGE_MACHINE',
] +
(if sources != [] then [ ('apt-add-repository "' + source + '"') for source in sources ] else []) +
(if packages != "" then [ 'apt-get update', 'apt-get -y install ' + packages ] else []) +
[
'export LIBRARY=' + library,
'./.drone/drone.sh',
]
}
]
};
local macos_pipeline(name, environment, xcode_version = "12.2", osx_version = "catalina", arch = "amd64") =
{
name: name,
kind: "pipeline",
type: "exec",
trigger: triggers,
platform: {
"os": "darwin",
"arch": arch
},
node: {
"os": osx_version
},
steps: [
{
name: "everything",
environment: environment + { "DEVELOPER_DIR": "/Applications/Xcode-" + xcode_version + ".app/Contents/Developer" },
commands:
[
'export LIBRARY=' + library,
'./.drone/drone.sh',
]
}
]
};
local windows_pipeline(name, image, environment, arch = "amd64") =
{
name: name,
kind: "pipeline",
type: "docker",
trigger: triggers,
platform:
{
os: "windows",
arch: arch
},
"steps":
[
{
name: "everything",
image: image,
environment: environment,
commands:
[
'cmd /C .drone\\\\drone.bat ' + library,
]
}
]
};
[
linux_pipeline(
"Linux 14.04 GCC 4.4",
"cppalliance/droneubuntu1404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-4.4', CXXSTD: '98,0x' },
"g++-4.4",
[ "ppa:ubuntu-toolchain-r/test" ],
),
linux_pipeline(
"Linux 14.04 GCC 4.6",
"cppalliance/droneubuntu1404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-4.6', CXXSTD: '98,0x' },
"g++-4.6",
[ "ppa:ubuntu-toolchain-r/test" ],
),
linux_pipeline(
"Linux 14.04 GCC 4.7",
"cppalliance/droneubuntu1404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-4.7', CXXSTD: '98,0x' },
"g++-4.7",
[ "ppa:ubuntu-toolchain-r/test" ],
),
linux_pipeline(
"Linux 14.04 GCC 4.8*",
"cppalliance/droneubuntu1404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11' },
),
linux_pipeline(
"Linux 14.04 GCC 4.9",
"cppalliance/droneubuntu1404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-4.9', CXXSTD: '03,11' },
"g++-4.9",
[ "ppa:ubuntu-toolchain-r/test" ],
),
linux_pipeline(
"Linux 16.04 GCC 5*",
"cppalliance/droneubuntu1604:1",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14,1z' },
),
linux_pipeline(
"Linux 18.04 GCC 6",
"cppalliance/droneubuntu1804:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-6', CXXSTD: '03,11,14,1z' },
"g++-6",
),
linux_pipeline(
"Linux 18.04 GCC 7*",
"cppalliance/droneubuntu1804:1",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14,17' },
),
linux_pipeline(
"Linux 18.04 GCC 8",
"cppalliance/droneubuntu1804:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-8', CXXSTD: '03,11,14,17,2a' },
"g++-8",
),
linux_pipeline(
"Linux 20.04 GCC 9*",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14,17,2a' },
),
linux_pipeline(
"Linux 20.04 GCC 10",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-10', CXXSTD: '03,11,14,17,2a' },
"g++-10",
),
linux_pipeline(
"Linux 22.04 GCC 11*",
"cppalliance/droneubuntu2204:1",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14,17,2a' },
),
linux_pipeline(
"Linux 22.04 GCC 12",
"cppalliance/droneubuntu2204:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '03,11,14,17,20,2b' },
"g++-12",
),
linux_pipeline(
"Linux 24.04 GCC 13",
"cppalliance/droneubuntu2404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '03,11,14,17,20,2b' },
"g++-13",
),
linux_pipeline(
"Linux 24.04 GCC 14 UBSAN",
"cppalliance/droneubuntu2404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-14', CXXSTD: '03,11,14,17,20,2b' } + ubsan,
"g++-14",
),
linux_pipeline(
"Linux 24.04 GCC 14 ASAN",
"cppalliance/droneubuntu2404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-14', CXXSTD: '03,11,14,17,20,2b' } + asan,
"g++-14",
),
linux_pipeline(
"Linux 25.04 GCC 15",
"cppalliance/droneubuntu2504:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-15', CXXSTD: '03,11,14,17,20,23,2c' },
"g++-15",
),
linux_pipeline(
"Linux 16.04 Clang 3.5",
"cppalliance/droneubuntu1604:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-3.5', CXXSTD: '03,11' },
"clang-3.5",
),
linux_pipeline(
"Linux 16.04 Clang 3.6",
"cppalliance/droneubuntu1604:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-3.6', CXXSTD: '03,11,14' },
"clang-3.6",
),
linux_pipeline(
"Linux 16.04 Clang 3.7",
"cppalliance/droneubuntu1604:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-3.7', CXXSTD: '03,11,14' },
"clang-3.7",
),
linux_pipeline(
"Linux 16.04 Clang 3.8",
"cppalliance/droneubuntu1604:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-3.8', CXXSTD: '03,11,14' },
"clang-3.8",
),
linux_pipeline(
"Linux 18.04 Clang 3.9",
"cppalliance/droneubuntu1804:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-3.9', CXXSTD: '03,11,14' },
"clang-3.9",
),
linux_pipeline(
"Linux 18.04 Clang 4.0",
"cppalliance/droneubuntu1804:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-4.0', CXXSTD: '03,11,14' },
"clang-4.0",
),
linux_pipeline(
"Linux 18.04 Clang 5.0",
"cppalliance/droneubuntu1804:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-5.0', CXXSTD: '03,11,14' },
"clang-5.0",
),
linux_pipeline(
"Linux 18.04 Clang 6.0",
"cppalliance/droneubuntu1804:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-6.0', CXXSTD: '03,11,14,17' },
"clang-6.0",
),
linux_pipeline(
"Linux 20.04 Clang 7",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-7', CXXSTD: '03,11,14,17' },
"clang-7",
),
linux_pipeline(
"Linux 20.04 Clang 8",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-8', CXXSTD: '03,11,14,17' },
"clang-8",
),
linux_pipeline(
"Linux 20.04 Clang 9",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-9', CXXSTD: '03,11,14,17,2a' },
"clang-9",
),
linux_pipeline(
"Linux 20.04 Clang 10",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-10', CXXSTD: '03,11,14,17,2a' },
"clang-10",
),
linux_pipeline(
"Linux 20.04 Clang 11",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-11', CXXSTD: '03,11,14,17,2a' },
"clang-11",
),
linux_pipeline(
"Linux 20.04 Clang 12",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-12', CXXSTD: '03,11,14,17,2a' },
"clang-12",
),
linux_pipeline(
"Linux 22.04 Clang 13",
"cppalliance/droneubuntu2204:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-13', CXXSTD: '03,11,14,17,20,2b' },
"clang-13",
),
linux_pipeline(
"Linux 22.04 Clang 14",
"cppalliance/droneubuntu2204:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-14', CXXSTD: '03,11,14,17,20,2b' },
"clang-14",
),
linux_pipeline(
"Linux 22.04 Clang 15",
"cppalliance/droneubuntu2204:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-15', CXXSTD: '03,11,14,17,20,2b' },
"clang-15",
),
linux_pipeline(
"Linux 24.04 Clang 16",
"cppalliance/droneubuntu2404:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-16', CXXSTD: '03,11,14,17,20,2b' },
"clang-16",
),
linux_pipeline(
"Linux 24.04 Clang 17",
"cppalliance/droneubuntu2404:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-17', CXXSTD: '03,11,14,17,20,2b' },
"clang-17",
),
linux_pipeline(
"Linux 24.04 Clang 18 UBSAN",
"cppalliance/droneubuntu2404:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-18', CXXSTD: '03,11,14,17,20,2b' } + ubsan,
"clang-18",
),
linux_pipeline(
"Linux 24.04 Clang 18 ASAN",
"cppalliance/droneubuntu2404:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-18', CXXSTD: '03,11,14,17,20,2b' } + asan,
"clang-18",
),
linux_pipeline(
"Linux 24.04 Clang 19",
"cppalliance/droneubuntu2404:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-19', CXXSTD: '03,11,14,17,20,2b' },
"clang-19",
),
linux_pipeline(
"Linux 24.04 Clang 20",
"cppalliance/droneubuntu2404:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-20', CXXSTD: '03,11,14,17,20,23,2c' },
"clang-20",
),
linux_pipeline(
"Linux 25.10 Clang 21",
"cppalliance/droneubuntu2510:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-21', CXXSTD: '03,11,14,17,20,23,2c' },
"clang-21",
),
macos_pipeline(
"MacOS 10.15 Xcode 12.2 UBSAN",
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '03,11,14,1z' } + ubsan,
),
macos_pipeline(
"MacOS 10.15 Xcode 12.2 ASAN",
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '03,11,14,1z' } + asan,
),
macos_pipeline(
"MacOS 12.4 Xcode 13.2.1 UBSAN",
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '03,11,14,17,20,2b' } + ubsan,
xcode_version = "13.2.1", osx_version = "monterey", arch = "arm64",
),
macos_pipeline(
"MacOS 12.4 Xcode 13.2.1 ASAN",
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '03,11,14,17,20,2b' } + asan,
xcode_version = "13.2.1", osx_version = "monterey", arch = "arm64",
),
macos_pipeline(
"MacOS 12.4 Xcode 13.4.1 UBSAN",
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '03,11,14,17,20,2b' } + ubsan,
xcode_version = "13.4.1", osx_version = "monterey", arch = "arm64",
),
macos_pipeline(
"MacOS 12.4 Xcode 13.4.1 ASAN",
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '03,11,14,17,20,2b' } + asan,
xcode_version = "13.4.1", osx_version = "monterey", arch = "arm64",
),
macos_pipeline(
"MacOS 14 Xcode 16.2.0 UBSAN",
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '03,11,14,17,20,2b' } + ubsan,
xcode_version = "16.2.0", osx_version = "sonoma", arch = "arm64",
),
macos_pipeline(
"MacOS 14 Xcode 16.2.0 ASAN",
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '03,11,14,17,20,2b' } + asan,
xcode_version = "16.2.0", osx_version = "sonoma", arch = "arm64",
),
windows_pipeline(
"Windows VS2015 msvc-14.0",
"cppalliance/dronevs2015",
{ TOOLSET: 'msvc-14.0', CXXSTD: '14,latest', B2_DONT_EMBED_MANIFEST: '1' },
),
windows_pipeline(
"Windows VS2017 msvc-14.1",
"cppalliance/dronevs2017",
{ TOOLSET: 'msvc-14.1', CXXSTD: '14,17,latest' },
),
windows_pipeline(
"Windows VS2019 msvc-14.2",
"cppalliance/dronevs2019",
{ TOOLSET: 'msvc-14.2', CXXSTD: '14,17,20,latest' },
),
windows_pipeline(
"Windows VS2022 msvc-14.3",
"cppalliance/dronevs2022:1",
{ TOOLSET: 'msvc-14.3', CXXSTD: '14,17,20,latest' },
),
]

23
.drone/drone.bat Normal file
View File

@@ -0,0 +1,23 @@
@REM Copyright 2022 Peter Dimov
@REM Distributed under the Boost Software License, Version 1.0.
@REM https://www.boost.org/LICENSE_1_0.txt
@ECHO ON
set LIBRARY=%1
set DRONE_BUILD_DIR=%CD%
set BOOST_BRANCH=develop
if "%DRONE_BRANCH%" == "master" set BOOST_BRANCH=master
cd ..
git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root
cd boost-root
git submodule update --init tools/boostdep
xcopy /s /e /q %DRONE_BUILD_DIR% libs\%LIBRARY%\
python tools/boostdep/depinst/depinst.py -I example %LIBRARY%
cmd /c bootstrap
b2 -d0 headers
if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD%
if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD%
b2 -j3 libs/%LIBRARY%/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release embed-manifest-via=linker

25
.drone/drone.sh Executable file
View File

@@ -0,0 +1,25 @@
#!/bin/bash
# Copyright 2022 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# https://www.boost.org/LICENSE_1_0.txt
set -ex
export PATH=~/.local/bin:/usr/local/bin:$PATH
DRONE_BUILD_DIR=$(pwd)
BOOST_BRANCH=develop
if [ "$DRONE_BRANCH" = "master" ]; then BOOST_BRANCH=master; fi
cd ..
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
cd boost-root
git submodule update --init tools/boostdep
cp -r $DRONE_BUILD_DIR/* libs/$LIBRARY
python tools/boostdep/depinst/depinst.py -I example $LIBRARY
./bootstrap.sh
./b2 -d0 headers
echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam
./b2 -j3 libs/$LIBRARY/test toolset=$TOOLSET cxxstd=$CXXSTD variant=debug,release ${ADDRMD:+address-model=$ADDRMD} ${UBSAN:+undefined-sanitizer=norecover debug-symbols=on} ${ASAN:+address-sanitizer=norecover debug-symbols=on} ${LINKFLAGS:+linkflags=$LINKFLAGS}

View File

@@ -19,99 +19,216 @@ jobs:
include:
- toolset: gcc-4.8
cxxstd: "03,11"
os: ubuntu-16.04
container: ubuntu:18.04
os: ubuntu-latest
install: g++-4.8
- toolset: gcc-4.9
cxxstd: "03,11"
os: ubuntu-16.04
install: g++-4.9
- toolset: gcc-5
cxxstd: "03,11,14,14-gnu,1z,1z-gnu"
os: ubuntu-16.04
container: ubuntu:18.04
os: ubuntu-latest
install: g++-5
- toolset: gcc-6
cxxstd: "03,11,14,14-gnu,1z,1z-gnu"
os: ubuntu-16.04
container: ubuntu:18.04
os: ubuntu-latest
install: g++-6
- toolset: gcc-7
cxxstd: "03,11,14,14-gnu,17,17-gnu"
os: ubuntu-18.04
container: ubuntu:20.04
os: ubuntu-latest
install: g++-7
- toolset: gcc-8
cxxstd: "03,11,14,17,2a"
os: ubuntu-18.04
container: ubuntu:20.04
os: ubuntu-latest
install: g++-8
- toolset: gcc-9
cxxstd: "03,11,14,17,2a"
os: ubuntu-18.04
container: ubuntu:20.04
os: ubuntu-latest
- toolset: gcc-10
cxxstd: "03,11,14,17,2a"
os: ubuntu-18.04
- toolset: clang
compiler: clang++-3.5
cxxstd: "03,11,14"
os: ubuntu-16.04
install: clang-3.5
- toolset: clang
compiler: clang++-3.6
cxxstd: "03,11,14"
os: ubuntu-16.04
install: clang-3.6
- toolset: clang
compiler: clang++-3.7
cxxstd: "03,11,14"
os: ubuntu-16.04
install: clang-3.7
- toolset: clang
compiler: clang++-3.8
cxxstd: "03,11,14"
os: ubuntu-16.04
install: clang-3.8
os: ubuntu-22.04
install: g++-10
- toolset: gcc-11
cxxstd: "03,11,14,17,2a"
os: ubuntu-22.04
- toolset: gcc-12
cxxstd: "03,11,14,17,20,2b"
os: ubuntu-22.04
install: g++-12
- toolset: gcc-13
cxxstd: "03,11,14,17,20,2b"
container: ubuntu:24.04
os: ubuntu-latest
install: g++-13
- toolset: gcc-14
cxxstd: "03,11,14,17,20,2b"
container: ubuntu:24.04
os: ubuntu-latest
install: g++-14
- toolset: gcc-15
cxxstd: "03,11,14,17,20,23,2c"
container: ubuntu:25.10
os: ubuntu-latest
install: g++-15
- toolset: clang
compiler: clang++-3.9
cxxstd: "03,11,14"
os: ubuntu-16.04
container: ubuntu:18.04
os: ubuntu-latest
install: clang-3.9
- toolset: clang
compiler: clang++-4.0
cxxstd: "03,11,14"
os: ubuntu-16.04
container: ubuntu:18.04
os: ubuntu-latest
install: clang-4.0
- toolset: clang
compiler: clang++-5.0
cxxstd: "03,11,14,1z"
os: ubuntu-16.04
cxxstd: "03,11,14"
container: ubuntu:18.04
os: ubuntu-latest
install: clang-5.0
- toolset: clang
compiler: clang++-6.0
cxxstd: "03,11,14,17"
os: ubuntu-18.04
container: ubuntu:20.04
os: ubuntu-latest
install: clang-6.0
- toolset: clang
compiler: clang++-7
cxxstd: "03,11,14,17"
os: ubuntu-18.04
container: ubuntu:20.04
os: ubuntu-latest
install: clang-7
- toolset: clang
compiler: clang++-8
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
cxxstd: "03,11,14,17"
container: ubuntu:20.04
os: ubuntu-latest
install: clang-8
- toolset: clang
compiler: clang++-9
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
container: ubuntu:20.04
os: ubuntu-latest
install: clang-9
- toolset: clang
compiler: clang++-10
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
container: ubuntu:20.04
os: ubuntu-latest
install: clang-10
- toolset: clang
compiler: clang++-11
cxxstd: "03,11,14,17,2a"
os: macos-10.15
container: ubuntu:20.04
os: ubuntu-latest
install: clang-11
- toolset: clang
compiler: clang++-12
cxxstd: "03,11,14,17,2a"
container: ubuntu:20.04
os: ubuntu-latest
install: clang-12
- toolset: clang
compiler: clang++-13
cxxstd: "03,11,14,17,20,2b"
container: ubuntu:22.04
os: ubuntu-latest
install: clang-13
- toolset: clang
compiler: clang++-14
cxxstd: "03,11,14,17,20,2b"
container: ubuntu:22.04
os: ubuntu-latest
install: clang-14
- toolset: clang
compiler: clang++-15
cxxstd: "03,11,14,17,20,2b"
container: ubuntu:22.04
os: ubuntu-latest
install: clang-15
- toolset: clang
compiler: clang++-16
cxxstd: "03,11,14,17,20,2b"
container: ubuntu:24.04
os: ubuntu-latest
install: clang-16
- toolset: clang
compiler: clang++-17
cxxstd: "03,11,14,17,20,2b"
container: ubuntu:24.04
os: ubuntu-latest
install: clang-17
- toolset: clang
compiler: clang++-18
cxxstd: "03,11,14,17,20,2b"
container: ubuntu:24.04
os: ubuntu-latest
install: clang-18
- toolset: clang
compiler: clang++-19
cxxstd: "03,11,14,17,20,2b"
container: ubuntu:24.04
os: ubuntu-latest
install: clang-19
- toolset: clang
compiler: clang++-20
cxxstd: "03,11,14,17,20,23,2c"
container: ubuntu:24.04
os: ubuntu-latest
install: clang-20
- toolset: clang
compiler: clang++-21
cxxstd: "03,11,14,17,20,23,2c"
container: ubuntu:25.10
os: ubuntu-latest
install: clang-21
- toolset: clang
cxxstd: "03,11,14,17,20,2b"
os: macos-14
- toolset: clang
cxxstd: "03,11,14,17,20,2b"
os: macos-15
- toolset: clang
cxxstd: "03,11,14,17,20,23,2c"
os: macos-26
runs-on: ${{matrix.os}}
container:
image: ${{matrix.container}}
volumes:
- /node20217:/node20217:rw,rshared
- ${{ startsWith(matrix.container, 'ubuntu:1') && '/node20217:/__e/node20:ro,rshared' || ' ' }}
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v2
- name: Setup container environment
if: matrix.container
run: |
apt-get update
apt-get -y install sudo python3 git g++ curl xz-utils
- name: Install nodejs20glibc2.17
if: ${{ startsWith( matrix.container, 'ubuntu:1' ) }}
run: |
curl -LO https://archives.boost.io/misc/node/node-v20.9.0-linux-x64-glibc-217.tar.xz
tar -xf node-v20.9.0-linux-x64-glibc-217.tar.xz --strip-components 1 -C /node20217
ldd /__e/node20/bin/node
- uses: actions/checkout@v4
- name: Install packages
if: matrix.install
run: sudo apt install ${{matrix.install}}
run: |
sudo apt-get update
sudo apt-get -y install ${{matrix.install}}
- name: Setup Boost
run: |
@@ -132,7 +249,7 @@ jobs:
mkdir -p libs/$LIBRARY
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
git submodule update --init tools/boostdep
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" -I example $LIBRARY
python3 tools/boostdep/depinst/depinst.py --git_args "--jobs 3" -I example $LIBRARY
./bootstrap.sh
./b2 -d0 headers
@@ -151,23 +268,28 @@ jobs:
fail-fast: false
matrix:
include:
- toolset: msvc-14.1
- toolset: msvc-14.3
cxxstd: "14,17,20,latest"
addrmd: 32,64
os: windows-2022
- toolset: msvc-14.3
cxxstd: "14,17,20,latest"
addrmd: 32,64
cxxflags: "-Zc:preprocessor"
os: windows-2022
- toolset: clang-win
cxxstd: "14,17,latest"
addrmd: 32,64
os: windows-2016
- toolset: msvc-14.2
cxxstd: "14,17,latest"
addrmd: 32,64
os: windows-2019
os: windows-2022
- toolset: gcc
cxxstd: "03,11,14,17,2a"
addrmd: 64
os: windows-2019
os: windows-2022
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Setup Boost
shell: cmd
@@ -195,4 +317,344 @@ jobs:
shell: cmd
run: |
cd ../boost-root
b2 -j3 libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release
if not "${{matrix.cxxflags}}" == "" set CXXFLAGS=cxxflags=${{matrix.cxxflags}}
b2 -j3 libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} %CXXFLAGS% variant=debug,release embed-manifest-via=linker
posix-cmake-subdir:
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-22.04
- os: ubuntu-24.04
- os: macos-14
- os: macos-15
- os: macos-26
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v4
- 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 1 https://github.com/boostorg/boost.git boost-root
cd boost-root
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
git submodule update --init tools/boostdep
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY
- name: Use library with add_subdirectory
run: |
cd ../boost-root/libs/$LIBRARY/test/cmake_subdir_test
mkdir __build__ && cd __build__
cmake ..
cmake --build .
ctest --output-on-failure --no-tests=error
posix-cmake-install:
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-22.04
- os: ubuntu-24.04
- os: macos-14
- os: macos-15
- os: macos-26
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v4
- 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 1 https://github.com/boostorg/boost.git boost-root
cd boost-root
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
git submodule update --init tools/boostdep
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY
- name: Configure
run: |
cd ../boost-root
mkdir __build__ && cd __build__
cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DCMAKE_INSTALL_PREFIX=~/.local ..
- name: Install
run: |
cd ../boost-root/__build__
cmake --build . --target install
- name: Use the installed library
run: |
cd ../boost-root/libs/$LIBRARY/test/cmake_install_test && mkdir __build__ && cd __build__
cmake -DCMAKE_INSTALL_PREFIX=~/.local ..
cmake --build .
ctest --output-on-failure --no-tests=error
posix-cmake-test:
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-22.04
- os: ubuntu-24.04
- os: macos-14
- os: macos-15
- os: macos-26
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v4
- 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 1 https://github.com/boostorg/boost.git boost-root
cd boost-root
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
git submodule update --init tools/boostdep
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY
- name: Configure
run: |
cd ../boost-root
mkdir __build__ && cd __build__
cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DBUILD_TESTING=ON ..
- name: Build tests
run: |
cd ../boost-root/__build__
cmake --build . --target tests
- name: Run tests
run: |
cd ../boost-root/__build__
ctest --output-on-failure --no-tests=error
windows-cmake-subdir:
strategy:
fail-fast: false
matrix:
include:
- os: windows-latest
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v4
- 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 1 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 --git_args "--jobs 3" %LIBRARY%
- name: Use library with add_subdirectory (Debug)
shell: cmd
run: |
cd ../boost-root/libs/%LIBRARY%/test/cmake_subdir_test
mkdir __build__ && cd __build__
cmake ..
cmake --build . --config Debug
ctest --output-on-failure --no-tests=error -C Debug
- name: Use library with add_subdirectory (Release)
shell: cmd
run: |
cd ../boost-root/libs/%LIBRARY%/test/cmake_subdir_test/__build__
cmake --build . --config Release
ctest --output-on-failure --no-tests=error -C Release
windows-cmake-install:
strategy:
fail-fast: false
matrix:
include:
- os: windows-latest
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v4
- 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 1 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 --git_args "--jobs 3" %LIBRARY%
- name: Configure
shell: cmd
run: |
cd ../boost-root
mkdir __build__ && cd __build__
cmake -DBOOST_INCLUDE_LIBRARIES=%LIBRARY% -DCMAKE_INSTALL_PREFIX=C:/cmake-prefix ..
- name: Install (Debug)
shell: cmd
run: |
cd ../boost-root/__build__
cmake --build . --target install --config Debug
- name: Install (Release)
shell: cmd
run: |
cd ../boost-root/__build__
cmake --build . --target install --config Release
- name: Use the installed library (Debug)
shell: cmd
run: |
cd ../boost-root/libs/%LIBRARY%/test/cmake_install_test && mkdir __build__ && cd __build__
cmake -DCMAKE_INSTALL_PREFIX=C:/cmake-prefix ..
cmake --build . --config Debug
ctest --output-on-failure --no-tests=error -C Debug
- name: Use the installed library (Release)
shell: cmd
run: |
cd ../boost-root/libs/%LIBRARY%/test/cmake_install_test/__build__
cmake --build . --config Release
ctest --output-on-failure --no-tests=error -C Release
windows-cmake-test:
strategy:
fail-fast: false
matrix:
include:
- os: windows-latest
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v4
- 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 1 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 --git_args "--jobs 3" %LIBRARY%
- name: Configure
shell: cmd
run: |
cd ../boost-root
mkdir __build__ && cd __build__
cmake -DBOOST_INCLUDE_LIBRARIES=%LIBRARY% -DBUILD_TESTING=ON ..
- name: Build tests (Debug)
shell: cmd
run: |
cd ../boost-root/__build__
cmake --build . --target tests --config Debug
- name: Run tests (Debug)
shell: cmd
run: |
cd ../boost-root/__build__
ctest --output-on-failure --no-tests=error -C Debug
- name: Build tests (Release)
shell: cmd
run: |
cd ../boost-root/__build__
cmake --build . --target tests --config Release
- name: Run tests (Release)
shell: cmd
run: |
cd ../boost-root/__build__
ctest --output-on-failure --no-tests=error -C Release

View File

@@ -22,7 +22,7 @@ matrix:
include:
- os: linux
compiler: g++-5
env: TOOLSET=gcc CXXSTD=14-gnu,1z-gnu
env: TOOLSET=gcc CXXSTD=14,14-gnu,1z,1z-gnu
addons:
apt:
packages:
@@ -32,7 +32,7 @@ matrix:
- os: linux
compiler: g++-6
env: TOOLSET=gcc CXXSTD=14-gnu,1z-gnu
env: TOOLSET=gcc CXXSTD=14,14-gnu,1z,1z-gnu
addons:
apt:
packages:
@@ -42,7 +42,7 @@ matrix:
- os: linux
compiler: g++-7
env: TOOLSET=gcc CXXSTD=14-gnu,17-gnu
env: TOOLSET=gcc CXXSTD=14,14-gnu,17,17-gnu
addons:
apt:
packages:

25
CMakeLists.txt Normal file
View File

@@ -0,0 +1,25 @@
# Generated by `boostdep --cmake describe`
# Copyright 2020 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.16)
project(boost_describe VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
add_library(boost_describe INTERFACE)
add_library(Boost::describe ALIAS boost_describe)
target_include_directories(boost_describe INTERFACE include)
target_link_libraries(boost_describe
INTERFACE
Boost::mp11
)
if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt")
add_subdirectory(test)
endif()

View File

@@ -2,19 +2,19 @@
A C++14 reflection library. Provides macros for describing enumerators and
struct/class members, and primitives for querying this information. See
[the documentation](https://pdimov.github.io/describe) for more information
and usage examples.
[the documentation](https://www.boost.org/doc/libs/develop/libs/describe/)
for more information and usage examples.
## Supported Compilers
* GCC 5 or later with `-std=gnu++14` or above
* GCC 8 or later with `-std=c++14` or above
* Clang 3.6 or later with `-std=c++14` or above
* Visual Studio 2015, 2017, 2019
* GCC 5 or later with `-std=c++14` or above
* Clang 3.9 or later with `-std=c++14` or above
* Visual Studio 2015 or later
Tested on [Travis](https://travis-ci.org/github/pdimov/describe/) and
Tested on [Github Actions](https://github.com/boostorg/describe/actions) and
[Appveyor](https://ci.appveyor.com/project/pdimov/describe).
## License
Distributed under the [Boost Software License, Version 1.0](http://boost.org/LICENSE_1_0.txt).
Distributed under the
[Boost Software License, Version 1.0](http://boost.org/LICENSE_1_0.txt).

View File

@@ -1,4 +1,4 @@
# Copyright 2016-2020 Peter Dimov
# Copyright 2016-2021 Peter Dimov
# 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)
@@ -15,22 +15,23 @@ branches:
environment:
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
TOOLSET: msvc-14.0
TOOLSET: msvc-9.0,msvc-10.0,msvc-11.0
ADDRMD: 32
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
TOOLSET: msvc-12.0,msvc-14.0
ADDRMD: 32,64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
TOOLSET: msvc-14.1
CXXSTD: 14,17
ADDRMD: 32,64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
TOOLSET: clang-win
CXXSTD: 14,17,latest
ADDRMD: 32,64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
TOOLSET: msvc-14.2
CXXSTD: 14,17,latest
CXXSTD: 14,17,20,latest
ADDRMD: 32,64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
TOOLSET: clang-win
CXXSTD: 14,17,latest
CXXSTD: 14,17,20,latest
ADDRMD: 32,64
install:
- set BOOST_BRANCH=develop
@@ -49,4 +50,5 @@ build: off
test_script:
- if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD%
- if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD%
- b2 -j3 libs/describe/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release embed-manifest-via=linker
- if not "%CXXFLAGS%" == "" set CXXFLAGS=cxxflags=%CXXFLAGS%
- b2 -j3 libs/describe/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% %CXXFLAGS% variant=debug,release embed-manifest-via=linker

20
build.jam Normal file
View File

@@ -0,0 +1,20 @@
# Copyright 2023-2024 René Ferdinand Rivera Morell
# Copyright 2024 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# https://www.boost.org/LICENSE_1_0.txt
require-b2 5.2 ;
constant boost_dependencies :
/boost/mp11//boost_mp11
;
project /boost/describe ;
explicit
[ alias boost_describe : : : : <include>include <library>$(boost_dependencies) ]
[ alias all : boost_describe test ]
;
call-if : boost-library describe
;

1
doc/.gitignore vendored
View File

@@ -1 +1,2 @@
/pdf/
/html/

View File

@@ -9,11 +9,15 @@ Peter Dimov
:toc: left
:toclevels: 4
:idprefix:
:listing-caption: Code Example
:docinfo: private-footer
:source-highlighter: rouge
:source-language: c++
:leveloffset: +1
include::describe/overview.adoc[]
include::describe/changes.adoc[]
include::describe/enums.adoc[]
include::describe/classes.adoc[]
include::describe/examples.adoc[]

43
doc/describe/changes.adoc Normal file
View File

@@ -0,0 +1,43 @@
////
Copyright 2021 Peter Dimov
Distributed under the Boost Software License, Version 1.0.
https://www.boost.org/LICENSE_1_0.txt
////
[#changes]
# Revision History
:idprefix:
## Changes in Boost 1.91.0
* Under {cpp}20, described nested enums now work when the enclosing class is still incomplete. (Thanks to Julien Blanc.)
* Made `enum_to_string` constexpr. (Thanks to Julien Blanc.)
## Changes in Boost 1.84.0
* Added an overload of `enum_from_string` that takes a string view, to avoid
the need for null termination.
## Changes in Boost 1.81.0
* To allow the inclusion of `enumerators.hpp`, `bases.hpp`, and `members.hpp`
when the option `-pedantic` is used, the invocation of `BOOST_DESCRIBE_ENUM`
has been moved from `modifiers.hpp` into a separate header,
`modifier_description.hpp`. As a consequence, `modifiers.hpp` no longer
includes `enum.hpp`. Code that has been relying on this implicit inclusion
may fail, and will need to be fixed to include `enum.hpp`.
## Changes in Boost 1.79.0
* Enabled unions in `BOOST_DESCRIBE_STRUCT` and updated examples to check `std::is_union<T>`.
* Added example of defining a `fmtlib` class formatter.
* Added example of defining a `fmtlib` enum formatter.
* Added example of printing pointers to members.
## Changes in Boost 1.78.0
* Added `has_describe_enumerators`, `has_describe_bases`, `has_describe_members`.
* Added `enum_to_string`, `enum_from_string`.
* Added relational and stream insertion operators.
* Added `descriptor_by_name`, `descriptor_by_pointer`.
* Added `struct_to_tuple` example.

View File

@@ -1,5 +1,5 @@
////
Copyright 2020 Peter Dimov
Copyright 2020, 2021 Peter Dimov
Distributed under the Boost Software License, Version 1.0.
https://www.boost.org/LICENSE_1_0.txt
////
@@ -8,6 +8,8 @@ https://www.boost.org/LICENSE_1_0.txt
# Describing Class Types
:idprefix: classes_
## Class Types with Public Members
If you have a `struct`
```
@@ -31,8 +33,15 @@ It takes three arguments: the `struct` name, a list of base classes
(empty in our example), and a list of (public) members by name (this includes
both data members and member functions.)
To describe a class type with protected or private members, use the
`BOOST_DESCRIBE_CLASS` macro instead, placing it _inside the class_.
Since `BOOST_DESCRIBE_STRUCT` is placed outside the type, it's non-intrisive,
does not require access to the definition, and can therefore be used to describe
third-party types or types defined in system headers.
## Class Types with Protected or Private Members
To describe a class type, use the `BOOST_DESCRIBE_CLASS` macro instead, placing
it _inside the class_. This gives the macro access to the protected and private
members, but is intrusive and requires access to the definition.
```
class Y: private X
@@ -61,6 +70,8 @@ private:
It takes three member lists, for the public, protected, and private members.
## Retrieving Class Properties
Once a type `T` is annotated, its properties can be retrieved via
`describe_bases<T, M>` and `describe_members<T, M>` (`M` is a bitmask of
modifiers such as `mod_public | mod_static | mod_function`).
@@ -73,17 +84,11 @@ These primitives are defined in namespace `boost::describe`, in the headers
presence of `mod_public` includes the public bases in the result, its absence
excludes them. The other two modifiers work similarly.
(At least in principle. The current implementation cannot distinguish between
protected and private base classes, so protected bases are returned as private.
Consequently, using `mod_protected` gives no result. Lifting this limitation
would require compiler support.)
`describe_members` takes a bitwise-or combination of the following possible
modifiers: `mod_public`, `mod_protected`, `mod_private`, `mod_static`,
`mod_function`, `mod_inherited`, `mod_hidden`.
`mod_function`, `mod_any_member`, `mod_inherited`, `mod_hidden`.
The access modifiers work the same as with `describe_bases` (except here
`mod_protected` actually works when `BOOST_DESCRIBE_CLASS` is used.)
The access modifiers work the same as with `describe_bases`.
(For types annotated with `BOOST_DESCRIBE_STRUCT`, the protected and private
member lists will be empty.)
@@ -94,6 +99,9 @@ the nonstatic members are returned.
When `mod_function` is present, the member functions are returned, otherwise
the data members are returned.
When `mod_any_member` is present, `mod_static` and `mod_function` are ignored
and all members are returned regardless of kind.
When `mod_inherited` is present, members of base classes are also returned.
When `mod_hidden` is present, hidden inherited members are included. A member
@@ -127,3 +135,55 @@ For an example of how to use the base and data member descriptors, see
For an example of how to use member function descriptors, see
<<example_json_rpc>>.
## Overloaded Member Functions
To describe an overloaded member function, you will need to resort to
a more complicated syntax, as simply listing its name (say, `f`) will make
the library attempt to form a member pointer with `&X::f`, which would fail
because it's not clear to which `f` this expression refers.
To disambiguate, precede the function name with the type of the function, in
parentheses, as shown in the following example:
```
struct X
{
int f();
int f() const;
void f( int x );
};
BOOST_DESCRIBE_STRUCT(X, (), (
(int ()) f,
(int () const) f,
(void (int)) f
))
```
The type of the function is the same as its declaration, without the name.
Be sure to retain the space between the parenthesized function type and its name,
because omitting it will compile happily on GCC and Clang but will lead to
inscrutable errors on MSVC due to its nonstandard preprocessor.
Pay attention to the proper placement of the parentheses, because a mistake there
will also lead to hard to decipher compiler errors, on all compilers.
The same technique also works with `BOOST_DESCRIBE_CLASS`, and with static member
functions:
```
class Y
{
public:
static void f( int x );
static void f( int x, int y );
BOOST_DESCRIBE_CLASS(Y, (), ((void (int)) f, (void (int, int)) f), (), ())
};
```
The case where a member function and a static member function have the same name
and the same function type is currently not supported.

View File

@@ -8,5 +8,5 @@ https://www.boost.org/LICENSE_1_0.txt
# Copyright and License
:idprefix:
This documentation is copyright 2020 Peter Dimov and is distributed under
This documentation is copyright 2020, 2021 Peter Dimov and is distributed under
the http://www.boost.org/LICENSE_1_0.txt[Boost Software License, Version 1.0].

View File

@@ -28,8 +28,6 @@ BOOST_DESCRIBE_ENUM(E, v1, v2, v3)
The macro is defined in `<boost/describe/enum.hpp>` and should be placed in
the same namespace as the enum.
For scoped enums, use `BOOST_DESCRIBE_ENUM_CLASS` instead.
If your enumerators don't have initializers, instead of repeating them
```
@@ -49,6 +47,28 @@ For defining `enum class E2` instead, use `BOOST_DEFINE_ENUM_CLASS`. To add
an underlying type, i.e. `enum E3: int` or `enum class E4: unsigned char`,
use `BOOST_DEFINE_FIXED_ENUM` and `BOOST_DEFINE_FIXED_ENUM_CLASS`, respectively.
If your enumeration type is nested inside a class or a `struct`, use the
`BOOST_DESCRIBE_NESTED_ENUM` macro next to the `enum`, as follows:
```
class X
{
private:
enum class E
{
v1,
v2
};
BOOST_DESCRIBE_NESTED_ENUM(E, v1, v2)
public:
// ...
};
```
Once an enumeration type `E` is annotated, one can use `describe_enumerators<E>`
to obtain a _descriptor list_. (`describe_enumerators` is defined in the
`boost::describe` namespace, in `<boost/describe/enumerators.hpp>`.)

View File

@@ -19,6 +19,15 @@ descriptors using `mp11::mp_for_each` and prints them.
include::../../example/printing_enums_ct.cpp[lines=5..-1]
----
Sample output:
[listing]
----
v1: 11
v2: 12
v3: 5
----
[#example_printing_enums_rt]
## Printing Enumerators with a Run Time Loop
@@ -31,41 +40,70 @@ an ordinary `for` loop, instead of `mp_for_each`.
include::../../example/printing_enums_rt.cpp[lines=5..-1]
----
Sample output:
[listing]
----
v1: 0
v2: 1
v3: 2
v4: 3
v5: 4
v6: 5
----
[#example_enum_to_string]
## enum_to_string
This example shows a function that, given an enumerator
value, returns its name.
Providing `enum_to_string` in a library is made difficult
by the fact that the desired behavior when the passed value
does not correspond to a named enumerator varies depending
on the specific use case. But, since defining the function
is trivial when `describe_enumerators` is available, every
user can easily have his own.
This specific example elects to return `"(unnamed)"` when
the enum value doesn't have a name.
value, returns its name. If the value does not correspond
to a named value, the function returns `"(unnamed)"`.
[source]
----
include::../../example/enum_to_string.cpp[lines=5..-1]
----
Sample output:
[listing]
----
E(3): v1
E(0): (unnamed)
----
Since release 1.78.0, the library provides `enum_to_string`.
It differs from the one in the example by having a second
parameter that determines what should be returned when the
value doesn't correspond to a named enumerator.
[#example_string_to_enum]
## string_to_enum
The opposite of the previous example; returns an enumerator
value when given the enumerator name. The same problem exists
here with respect to the error handling strategy when the string
passed does not correspond to any enumerator name. This example
throws an exception.
value when given the enumerator name. When the string passed
does not correspond to any enumerator name, throws an exception.
[source]
----
include::../../example/string_to_enum.cpp[lines=5..-1]
----
Sample output:
[listing]
----
v1: 0
v2: 1
v3: 2
v4: Invalid enumerator name 'v4' for enum type 'enum E'
----
Since release 1.78.0, the library provides `enum_from_string`.
It differs from the function in the example by signaling failure
by a `bool` return value instead of using exceptions. The
enumerator value is assigned to the output argument.
[#example_print_function]
## Defining a Universal Print Function
@@ -86,12 +124,135 @@ change its state and hence cannot violate its invariant.)
include::../../example/print_function.cpp[lines=5..-1]
----
Sample output:
[listing]
----
{{.m1 = 1}, {.m2 = 2}, .m1 = 3, .m2 = 4}
----
Since release 1.78.0, this universal `operator<<` is supplied
by the library, in the `boost::describe::operators` namespace.
It's enabled by means of a using declaration in the namespace
containing the described application types, like in the example
below:
```
namespace app
{
struct X
{
int a = 1;
};
BOOST_DESCRIBE_STRUCT(X, (), (a))
using boost::describe::operators::operator<<;
}
```
[#example_hash_value]
## Implementing hash_value
This example defines a universal `hash_value` overload that
computes the hash value of an annotated struct or class. It
does so by iterating over the described bases and members and
calling `boost::hash_combine` on each.
The overload is defined in namespace `app` in order to apply
to all annotated classes also defined in `app`.
NOTE: Since release 1.81.0, Boost.ContainerHash provides its
own, built-in, support for described classes, by having an
overload of `boost::hash_value` very similar to the one given
below. Consequently, when using Boost 1.81.0 or later, you
don't need the below `hash_value` function, as it will cause
an ambiguity.
[source]
----
include::../../example/hash_value.cpp[lines=5..-1]
----
Sample output:
[listing]
----
12526671134390370097
----
[#example_equality]
## Implementing operator==
This example defines a universal `operator==` overload that
iterates over the described bases and members and compares
them for equality using `==`.
The overload is defined in namespace `app` in order to apply
to all annotated classes also defined in `app`.
[source]
----
include::../../example/equality.cpp[lines=5..-1]
----
Sample output:
[listing]
----
true false
----
Since release 1.78.0, this universal `operator==` is supplied
by the library, in the `boost::describe::operators` namespace.
It's enabled by means of a using declaration in the namespace
containing the described application types, like in the example
below:
```
namespace app
{
struct X
{
int a = 1;
};
BOOST_DESCRIBE_STRUCT(X, (), (a))
using boost::describe::operators::operator==;
}
```
The rest of the relational operators are also provided and can
be enabled similarly.
[#example_struct_to_tuple]
## struct_to_tuple
This example defines a function `struct_to_tuple` that takes
a described class type as an argument and returns a tuple of
all its public members.
[source]
----
include::../../example/struct_to_tuple.cpp[lines=5..-1]
----
Sample output:
[listing]
----
std::tuple<int, float>: 1, 3.14
----
[#example_to_json]
## Automatic Conversion to JSON
This example defines a universal `tag_invoke` overload that
automatically converts an annotated struct to a
http://master.json.cpp.al[Boost.JSON] value by iterating
http://boost.org/libs/json[Boost.JSON] value by iterating
over the described public members and adding them to the return
`boost::json::object`.
@@ -102,11 +263,23 @@ The presence of private members is taken as an indication that
a universal conversion is not suitable, so the overload is
disabled in this case using `std::enable_if_t`.
NOTE: Since release 1.81.0, Boost.JSON provides its
own, built-in, support for described classes. Consequently,
when using Boost 1.81.0 or later, you don't need the below
`tag_invoke` function.
[source]
----
include::../../example/to_json.cpp[lines=5..-1]
----
Sample output:
[listing]
----
{"v":[{"x":1,"y":2},{"x":3,"y":4}],"m":{"k1":{"x":5,"y":6},"k2":{"x":7,"y":8}}}
----
[#example_from_json]
## Automatic Conversion from JSON
@@ -114,11 +287,24 @@ Like the previous example, but in the other direction. Defines
a `tag_invoke` overload that converts a `boost::json::value` to
an annotated struct.
NOTE: Since release 1.81.0, Boost.JSON provides its
own, built-in, support for described classes. Consequently,
when using Boost 1.81.0 or later, you don't need the below
`tag_invoke` function.
[source]
----
include::../../example/from_json.cpp[lines=5..-1]
----
Sample output:
[listing]
----
jv: {"x":1,"y":2}
a: { 1, 2 }
----
[#example_serialization]
## Automatic Serialization
@@ -131,12 +317,55 @@ support to annotated classes.
include::../../example/serialization.cpp[lines=5..-1]
----
Sample output:
[listing]
----
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE boost_serialization>
<boost_serialization signature="serialization::archive" version="19">
<c1 class_id="0" tracking_level="0" version="0">
<v class_id="1" tracking_level="0" version="0">
<count>3</count>
<item_version>0</item_version>
<item class_id="2" tracking_level="0" version="0">
<base.1 class_id="3" tracking_level="0" version="0">
<x>1</x>
</base.1>
<base.2 class_id="4" tracking_level="0" version="0">
<y>2</y>
</base.2>
</item>
<item>
<base.1>
<x>3</x>
</base.1>
<base.2>
<y>4</y>
</base.2>
</item>
<item>
<base.1>
<x>5</x>
</base.1>
<base.2>
<y>6</y>
</base.2>
</item>
</v>
</c1>
</boost_serialization>
22 serialization::archive 19 0 0 0 0 3 0 0 0 0 0 1 0 0 2 3 4 5 6
----
[#example_json_rpc]
## Automatic JSON RPC
This example defines a generic `call` function that can be used to
invoke a member function by name, with the arguments passed in a
http://master.json.cpp.al[Boost.JSON] array. The result is returned
http://boost.org/libs/json[Boost.JSON] array. The result is returned
in a `boost::json::value`.
[source]
@@ -144,3 +373,139 @@ in a `boost::json::value`.
include::../../example/json_rpc.cpp[lines=5..-1]
----
Sample output:
[listing]
----
"Hello, world!"
3
----
[#example_console]
## Interactive Variable Console
This example implements an interactive console that allows printing
and modifying variables. It uses http://boost.org/libs/json[Boost.JSON]
for converting the variables to and from a string form.
[source]
----
include::../../example/console.cpp[lines=9..-1]
----
Sample output:
[listing]
----
> help
"Enter a variable name ('x', 'y', 'v', or 'm') to print its value; enter variable=value to assign a new value to a variable. Values are in JSON format."
> x
1
> y
3.14E0
> v
[1,2,3]
> m
{"BTC":4.489868E4,"ETH":1.38657E3}
> x="hello"
Error: not a number [boost.json:15]
> x=3.14
Error: not exact [boost.json:16]
> x=4
> x
4
> y=6.28
> y
6.28E0
> v=["hello", "world"]
Error: not a number [boost.json:15]
> v=[1.2, 3.4]
Error: not exact [boost.json:16]
> v=[11, 27]
> c
Error: 'c': no such variable
> v
[11,27]
> m={"BTC": 42139.07, "ETH": 2912.00}
> m
{"BTC":4.213907E4,"ETH":2.912E3}
----
[#example_fmtlib_class_formatter]
## `fmtlib` Class Formatter
This example defines a universal https://github.com/fmtlib/fmt[`fmtlib`]
formatter that works on any class or struct type that has been described
with `BOOST_DESCRIBE_STRUCT` or `BOOST_DESCRIBE_CLASS`. It's similar to
<<example_print_function,the universal print function shown above>>.
[source]
----
include::../../example/fmtlib_class_formatter.cpp[lines=5..-1]
----
Sample output:
[listing]
----
{ { .r=255, .g=192, .b=16 }, .first={ .x=1, .y=2 }, .last={ .x=3, .y=4 } }
----
[#example_fmtlib_enum_formatter]
## `fmtlib` Enum Formatter
This example defines a https://github.com/fmtlib/fmt[`fmtlib`] formatter
for described enums.
[source]
----
include::../../example/fmtlib_enum_formatter.cpp[lines=5..-1]
----
Sample output:
[listing]
----
____v1____
____7_____
----
[#example_pm_to_string]
## Printing Pointers to Members
This example defines an `operator<<` overload for pointers to members.
[source]
----
include::../../example/pm_to_string.cpp[lines=9..-1]
----
Sample output:
[listing]
----
&X::m [int]
&X::f [int() const]
&Y::m [int]
&X::f [int() const]
&Y::g [int() const]
&Z::(unknown) [void()]
----

View File

@@ -14,22 +14,24 @@ https://boost.org/libs/mp11[Boost.Mp11].
## Supported Compilers
* GCC 5 or later with `-std=gnu++14` or above
* GCC 8 or later with `-std=c++14` or above
* Clang 3.6 or later with `-std=c++14` or above
* Visual Studio 2015, 2017, 2019
* GCC 5 or later with `-std=c++14` or above
* Clang 3.9 or later with `-std=c++14` or above
* Visual Studio 2015 or later
Tested on https://travis-ci.org/github/pdimov/describe[Travis] and
https://ci.appveyor.com/project/pdimov/describe[Appveyor].
Tested on https://github.com/boostorg/describe/actions[Github Actions]
and https://ci.appveyor.com/project/pdimov/describe[Appveyor].
## Limitations
This implementation has the following limitations:
* Up to 52 elements are supported in the lists of enumerators,
bases, and members.
* Protected base classes cannot be distinguished from private
base classes and are considered private.
* Overloaded member functions are not supported. Member names
must be unique within the class.
* Bitfields are not supported.
base classes when the described class is final, and are considered
private.
* Bitfields are not supported. It's not possible to form a pointer
to member to a bitfield.
* Reference members are not supported. It's not possible to form a
pointer to member to a reference.
* Anonymous unions are not supported.
* Reference members are not supported.

View File

@@ -1,5 +1,5 @@
////
Copyright 2020 Peter Dimov
Copyright 2020, 2021 Peter Dimov
Distributed under the Boost Software License, Version 1.0.
https://www.boost.org/LICENSE_1_0.txt
////
@@ -12,7 +12,8 @@ https://www.boost.org/LICENSE_1_0.txt
```
#define BOOST_DESCRIBE_ENUM(E, ...) /*...*/
#define BOOST_DESCRIBE_ENUM_CLASS(E, ...) /*...*/
#define BOOST_DESCRIBE_NESTED_ENUM(E, ...) /*...*/
#define BOOST_DEFINE_ENUM(E, ...) \
enum E { __VA_ARGS__ }; BOOST_DESCRIBE_ENUM(E, __VA_ARGS__)
@@ -48,11 +49,12 @@ struct Di
```
where `vi` is the corresponding identifier passed to the macro.
### BOOST_DESCRIBE_ENUM_CLASS
### BOOST_DESCRIBE_NESTED_ENUM
`BOOST_DESCRIBE_ENUM_CLASS(E, v1, ..., vN)` should be used instead of
`BOOST_DESCRIBE_ENUM` when `E` is a scoped enumeration type, and has
the same effect.
`BOOST_DESCRIBE_NESTED_ENUM(E, v1, v2, ..., vN)` is similar to
`BOOST_DESCRIBE_ENUM` and is used to annotate enumeration types nested inside
class (or `struct`) types. It should be placed in the class type where the
`enum` is defined.
### BOOST_DEFINE_ENUM
@@ -67,7 +69,7 @@ BOOST_DESCRIBE_ENUM(E, v1, v2, ..., vN)
`BOOST_DEFINE_ENUM_CLASS(E, v1, v2, ..., vN)` is a convenience macro expanding to
```
enum class E { v1, v2, ..., vN };
BOOST_DESCRIBE_ENUM_CLASS(E, v1, v2, ..., vN)
BOOST_DESCRIBE_ENUM(E, v1, v2, ..., vN)
```
### BOOST_DEFINE_FIXED_ENUM
@@ -83,10 +85,10 @@ BOOST_DESCRIBE_ENUM(E, v1, v2, ..., vN)
`BOOST_DEFINE_FIXED_ENUM_CLASS(E, Base, v1, v2, ..., vN)` is a convenience macro expanding to
```
enum class E: Base { v1, v2, ..., vN };
BOOST_DESCRIBE_ENUM_CLASS(E, v1, v2, ..., vN)
BOOST_DESCRIBE_ENUM(E, v1, v2, ..., vN)
```
## <boost/describe/enumerators.hpp>
## <boost/describe/{zwsp}enumerators{zwsp}.hpp>
```
namespace boost {
@@ -94,6 +96,8 @@ namespace describe {
template<class E> using describe_enumerators = /*...*/;
template<class E> using has_describe_enumerators = /*...*/;
} }
```
@@ -114,6 +118,14 @@ struct Di
```
where `vi` is the i-th enumerator.
If `E` is not a described enumeration type, `describe_enumerators<E>` causes
a substitution failure.
### has_describe_enumerators<E>
`has_describe_enumerators<E>::value` is `true` when `E` is a described
enumeration type, `false` otherwise.
## <boost/describe/class.hpp>
```
@@ -196,8 +208,9 @@ enum modifiers
mod_virtual = 8,
mod_static = 16,
mod_function = 32,
mod_inherited = 64,
mod_hidden = 128,
mod_any_member = 64,
mod_inherited = 128,
mod_hidden = 256
};
constexpr modifiers mod_any_access = static_cast<modifiers>( mod_public | mod_protected | mod_private );
@@ -217,9 +230,16 @@ following flags:
* `mod_virtual` - returned when a base class is a virtual base
* `mod_static` - returns static members (when not given, returns nonstatic members)
* `mod_function` - returns member functions (when not given, returns data members)
* `mod_any_member` - overrides `mod_static` and `mod_function` and returns all members regardless of kind
* `mod_inherited` - includes members of base classes
* `mod_hidden` - includes hidden inherited members
## <boost/describe/{zwsp}modifier_description.hpp>
The header `modifier_description.hpp` includes `modifiers.hpp` and invokes
`BOOST_DESCRIBE_ENUM` on `modifiers`, allowing `describe_enumerators<modifiers>`
to work.
## <boost/describe/bases.hpp>
```
@@ -228,6 +248,8 @@ namespace describe {
template<class T, unsigned M> using describe_bases = /*...*/;
template<class T> using has_describe_bases = /*...*/;
} }
```
@@ -253,6 +275,18 @@ where `type` is the type of the base class, and `modifiers` are a bitwise-or
combination of `mod_public`, `mod_protected`, `mod_private`, and `mod_virtual`
that reflects the properties of the base class.
If `T` is not a described class type, `describe_bases<T, M>` causes a
substitution failure.
### has_describe_bases<T>
`has_describe_bases<T>::value` is `true` when `T` is a described class type,
`false` otherwise.
Since the library does not provide a way to describe bases and members separately,
`has_describe_bases` and `has_describe_members` are, in practice, synonyms. They
are provided separately for consistency.
## <boost/describe/members.hpp>
```
@@ -261,14 +295,16 @@ namespace describe {
template<class T, unsigned M> using describe_members = /*...*/;
template<class T> using has_describe_members = /*...*/;
} }
```
### describe_members<T, M>
`M` must be a bitwise-or combination of `mod_public`, `mod_protected`,
`mod_private`, `mod_static`, `mod_function`, `mod_inherited`, and
`mod_hidden`, and acts as a filter.
`mod_private`, `mod_static`, `mod_function`, `mod_any_member`,
`mod_inherited`, and `mod_hidden`, and acts as a filter.
`describe_members<T, M>` returns `L<D1, D2, ..., Dn>`, where `L` is a class
template of the form
@@ -290,6 +326,195 @@ member, and `modifiers` are a bitwise-or combination of `mod_public`,
`mod_protected`, `mod_private`, `mod_static`, `mod_function`, `mod_inherited`,
and `mod_hidden` that reflects the properties of the member.
If `T` is not a described class type, `describe_members<T, M>` causes a
substitution failure.
### has_describe_members<T>
`has_describe_members<T>::value` is `true` when `T` is a described class type,
`false` otherwise.
Since the library does not provide a way to describe bases and members separately,
`has_describe_bases` and `has_describe_members` are, in practice, synonyms. They
are provided separately for consistency.
## <boost/describe/{zwsp}enum_to_string{zwsp}.hpp>
```
namespace boost {
namespace describe {
template<class E> char const * enum_to_string( E e, char const * def ) noexcept;
} }
```
### enum_to_string
The function `enum_to_string` returns the name of the enumerator `e`. `E` must
be a described enumeration type. If `e` does not correspond to one of the described
values, the function returns `def`.
## <boost/describe/{zwsp}enum_from_string{zwsp}.hpp>
```
namespace boost {
namespace describe {
template<class E> bool enum_from_string( char const * name, E & e ) noexcept;
template<class S, class E> bool enum_from_string( S const & name, E & e ) noexcept;
} }
```
### enum_from_string
The function `enum_from_string` assigns to `e` the enumerator value corresponding
to `name` and returns `true`. `E` must be a described enumeration type. If `name`
does not correspond to one of the described values, the function returns `false`.
The second overload only participates in overload resolution when `S` is a
string-like type such as `std::string` or `std::string_view`. String-like types
are recognized by the presence of nested `value_type` and `traits_type` typedefs
and are expected to have a non-throwing `operator==` taking `char const*`.
## <boost/describe/operators.hpp>
```
namespace boost {
namespace describe {
namespace operators {
template<class T> bool operator==( T const& t1, T const& t2 );
template<class T> bool operator!=( T const& t1, T const& t2 );
template<class T> bool operator<( T const& t1, T const& t2 );
template<class T> bool operator>( T const& t1, T const& t2 );
template<class T> bool operator<=( T const& t1, T const& t2 );
template<class T> bool operator>=( T const& t1, T const& t2 );
template<class T, class Ch, class Tr>
std::basic_ostream<Ch, Tr>&
operator<<( std::basic_ostream<Ch, Tr>& os, T const& t );
} } }
```
The header `<boost/describe/operators.hpp>` defines generic operators for
described class types. They are used by bringing them into the namespace
containing the described types via a using declaration, as in the example
below:
```
namespace app
{
struct X
{
int a = 1;
};
BOOST_DESCRIBE_STRUCT(X, (), (a))
using boost::describe::operators::operator==;
using boost::describe::operators::operator!=;
using boost::describe::operators::operator<<;
}
```
### operator==
If all bases and members compare equal, returns `true`, otherwise `false`.
### operator!=
Returns the negation of `operator==`.
### operator<
Performs a lexicographical comparison over the bases and members in sequence
using `operator<` and returns the result.
### operator>
Returns the result of `operator<` with the arguments reversed.
### operator\<=
Returns the negated result of `operator>`.
### operator>=
Returns the negated result of `operator<`.
### operator<<
Outputs a representation of `t` to `os` by recursively using `operator<<`
to output all bases and then all members.
## <boost/describe/{zwsp}descriptor_by_name{zwsp}.hpp>
```
namespace boost {
namespace describe {
#define BOOST_DESCRIBE_MAKE_NAME(s) /*...*/
template<class L, class N> using descriptor_by_name = /*...*/;
} }
```
### BOOST_DESCRIBE_MAKE_NAME
The macro `BOOST_DESCRIBE_MAKE_NAME` creates a type that identifies the
name given as an argument. It should be used as follows:
```
using N = BOOST_DESCRIBE_MAKE_NAME(some_member);
```
### descriptor_by_name
`descriptor_by_name<L, N>` searches the descriptor list `L` for the member
with the name identified by `N`. `N` should be a type created by
`BOOST_DESCRIBE_MAKE_NAME` as in the above example. `L` is intended to be
a list returned by `describe_members`, although since enumerator descriptors
also have `::name`, a list returned by `describe_enumerators` will work as
well.
.Using descriptor_by_name
```
using L = describe_members<SomeType, mod_any_access>;
using N = BOOST_DESCRIBE_MAKE_NAME(some_member);
using D = descriptor_by_name<L, N>; // descriptor for SomeType::some_member
```
## <boost/describe/{zwsp}descriptor_by_pointer{zwsp}.hpp>
```
namespace boost {
namespace describe {
template<class L, auto Pm> using descriptor_by_pointer = /*...*/;
} }
```
### descriptor_by_pointer
`descriptor_by_pointer<L, Pm>` searches the descriptor list `L` for the member
pointer `Pm`. `L` should be a list returned by `describe_members`.
Since `auto` template parameters are a {cpp}17 feature, using
`descriptor_by_pointer` requires {cpp}17.
.Using descriptor_by_pointer
```
using L = describe_members<X, mod_any_access>;
using D = descriptor_by_pointer<L, &X::a>; // descriptor for X::a
```
## <boost/describe.hpp>
This convenience header includes all the headers previously

File diff suppressed because it is too large Load Diff

129
example/console.cpp Normal file
View File

@@ -0,0 +1,129 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#if defined(_MSC_VER)
# pragma warning(disable: 4702) // unreachable code
#endif
#include <boost/describe.hpp>
#include <boost/mp11.hpp>
#include <boost/json.hpp>
#include <boost/utility/string_view.hpp>
#include <string>
#include <stdexcept>
#include <vector>
#include <map>
#include <iostream>
// get variable
template<class Scope> boost::json::value get( Scope& scope, boost::string_view name )
{
using Md = boost::describe::describe_members<Scope, boost::describe::mod_public>;
bool found = false;
boost::json::value result;
boost::mp11::mp_for_each<Md>([&](auto D) {
if( !found && name == D.name )
{
result = boost::json::value_from( scope.*D.pointer );
found = true;
}
});
if( !found )
{
throw std::invalid_argument(
std::string( "'" ) + std::string( name ) + "': no such variable" );
}
return result;
}
// set variable
template<class T> void set_impl( T & t, boost::string_view /*name*/, boost::json::value const& value )
{
t = boost::json::value_to<T>( value );
}
template<class T> void set_impl( T const & /*t*/, boost::string_view name, boost::json::value const& /*value*/ )
{
throw std::invalid_argument(
std::string( "'" ) + std::string( name ) + "': variable cannot be modified" );
}
template<class Scope> void set( Scope& scope, boost::string_view name, boost::json::value const& value )
{
using Md = boost::describe::describe_members<Scope, boost::describe::mod_public>;
bool found = false;
boost::mp11::mp_for_each<Md>([&](auto D) {
if( !found && name == D.name )
{
set_impl( scope.*D.pointer, name, value );
found = true;
}
});
if( !found )
{
throw std::invalid_argument(
std::string( "'" ) + std::string( name ) + "': no such variable" );
}
}
//
struct globals
{
std::string const help = "Enter a variable name ('x', 'y', 'v', or 'm') to print its value; enter variable=value to assign a new value to a variable. Values are in JSON format.";
int x = 1;
double y = 3.14;
std::vector<int> v{ 1, 2, 3 };
std::map<std::string, double> m{ { "BTC", 44898.68 }, { "ETH", 1386.57 } };
};
BOOST_DESCRIBE_STRUCT( globals, (), (help, x, y, v, m) )
int main()
{
globals g_;
for( ;; )
{
std::cout << "\n> ";
std::string line;
std::getline( std::cin, line );
try
{
std::size_t i = line.find( '=' );
if( i != std::string::npos )
{
set( g_, line.substr( 0, i ), boost::json::parse( line.substr( i + 1 ) ) );
}
else
{
std::cout << get( g_, line ) << std::endl;
}
}
catch( std::exception const& x )
{
std::cout << "Error: " << x.what() << std::endl;
}
}
}

74
example/equality.cpp Normal file
View File

@@ -0,0 +1,74 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe.hpp>
#include <boost/mp11.hpp>
#include <boost/variant2/variant.hpp>
#include <vector>
using namespace boost::describe;
namespace app
{
template<class T,
class Bd = describe_bases<T, mod_any_access>,
class Md = describe_members<T, mod_any_access>,
class En = std::enable_if_t<!std::is_union<T>::value> >
bool operator==( T const& t1, T const& t2 )
{
bool r = true;
boost::mp11::mp_for_each<Bd>([&](auto D){
using B = typename decltype(D)::type;
r = r && (B const&)t1 == (B const&)t2;
});
boost::mp11::mp_for_each<Md>([&](auto D){
r = r && t1.*D.pointer == t2.*D.pointer;
});
return r;
}
struct A
{
int x = 1;
};
BOOST_DESCRIBE_STRUCT(A, (), (x))
struct B
{
int y = 2;
};
BOOST_DESCRIBE_STRUCT(B, (), (y))
struct C
{
std::vector<boost::variant2::variant<A, B>> v;
};
BOOST_DESCRIBE_STRUCT(C, (), (v))
} // namespace app
#include <iostream>
int main()
{
app::C c1, c2, c3;
c1.v.push_back( app::A{} );
c2.v.push_back( app::A{} );
c3.v.push_back( app::B{} );
std::cout << std::boolalpha
<< ( c1 == c2 ) << ' '
<< ( c1 == c3 ) << std::endl;
}

View File

@@ -0,0 +1,101 @@
// Copyright 2022 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe.hpp>
#include <boost/mp11.hpp>
#include <fmt/format.h>
#include <type_traits>
template<class T> struct fmt::formatter<T, char, std::enable_if_t<
boost::describe::has_describe_bases<T>::value &&
boost::describe::has_describe_members<T>::value &&
!std::is_union<T>::value>>
{
constexpr auto parse( format_parse_context& ctx )
{
auto it = ctx.begin(), end = ctx.end();
if( it != end && *it != '}' )
{
throw_format_error( "invalid format" );
}
return it;
}
auto format( T const& t, format_context& ctx ) const
{
using namespace boost::describe;
using Bd = describe_bases<T, mod_any_access>;
using Md = describe_members<T, mod_any_access>;
auto out = ctx.out();
*out++ = '{';
bool first = true;
boost::mp11::mp_for_each<Bd>([&](auto D){
if( !first )
{
*out++ = ',';
}
first = false;
out = fmt::format_to( out, " {}",
(typename decltype(D)::type const&)t );
});
boost::mp11::mp_for_each<Md>([&](auto D){
if( !first )
{
*out++ = ',';
}
first = false;
out = fmt::format_to( out, " .{}={}",
D.name, t.*D.pointer );
});
if( !first )
{
*out++ = ' ';
}
*out++ = '}';
return out;
}
};
struct point
{
int x, y;
};
BOOST_DESCRIBE_STRUCT( point, (), (x, y) )
struct color
{
unsigned char r, g, b;
};
BOOST_DESCRIBE_STRUCT( color, (), (r, g, b) )
struct line: color
{
point first, last;
};
BOOST_DESCRIBE_STRUCT( line, (color), (first, last) )
int main()
{
fmt::print( "{}\n", line{ { 255, 192, 16 }, { 1, 2 }, { 3, 4 } } );
}

View File

@@ -0,0 +1,60 @@
// Copyright 2022 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe.hpp>
#include <fmt/format.h>
#include <type_traits>
template<class T> struct fmt::formatter<T, char, std::enable_if_t<
boost::describe::has_describe_enumerators<T>::value>>
{
private:
using U = std::underlying_type_t<T>;
fmt::formatter<fmt::string_view, char> sf_;
fmt::formatter<U, char> nf_;
public:
constexpr auto parse( format_parse_context& ctx )
{
auto i1 = sf_.parse( ctx );
auto i2 = nf_.parse( ctx );
if( i1 != i2 )
{
throw_format_error( "invalid format" );
}
return i1;
}
auto format( T const& t, format_context& ctx ) const
{
char const * s = boost::describe::enum_to_string( t, 0 );
if( s )
{
return sf_.format( s, ctx );
}
else
{
return nf_.format( static_cast<U>( t ), ctx );
}
}
};
enum E1
{
v1, v2, v3 = 11
};
BOOST_DESCRIBE_ENUM( E1, v1, v2, v3 )
int main()
{
fmt::print( "{:_^10}\n", E1::v1 );
fmt::print( "{:_^10}\n", (E1)7 );
}

View File

@@ -5,11 +5,14 @@
#include <boost/describe.hpp>
#include <boost/mp11.hpp>
#include <boost/json.hpp>
#include <boost/version.hpp>
#include <type_traits>
namespace app
{
#if BOOST_VERSION < 108100
template<class T> void extract( boost::json::object const & obj, char const * name, T & value )
{
value = boost::json::value_to<T>( obj.at( name ) );
@@ -19,7 +22,7 @@ template<class T,
class D1 = boost::describe::describe_members<T,
boost::describe::mod_public | boost::describe::mod_protected>,
class D2 = boost::describe::describe_members<T, boost::describe::mod_private>,
class En = std::enable_if_t<boost::mp11::mp_empty<D2>::value> >
class En = std::enable_if_t<boost::mp11::mp_empty<D2>::value && !std::is_union<T>::value> >
T tag_invoke( boost::json::value_to_tag<T> const&, boost::json::value const& v )
{
@@ -36,6 +39,8 @@ template<class T,
return t;
}
#endif
struct A
{
int x;

78
example/hash_value.cpp Normal file
View File

@@ -0,0 +1,78 @@
// Copyright 2021, 2022 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/container_hash/hash.hpp>
#include <boost/describe.hpp>
#include <boost/mp11.hpp>
#include <boost/variant2/variant.hpp>
#include <boost/version.hpp>
#include <vector>
using namespace boost::describe;
namespace app
{
#if BOOST_VERSION < 108100
template<class T,
class Bd = describe_bases<T, mod_any_access>,
class Md = describe_members<T, mod_any_access>,
class En = std::enable_if_t<!std::is_union<T>::value> >
std::size_t hash_value( T const & t )
{
std::size_t r = 0;
boost::mp11::mp_for_each<Bd>([&](auto D){
using B = typename decltype(D)::type;
boost::hash_combine( r, (B const&)t );
});
boost::mp11::mp_for_each<Md>([&](auto D){
boost::hash_combine( r, t.*D.pointer );
});
return r;
}
#endif
struct A
{
int x = 1;
};
BOOST_DESCRIBE_STRUCT(A, (), (x))
struct B
{
int y = 2;
};
BOOST_DESCRIBE_STRUCT(B, (), (y))
struct C
{
std::vector<boost::variant2::variant<A, B>> v;
};
BOOST_DESCRIBE_STRUCT(C, (), (v))
} // namespace app
#include <iostream>
int main()
{
app::C c;
c.v.push_back( app::A{} );
c.v.push_back( app::B{} );
std::cout << boost::hash<app::C>()( c ) << std::endl;
}

View File

@@ -34,7 +34,7 @@ template<class C1, class C2, class R, class... A>
template<class C>
boost::json::value
call( C & c, boost::string_view method, boost::json::value const & args )
call( C & c, boost::string_view method, boost::json::array const & args )
{
using Fd = boost::describe::describe_members<C,
boost::describe::mod_public | boost::describe::mod_function>;
@@ -46,7 +46,7 @@ template<class C>
if( !found && method == D.name)
{
result = call_impl( c, D.pointer, args.as_array() );
result = call_impl( c, D.pointer, args );
found = true;
}

125
example/pm_to_string.cpp Normal file
View File

@@ -0,0 +1,125 @@
// Copyright 2022 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#if defined(__GNUC__) && __GNUC__ == 12
# pragma GCC diagnostic ignored "-Wrestrict" // false positive
#endif
#include <boost/describe.hpp>
#include <boost/mp11.hpp>
#include <boost/core/type_name.hpp>
#include <string>
#include <ostream>
namespace detail
{
template<class T1, class T2>
constexpr auto equals( T1 t1, T2 t2, int ) -> decltype( t1 == t2 )
{
return t1 == t2;
}
template<class T1, class T2>
constexpr bool equals( T1 /*t1*/, T2 /*t2*/, long )
{
return false;
}
using namespace boost::describe;
template<class T, class C,
class L = describe_members<C, mod_any_access | mod_any_member>>
char const* get_member_name( T C::* pm, int )
{
char const * name = nullptr;
boost::mp11::mp_for_each<L>([&](auto D){
if( equals( D.pointer, pm, 0 ) ) name = D.name;
});
return name;
}
template<class T, class C>
char const* get_member_name( T C::* /*pm*/, long )
{
return nullptr;
}
} // namespace detail
template<class T, class C>
std::string pm_to_string( T C::* pm )
{
char const * name = ::detail::get_member_name( pm, 0 );
if( name == nullptr ) name = "(unknown)";
return "&" + boost::core::type_name<C>() + "::" + name
+ " [" + boost::core::type_name<T>() + "]";
}
template<class T, class C>
std::ostream& operator<<( std::ostream& os, T C::* pm )
{
os << pm_to_string( pm );
return os;
}
struct X
{
int m;
int f() const { return m; }
};
BOOST_DESCRIBE_STRUCT(X, (), (m, f))
struct Y: public X
{
int m;
int g() const { return -m; }
};
BOOST_DESCRIBE_STRUCT(Y, (X), (m, g))
struct Z
{
void h() {}
};
#if !defined(_MSC_VER) || defined(__clang__)
// MSVC doesn't support BOOST_DESCRIBE_CLASS inside
// templates until 2022 in C++20 mode
template<class T1, class T2> struct pair
{
T1 first;
T2 second;
BOOST_DESCRIBE_CLASS(pair, (), (first, second), (), ())
};
#endif
#include <iostream>
int main()
{
std::cout << &X::m << std::endl;
std::cout << &X::f << std::endl;
std::cout << &Y::m << std::endl;
std::cout << &Y::f << std::endl;
std::cout << &Y::g << std::endl;
std::cout << &Z::h << std::endl;
#if !defined(_MSC_VER) || defined(__clang__)
std::cout << &pair<int, float>::second << std::endl;
#endif
}

View File

@@ -10,7 +10,8 @@ using namespace boost::describe;
template<class T,
class Bd = describe_bases<T, mod_any_access>,
class Md = describe_members<T, mod_any_access>>
class Md = describe_members<T, mod_any_access>,
class En = std::enable_if_t<!std::is_union<T>::value> >
std::ostream& operator<<( std::ostream & os, T const & t )
{
os << "{";

View File

@@ -24,8 +24,8 @@ template<class Archive, class T,
class D3 = boost::describe::describe_members<T,
boost::describe::mod_public | boost::describe::mod_protected>,
class D4 = boost::describe::describe_members<T, boost::describe::mod_private>,
class En = std::enable_if_t<
boost::mp11::mp_empty<D2>::value && boost::mp11::mp_empty<D4>::value> >
class En = std::enable_if_t< boost::mp11::mp_empty<D2>::value &&
boost::mp11::mp_empty<D4>::value && !std::is_union<T>::value> >
void serialize( Archive & ar, T & t, boost::serialization::version_type )
{

View File

@@ -12,7 +12,8 @@
[[noreturn]] void throw_invalid_name( char const * name, char const * type )
{
throw std::runtime_error(
std::string( "Invalid enumerator name '" ) + name + "' for enum type '" + type + "'" );
std::string( "Invalid enumerator name '" ) + name
+ "' for enum type '" + type + "'" );
}
template<class E> E string_to_enum( char const * name )

View File

@@ -0,0 +1,57 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe.hpp>
#include <tuple>
namespace desc = boost::describe;
template<class T, template<class...> class L, class... D>
auto struct_to_tuple_impl( T const& t, L<D...> )
{
return std::make_tuple( t.*D::pointer... );
}
template<class T,
class Dm = desc::describe_members<T,
desc::mod_public | desc::mod_inherited>,
class En = std::enable_if_t<!std::is_union<T>::value> >
auto struct_to_tuple( T const& t )
{
return struct_to_tuple_impl( t, Dm() );
}
#include <boost/core/type_name.hpp>
#include <iostream>
struct X
{
int a = 1;
};
BOOST_DESCRIBE_STRUCT(X, (), (a))
struct Y
{
float b = 3.14f;
};
BOOST_DESCRIBE_STRUCT(Y, (), (b))
struct Z: X, Y
{
};
BOOST_DESCRIBE_STRUCT(Z, (X, Y), ())
int main()
{
Z z;
auto tp = struct_to_tuple( z );
std::cout <<
boost::core::type_name<decltype(tp)>() << ": "
<< std::get<0>(tp) << ", " << std::get<1>(tp);
}

View File

@@ -5,6 +5,7 @@
#include <boost/describe.hpp>
#include <boost/mp11.hpp>
#include <boost/json.hpp>
#include <boost/version.hpp>
#include <type_traits>
#include <vector>
#include <map>
@@ -12,11 +13,13 @@
namespace app
{
#if BOOST_VERSION < 108100
template<class T,
class D1 = boost::describe::describe_members<T,
boost::describe::mod_public | boost::describe::mod_protected>,
class D2 = boost::describe::describe_members<T, boost::describe::mod_private>,
class En = std::enable_if_t<boost::mp11::mp_empty<D2>::value> >
class En = std::enable_if_t<boost::mp11::mp_empty<D2>::value && !std::is_union<T>::value> >
void tag_invoke( boost::json::value_from_tag const&, boost::json::value& v, T const & t )
{
@@ -29,6 +32,8 @@ template<class T,
});
}
#endif
struct A
{
int x;

View File

@@ -11,5 +11,11 @@
#include <boost/describe/enum.hpp>
#include <boost/describe/class.hpp>
#include <boost/describe/modifiers.hpp>
#include <boost/describe/enum_to_string.hpp>
#include <boost/describe/enum_from_string.hpp>
#include <boost/describe/operators.hpp>
#include <boost/describe/descriptor_by_name.hpp>
#include <boost/describe/descriptor_by_pointer.hpp>
#include <boost/describe/modifier_description.hpp>
#endif // #ifndef BOOST_DESCRIBE_HPP_INCLUDED

View File

@@ -1,16 +1,18 @@
#ifndef BOOST_DESCRIBE_BASES_HPP_INCLUDED
#define BOOST_DESCRIBE_BASES_HPP_INCLUDED
// Copyright 2020 Peter Dimov
// Copyright 2020, 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/modifiers.hpp>
#include <boost/describe/detail/void_t.hpp>
#include <boost/describe/detail/config.hpp>
#if defined(BOOST_DESCRIBE_CXX11)
#include <boost/mp11/algorithm.hpp>
#include <type_traits>
namespace boost
{
@@ -19,17 +21,27 @@ namespace describe
namespace detail
{
template<class T> using _describe_bases = decltype( _base_descriptor_fn( static_cast<T*>(0) ) );
template<class T> using _describe_bases = decltype( boost_base_descriptor_fn( static_cast<T**>(0) ) );
template<unsigned M> struct base_filter
{
template<class T> using fn = mp11::mp_bool< ( M & mod_any_access & T::modifiers ) != 0 >;
};
template<class T, class En = void> struct has_describe_bases: std::false_type
{
};
template<class T> struct has_describe_bases<T, void_t<_describe_bases<T>>>: std::true_type
{
};
} // namespace detail
template<class T, unsigned M> using describe_bases = mp11::mp_copy_if_q<detail::_describe_bases<T>, detail::base_filter<M>>;
template<class T> using has_describe_bases = detail::has_describe_bases<T>;
} // namespace describe
} // namespace boost

View File

@@ -16,6 +16,7 @@
#include <boost/describe/detail/bases.hpp>
#include <boost/describe/detail/members.hpp>
#include <type_traits>
namespace boost
{
@@ -33,6 +34,7 @@ namespace describe
friend BOOST_DESCRIBE_PRIVATE_MEMBERS(C, BOOST_DESCRIBE_PP_UNPACK Private)
#define BOOST_DESCRIBE_STRUCT(C, Bases, Members) \
static_assert(std::is_class<C>::value || std::is_union<C>::value, "BOOST_DESCRIBE_STRUCT should only be used with class types"); \
BOOST_DESCRIBE_BASES(C, BOOST_DESCRIBE_PP_UNPACK Bases) \
BOOST_DESCRIBE_PUBLIC_MEMBERS(C, BOOST_DESCRIBE_PP_UNPACK Members) \
BOOST_DESCRIBE_PROTECTED_MEMBERS(C) \
@@ -52,16 +54,17 @@ namespace describe
#define BOOST_DESCRIBE_PRIVATE_MEMBERS_(...) BOOST_DESCRIBE_PRIVATE_MEMBERS(__VA_ARGS__)
#define BOOST_DESCRIBE_CLASS(C, Bases, Public, Protected, Private) \
friend BOOST_DESCRIBE_BASES_(C BOOST_DESCRIBE_PP_UNPACK Bases) \
friend BOOST_DESCRIBE_PUBLIC_MEMBERS_(C BOOST_DESCRIBE_PP_UNPACK Public) \
friend BOOST_DESCRIBE_PROTECTED_MEMBERS_(C BOOST_DESCRIBE_PP_UNPACK Protected) \
friend BOOST_DESCRIBE_PRIVATE_MEMBERS_(C BOOST_DESCRIBE_PP_UNPACK Private)
BOOST_DESCRIBE_MAYBE_UNUSED friend BOOST_DESCRIBE_BASES_(C BOOST_DESCRIBE_PP_UNPACK Bases) \
BOOST_DESCRIBE_MAYBE_UNUSED friend BOOST_DESCRIBE_PUBLIC_MEMBERS_(C BOOST_DESCRIBE_PP_UNPACK Public) \
BOOST_DESCRIBE_MAYBE_UNUSED friend BOOST_DESCRIBE_PROTECTED_MEMBERS_(C BOOST_DESCRIBE_PP_UNPACK Protected) \
BOOST_DESCRIBE_MAYBE_UNUSED friend BOOST_DESCRIBE_PRIVATE_MEMBERS_(C BOOST_DESCRIBE_PP_UNPACK Private)
#define BOOST_DESCRIBE_STRUCT(C, Bases, Members) \
BOOST_DESCRIBE_BASES_(C BOOST_DESCRIBE_PP_UNPACK Bases) \
BOOST_DESCRIBE_PUBLIC_MEMBERS_(C BOOST_DESCRIBE_PP_UNPACK Members) \
BOOST_DESCRIBE_PROTECTED_MEMBERS_(C) \
BOOST_DESCRIBE_PRIVATE_MEMBERS_(C)
static_assert(std::is_class<C>::value || std::is_union<C>::value, "BOOST_DESCRIBE_STRUCT should only be used with class types"); \
BOOST_DESCRIBE_MAYBE_UNUSED BOOST_DESCRIBE_BASES_(C BOOST_DESCRIBE_PP_UNPACK Bases) \
BOOST_DESCRIBE_MAYBE_UNUSED BOOST_DESCRIBE_PUBLIC_MEMBERS_(C BOOST_DESCRIBE_PP_UNPACK Members) \
BOOST_DESCRIBE_MAYBE_UNUSED BOOST_DESCRIBE_PROTECTED_MEMBERS_(C) \
BOOST_DESCRIBE_MAYBE_UNUSED BOOST_DESCRIBE_PRIVATE_MEMBERS_(C)
#endif

View File

@@ -0,0 +1,41 @@
#ifndef BOOST_DESCRIBE_DESCRIPTOR_BY_NAME_HPP_INCLUDED
#define BOOST_DESCRIBE_DESCRIPTOR_BY_NAME_HPP_INCLUDED
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/detail/cx_streq.hpp>
#include <boost/describe/detail/config.hpp>
#if defined(BOOST_DESCRIBE_CXX14)
#include <boost/mp11/algorithm.hpp>
#include <boost/mp11/bind.hpp>
#include <boost/mp11/integral.hpp>
namespace boost
{
namespace describe
{
namespace detail
{
template<class D, class N> using match_by_name = mp11::mp_bool<cx_streq(N::name(), D::name)>;
#define BOOST_DESCRIBE_MAKE_NAME_IMPL2(s, k) struct _boost_name_##s##_##k { static constexpr char const * name() { return #s; } }
#define BOOST_DESCRIBE_MAKE_NAME_IMPL(s, k) BOOST_DESCRIBE_MAKE_NAME_IMPL2(s, k)
} // namespace detail
#define BOOST_DESCRIBE_MAKE_NAME(s) BOOST_DESCRIBE_MAKE_NAME_IMPL(s, __LINE__)
template<class L, class N> using descriptor_by_name = mp11::mp_at<L, mp11::mp_find_if_q<L, mp11::mp_bind_back<detail::match_by_name, N>>>;
} // namespace describe
} // namespace boost
#endif // defined(BOOST_DESCRIBE_CXX14)
#endif // #ifndef BOOST_DESCRIBE_DESCRIPTOR_BY_NAME_HPP_INCLUDED

View File

@@ -0,0 +1,48 @@
#ifndef BOOST_DESCRIBE_DESCRIPTOR_BY_POINTER_HPP_INCLUDED
#define BOOST_DESCRIBE_DESCRIPTOR_BY_POINTER_HPP_INCLUDED
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/detail/config.hpp>
#if defined(__cpp_nontype_template_parameter_auto) && __cpp_nontype_template_parameter_auto >= 201606L
#include <boost/mp11/algorithm.hpp>
#include <boost/mp11/bind.hpp>
#include <boost/mp11/integral.hpp>
namespace boost
{
namespace describe
{
namespace detail
{
template<class Pm> constexpr bool cx_pmeq( Pm p1, Pm p2 )
{
return p1 == p2;
}
template<class Pm1, class Pm2> constexpr bool cx_pmeq( Pm1, Pm2 )
{
return false;
}
template<auto Pm> struct match_by_pointer
{
template<class D> using fn = mp11::mp_bool< cx_pmeq( D::pointer, Pm ) >;
};
} // namespace detail
template<class L, auto Pm> using descriptor_by_pointer = mp11::mp_at<L, mp11::mp_find_if_q<L, detail::match_by_pointer<Pm>>>;
} // namespace describe
} // namespace boost
#endif // __cpp_nontype_template_parameter_auto
#endif // #ifndef BOOST_DESCRIBE_DESCRIPTOR_BY_POINTER_HPP_INCLUDED

View File

@@ -5,7 +5,7 @@
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/modifiers.hpp>
#include <boost/describe/detail/compute_base_modifiers.hpp>
#include <boost/describe/detail/pp_for_each.hpp>
#include <boost/describe/detail/list.hpp>
#include <type_traits>
@@ -17,52 +17,32 @@ namespace describe
namespace detail
{
// is_public_base_of
template<class T, class U> using is_public_base_of = std::is_convertible<U*, T*>;
// is_virtual_base_of
template<class T, class U, class = void> struct can_cast: std::false_type {};
template<class T, class U> struct can_cast<T, U, decltype((void)(U*)(T*)0)>: std::true_type {};
template<class T, class U> using is_virtual_base_of =
std::integral_constant<bool, can_cast<U, T>::value && !can_cast<T, U>::value>;
// base_modifiers
template<class C, class B> constexpr unsigned base_modifiers() noexcept
{
return (is_public_base_of<B, C>::value? mod_public: mod_private) | (is_virtual_base_of<B, C>::value? mod_virtual: 0);
}
// base_descriptor
template<class C, class B> struct base_descriptor
{
static_assert( std::is_base_of<B, C>::value, "A type listed as a base is not one" );
using type = B;
static constexpr unsigned modifiers = base_modifiers<C, B>();
static constexpr unsigned modifiers = compute_base_modifiers<C, B>();
};
#ifndef __cpp_inline_variables
template<class C, class B> constexpr unsigned base_descriptor<C, B>::modifiers;
template<class... T> auto base_descriptor_fn_impl( int, T... )
{
return list<T...>();
}
#define BOOST_DESCRIBE_BASE_IMPL(C, B) , boost::describe::detail::base_descriptor<C, B>()
#if defined(_MSC_VER) && !defined(__clang__)
#define BOOST_DESCRIBE_BASES(C, ...) inline auto _base_descriptor_fn( C * ) \
{ return boost::describe::detail::base_descriptor_fn_impl( 0 BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_BASE_IMPL, C, __VA_ARGS__) ); }
#else
#define BOOST_DESCRIBE_BASES(C, ...) inline auto _base_descriptor_fn( C * ) \
{ return boost::describe::detail::base_descriptor_fn_impl( 0 BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_BASE_IMPL, C, ##__VA_ARGS__) ); }
#endif
// bases_descriptor
template<typename ...>
struct bases_descriptor_impl;
template<class C, class ...Bs>
struct bases_descriptor_impl<C, list<Bs...>>
{
using type = list<base_descriptor<C, Bs>...>;
};
#define BOOST_DESCRIBE_BASES(C, ...) inline auto boost_base_descriptor_fn( C** ) \
{ return typename boost::describe::detail::bases_descriptor_impl<C, boost::describe::detail::list<__VA_ARGS__>>::type(); }
} // namespace detail
} // namespace describe
} // namespace boost

View File

@@ -0,0 +1,73 @@
#ifndef BOOST_DESCRIBE_DETAIL_COMPUTE_BASE_MODIFIERS_HPP_INCLUDED
#define BOOST_DESCRIBE_DETAIL_COMPUTE_BASE_MODIFIERS_HPP_INCLUDED
// Copyright 2020, 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/modifiers.hpp>
#include <type_traits>
namespace boost
{
namespace describe
{
namespace detail
{
#if defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable: 4594) // can never be instantiated - indirect virtual base class is inaccessible
# pragma warning(disable: 4624) // destructor was implicitly defined as deleted
#endif
// is_public_base_of
template<class T, class U> using is_public_base_of = std::is_convertible<U*, T*>;
// is_protected_base_of
struct ipb_final
{
template<class T, class U> using fn = std::false_type;
};
struct ipb_non_final
{
template<class T, class U> struct fn: U
{
static std::true_type f( T* );
template<class X> static auto g( X x ) -> decltype( f(x) );
static std::false_type g( ... );
using type = decltype( g((U*)0) );
};
};
template<class T, class U> using is_protected_base_of =
typename std::conditional<std::is_final<U>::value || std::is_union<U>::value, ipb_final, ipb_non_final>::type::template fn<T, U>::type;
// is_virtual_base_of
template<class T, class U, class = void> struct can_cast: std::false_type {};
template<class T, class U> struct can_cast<T, U, decltype((void)(U*)(T*)0)>: std::true_type {};
template<class T, class U> using is_virtual_base_of =
std::integral_constant<bool, can_cast<U, T>::value && !can_cast<T, U>::value>;
// compute_base_modifiers
template<class C, class B> constexpr unsigned compute_base_modifiers() noexcept
{
return (is_public_base_of<B, C>::value? mod_public: (is_protected_base_of<B, C>::value? mod_protected: mod_private)) | (is_virtual_base_of<B, C>::value? mod_virtual: 0);
}
#if defined(_MSC_VER)
# pragma warning(pop)
#endif
} // namespace detail
} // namespace describe
} // namespace boost
#endif // #ifndef BOOST_DESCRIBE_DETAIL_COMPUTE_BASE_MODIFIERS_HPP_INCLUDED

View File

@@ -19,11 +19,10 @@
# define BOOST_DESCRIBE_CXX11
#endif
# if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 7
# undef BOOST_DESCRIBE_CXX11
# endif
#if defined(BOOST_DESCRIBE_CXX14) && defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 5 && __GNUC__ <= 7 && defined(__STRICT_ANSI__)
// g++ 5..7 with -std=c++14 doesn't support the variadic extension we need, use -std=gnu++14
# undef BOOST_DESCRIBE_CXX14
#endif
#if defined(BOOST_DESCRIBE_CXX11)
@@ -32,4 +31,34 @@
# define BOOST_DESCRIBE_CONSTEXPR_OR_CONST const
#endif
#if defined(__clang__)
# define BOOST_DESCRIBE_MAYBE_UNUSED __attribute__((unused))
#else
# define BOOST_DESCRIBE_MAYBE_UNUSED
#endif
#if defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L
# define BOOST_DESCRIBE_INLINE_VARIABLE inline
#else
# define BOOST_DESCRIBE_INLINE_VARIABLE
#endif
#define BOOST_DESCRIBE_INLINE_CONSTEXPR BOOST_DESCRIBE_INLINE_VARIABLE BOOST_DESCRIBE_CONSTEXPR_OR_CONST
#if __cplusplus >= 202002L || ( defined(_MSVC_LANG) && _MSVC_LANG >= 202002L )
# define BOOST_DESCRIBE_CXX20
// Clang 13.0 is needed for unevaluated lambdas
# if defined(__clang__) && __clang_major__ < 13
# undef BOOST_DESCRIBE_CXX20
# endif
// Apple Clang 13.1 is Clang 13.0
# if defined(__clang__) && defined(__apple_build_version__) && __clang_major__ == 13 && __clang_minor__ < 1
# undef BOOST_DESCRIBE_CXX20
# endif
#endif
#endif // #ifndef BOOST_DESCRIBE_DETAIL_CONFIG_HPP_INCLUDED

View File

@@ -0,0 +1,30 @@
#ifndef BOOST_DESCRIBE_DETAIL_CX_STREQ_HPP_INCLUDED
#define BOOST_DESCRIBE_DETAIL_CX_STREQ_HPP_INCLUDED
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/detail/config.hpp>
#if defined(BOOST_DESCRIBE_CXX11)
namespace boost
{
namespace describe
{
namespace detail
{
constexpr bool cx_streq( char const * s1, char const * s2 )
{
return s1[0] == s2[0] && ( s1[0] == 0 || cx_streq( s1 + 1, s2 + 1 ) );
}
} // namespace detail
} // namespace describe
} // namespace boost
#endif // defined(BOOST_DESCRIBE_CXX11)
#endif // #ifndef BOOST_DESCRIBE_DETAIL_CX_STREQ_HPP_INCLUDED

View File

@@ -7,6 +7,7 @@
#include <boost/describe/modifiers.hpp>
#include <boost/describe/detail/pp_for_each.hpp>
#include <boost/describe/detail/pp_utilities.hpp>
#include <boost/describe/detail/list.hpp>
#include <type_traits>
@@ -34,39 +35,44 @@ template<class D, unsigned M> struct member_descriptor
static constexpr unsigned modifiers = M | add_static_modifier( D::pointer() ) | add_function_modifier( D::pointer() );
};
#ifndef __cpp_inline_variables
template<class D, unsigned M> constexpr decltype(D::pointer()) member_descriptor<D, M>::pointer;
template<class D, unsigned M> constexpr decltype(D::name()) member_descriptor<D, M>::name;
template<class D, unsigned M> constexpr unsigned member_descriptor<D, M>::modifiers;
#endif
template<unsigned M, class... T> auto member_descriptor_fn_impl( int, T... )
{
return list<member_descriptor<T, M>...>();
}
#define BOOST_DESCRIBE_MEMBER_IMPL(C, m) , []{ struct D { \
static constexpr auto pointer() noexcept { return &C::m; } \
static constexpr auto name() noexcept { return #m; } }; return D(); }()
template<class C, class F> constexpr auto mfn( F C::* p ) { return p; }
template<class C, class F> constexpr auto mfn( F * p ) { return p; }
#define BOOST_DESCRIBE_MEMBER_IMPL(C, m) , []{ struct _boost_desc { \
static constexpr auto pointer() noexcept { return BOOST_DESCRIBE_PP_POINTER(C, m); } \
static constexpr auto name() noexcept { return BOOST_DESCRIBE_PP_NAME(m); } }; return _boost_desc(); }()
#if defined(_MSC_VER) && !defined(__clang__)
#define BOOST_DESCRIBE_PUBLIC_MEMBERS(C, ...) inline auto _public_member_descriptor_fn( C * ) \
#define BOOST_DESCRIBE_PUBLIC_MEMBERS(C, ...) inline auto boost_public_member_descriptor_fn( C** ) \
{ return boost::describe::detail::member_descriptor_fn_impl<boost::describe::mod_public>( 0 BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_MEMBER_IMPL, C, __VA_ARGS__) ); }
#define BOOST_DESCRIBE_PROTECTED_MEMBERS(C, ...) inline auto _protected_member_descriptor_fn( C * ) \
#define BOOST_DESCRIBE_PROTECTED_MEMBERS(C, ...) inline auto boost_protected_member_descriptor_fn( C** ) \
{ return boost::describe::detail::member_descriptor_fn_impl<boost::describe::mod_protected>( 0 BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_MEMBER_IMPL, C, __VA_ARGS__) ); }
#define BOOST_DESCRIBE_PRIVATE_MEMBERS(C, ...) inline auto _private_member_descriptor_fn( C * ) \
#define BOOST_DESCRIBE_PRIVATE_MEMBERS(C, ...) inline auto boost_private_member_descriptor_fn( C** ) \
{ return boost::describe::detail::member_descriptor_fn_impl<boost::describe::mod_private>( 0 BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_MEMBER_IMPL, C, __VA_ARGS__) ); }
#else
#define BOOST_DESCRIBE_PUBLIC_MEMBERS(C, ...) inline auto _public_member_descriptor_fn( C * ) \
#define BOOST_DESCRIBE_PUBLIC_MEMBERS(C, ...) inline auto boost_public_member_descriptor_fn( C** ) \
{ return boost::describe::detail::member_descriptor_fn_impl<boost::describe::mod_public>( 0 BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_MEMBER_IMPL, C, ##__VA_ARGS__) ); }
#define BOOST_DESCRIBE_PROTECTED_MEMBERS(C, ...) inline auto _protected_member_descriptor_fn( C * ) \
#define BOOST_DESCRIBE_PROTECTED_MEMBERS(C, ...) inline auto boost_protected_member_descriptor_fn( C** ) \
{ return boost::describe::detail::member_descriptor_fn_impl<boost::describe::mod_protected>( 0 BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_MEMBER_IMPL, C, ##__VA_ARGS__) ); }
#define BOOST_DESCRIBE_PRIVATE_MEMBERS(C, ...) inline auto _private_member_descriptor_fn( C * ) \
#define BOOST_DESCRIBE_PRIVATE_MEMBERS(C, ...) inline auto boost_private_member_descriptor_fn( C** ) \
{ return boost::describe::detail::member_descriptor_fn_impl<boost::describe::mod_private>( 0 BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_MEMBER_IMPL, C, ##__VA_ARGS__) ); }
#endif

View File

@@ -5,66 +5,90 @@
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#define BOOST_DESCRIBE_PP_EXPAND(x) x
#include <boost/describe/detail/pp_utilities.hpp>
#define BOOST_DESCRIBE_PP_FOR_EACH_0(F, a)
#define BOOST_DESCRIBE_PP_FOR_EACH_1(F, a, x) F(a, x)
#define BOOST_DESCRIBE_PP_FOR_EACH_2(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_1(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_3(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_2(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_4(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_3(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_5(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_4(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_6(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_5(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_7(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_6(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_8(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_7(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_9(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_8(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_10(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_9(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_11(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_10(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_12(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_11(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_13(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_12(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_14(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_13(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_15(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_14(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_16(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_15(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_17(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_16(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_18(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_17(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_19(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_18(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_20(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_19(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_21(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_20(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_22(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_21(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_23(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_22(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_24(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_23(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_25(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_24(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_26(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_25(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_27(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_26(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_28(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_27(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_29(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_28(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_30(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_29(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_31(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_30(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_32(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_31(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_33(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_32(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_34(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_33(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_35(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_34(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_36(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_35(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_37(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_36(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_38(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_37(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_39(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_38(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_40(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_39(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_41(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_40(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_42(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_41(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_43(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_42(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_44(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_43(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_45(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_44(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_46(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_45(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_47(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_46(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_48(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_47(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_49(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_48(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_50(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_49(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_51(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_50(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_52(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_51(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_1(F, a, x) BOOST_DESCRIBE_PP_CALL(F, a, x)
#define BOOST_DESCRIBE_PP_FOR_EACH_2(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_1(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_3(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_2(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_4(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_3(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_5(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_4(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_6(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_5(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_7(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_6(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_8(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_7(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_9(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_8(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_10(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_9(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_11(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_10(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_12(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_11(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_13(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_12(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_14(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_13(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_15(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_14(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_16(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_15(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_17(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_16(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_18(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_17(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_19(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_18(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_20(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_19(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_21(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_20(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_22(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_21(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_23(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_22(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_24(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_23(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_25(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_24(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_26(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_25(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_27(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_26(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_28(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_27(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_29(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_28(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_30(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_29(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_31(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_30(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_32(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_31(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_33(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_32(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_34(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_33(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_35(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_34(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_36(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_35(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_37(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_36(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_38(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_37(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_39(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_38(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_40(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_39(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_41(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_40(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_42(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_41(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_43(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_42(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_44(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_43(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_45(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_44(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_46(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_45(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_47(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_46(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_48(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_47(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_49(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_48(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_50(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_49(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_51(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_50(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_52(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_51(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_53(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_52(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_54(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_53(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_55(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_54(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_56(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_55(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_57(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_56(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_58(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_57(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_59(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_58(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_60(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_59(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_61(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_60(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_62(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_61(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_63(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_62(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_64(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_63(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_EXTRACT(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, V, ...) V
#define BOOST_DESCRIBE_PP_FE_EXTRACT(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, V, ...) V
#define BOOST_DESCRIBE_PP_FOR_EACH(F, ...) \
BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_EXTRACT(__VA_ARGS__, \
BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_FE_EXTRACT(__VA_ARGS__, \
BOOST_DESCRIBE_PP_FOR_EACH_64, \
BOOST_DESCRIBE_PP_FOR_EACH_63, \
BOOST_DESCRIBE_PP_FOR_EACH_62, \
BOOST_DESCRIBE_PP_FOR_EACH_61, \
BOOST_DESCRIBE_PP_FOR_EACH_60, \
BOOST_DESCRIBE_PP_FOR_EACH_59, \
BOOST_DESCRIBE_PP_FOR_EACH_58, \
BOOST_DESCRIBE_PP_FOR_EACH_57, \
BOOST_DESCRIBE_PP_FOR_EACH_56, \
BOOST_DESCRIBE_PP_FOR_EACH_55, \
BOOST_DESCRIBE_PP_FOR_EACH_54, \
BOOST_DESCRIBE_PP_FOR_EACH_53, \
BOOST_DESCRIBE_PP_FOR_EACH_52, \
BOOST_DESCRIBE_PP_FOR_EACH_51, \
BOOST_DESCRIBE_PP_FOR_EACH_50, \

View File

@@ -0,0 +1,92 @@
#ifndef BOOST_DESCRIBE_DETAIL_PP_UTILITIES_HPP_INCLUDED
#define BOOST_DESCRIBE_DETAIL_PP_UTILITIES_HPP_INCLUDED
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#define BOOST_DESCRIBE_PP_EXPAND(x) x
#define BOOST_DESCRIBE_PP_CAT(x, y) BOOST_DESCRIBE_PP_CAT_I(x, y)
#define BOOST_DESCRIBE_PP_CAT_I(x, ...) x ## __VA_ARGS__
#if defined(_MSC_VER) && !defined(__clang__)
#define BOOST_DESCRIBE_PP_FIRST(x) BOOST_DESCRIBE_PP_FIRST_I((x))
#define BOOST_DESCRIBE_PP_FIRST_I(x) BOOST_DESCRIBE_PP_FIRST_II x
#define BOOST_DESCRIBE_PP_FIRST_II(x, ...) x
#else
#define BOOST_DESCRIBE_PP_FIRST(x) BOOST_DESCRIBE_PP_FIRST_I(x)
#define BOOST_DESCRIBE_PP_FIRST_I(x, ...) x
#endif
#define BOOST_DESCRIBE_PP_IS_PAREN_I(x) BOOST_DESCRIBE_PP_CAT(BOOST_DESCRIBE_PP_IS_PAREN_I_, BOOST_DESCRIBE_PP_IS_PAREN_II x)
#define BOOST_DESCRIBE_PP_IS_PAREN_II(...) 0
#define BOOST_DESCRIBE_PP_IS_PAREN_I_0 1,
#define BOOST_DESCRIBE_PP_IS_PAREN_I_BOOST_DESCRIBE_PP_IS_PAREN_II 0,
#define BOOST_DESCRIBE_PP_IS_PAREN(x) BOOST_DESCRIBE_PP_FIRST(BOOST_DESCRIBE_PP_IS_PAREN_I(x))
#define BOOST_DESCRIBE_PP_EMPTY
#define BOOST_DESCRIBE_PP_IS_EMPTY(x) BOOST_DESCRIBE_PP_IS_EMPTY_I(BOOST_DESCRIBE_PP_IS_PAREN(x), BOOST_DESCRIBE_PP_IS_PAREN(x BOOST_DESCRIBE_PP_EMPTY ()))
#define BOOST_DESCRIBE_PP_IS_EMPTY_I(x, y) BOOST_DESCRIBE_PP_IS_EMPTY_II(x, y)
#define BOOST_DESCRIBE_PP_IS_EMPTY_II(x, y) BOOST_DESCRIBE_PP_IS_EMPTY_III(x, y)
#define BOOST_DESCRIBE_PP_IS_EMPTY_III(x, y) BOOST_DESCRIBE_PP_IS_EMPTY_III_ ## x ## y
#define BOOST_DESCRIBE_PP_IS_EMPTY_III_00 0
#define BOOST_DESCRIBE_PP_IS_EMPTY_III_01 1
#define BOOST_DESCRIBE_PP_IS_EMPTY_III_10 0
#define BOOST_DESCRIBE_PP_IS_EMPTY_III_11 0
#define BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_CAT(BOOST_DESCRIBE_PP_CALL_I_, BOOST_DESCRIBE_PP_IS_EMPTY(x))(F, a, x)
#define BOOST_DESCRIBE_PP_CALL_I_0(F, a, x) F(a, x)
#define BOOST_DESCRIBE_PP_CALL_I_1(F, a, x)
#define BOOST_DESCRIBE_PP_PARSE(x) BOOST_DESCRIBE_PP_CAT(BOOST_DESCRIBE_PP_PARSE_I_, BOOST_DESCRIBE_PP_PARSE_II x)
#define BOOST_DESCRIBE_PP_PARSE_II(...) 0, (__VA_ARGS__),
#define BOOST_DESCRIBE_PP_PARSE_I_BOOST_DESCRIBE_PP_PARSE_II 0, ~,
#define BOOST_DESCRIBE_PP_PARSE_I_0 1
#if defined(_MSC_VER) && !defined(__clang__)
#define BOOST_DESCRIBE_PP_NAME(x) BOOST_DESCRIBE_PP_NAME_I(BOOST_DESCRIBE_PP_PARSE(x))
#define BOOST_DESCRIBE_PP_NAME_I(x) BOOST_DESCRIBE_PP_NAME_II((x))
#define BOOST_DESCRIBE_PP_NAME_II(x) BOOST_DESCRIBE_PP_NAME_III x
#define BOOST_DESCRIBE_PP_NAME_III(x, y, z) #z
#else
#define BOOST_DESCRIBE_PP_NAME(x) BOOST_DESCRIBE_PP_NAME_I(BOOST_DESCRIBE_PP_PARSE(x))
#define BOOST_DESCRIBE_PP_NAME_I(x) BOOST_DESCRIBE_PP_NAME_II(x)
#define BOOST_DESCRIBE_PP_NAME_II(x, y, z) #z
#endif
// template<class C, class F> constexpr auto mfn( F C::* p ) { return p; }
// template<class C, class F> constexpr auto mfn( F * p ) { return p; }
#define BOOST_DESCRIBE_PP_POINTER(C, x) BOOST_DESCRIBE_PP_POINTER_I(C, BOOST_DESCRIBE_PP_PARSE(x))
#define BOOST_DESCRIBE_PP_EXPAND_V(...) __VA_ARGS__
#if defined(_MSC_VER) && !defined(__clang__)
#define BOOST_DESCRIBE_PP_POINTER_I(C, x) BOOST_DESCRIBE_PP_POINTER_II((C, x))
#define BOOST_DESCRIBE_PP_POINTER_II(x) BOOST_DESCRIBE_PP_POINTER_III x
#define BOOST_DESCRIBE_PP_POINTER_III(C, x, y, z) BOOST_DESCRIBE_PP_POINTER_III_##x(C, y, z)
#define BOOST_DESCRIBE_PP_POINTER_III_0(C, y, z) &C::z
#define BOOST_DESCRIBE_PP_POINTER_III_1(C, y, z) ::boost::describe::detail::mfn<C, BOOST_DESCRIBE_PP_EXPAND_V y>(&C::z)
#else
#define BOOST_DESCRIBE_PP_POINTER_I(C, x) BOOST_DESCRIBE_PP_POINTER_II(C, x)
#define BOOST_DESCRIBE_PP_POINTER_II(C, x, y, z) BOOST_DESCRIBE_PP_POINTER_III_##x(C, y, z)
#define BOOST_DESCRIBE_PP_POINTER_III_0(C, y, z) &C::z
#define BOOST_DESCRIBE_PP_POINTER_III_1(C, y, z) ::boost::describe::detail::mfn<C, BOOST_DESCRIBE_PP_EXPAND_V y>(&C::z)
#endif
#endif // #ifndef BOOST_DESCRIBE_DETAIL_PP_UTILITIES_HPP_INCLUDED

View File

@@ -0,0 +1,32 @@
#ifndef BOOST_DESCRIBE_DETAIL_VOID_T_HPP_INCLUDED
#define BOOST_DESCRIBE_DETAIL_VOID_T_HPP_INCLUDED
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/detail/config.hpp>
#if defined(BOOST_DESCRIBE_CXX11)
namespace boost
{
namespace describe
{
namespace detail
{
template<class...> struct make_void
{
using type = void;
};
template<class... T> using void_t = typename make_void<T...>::type;
} // namespace detail
} // namespace describe
} // namespace boost
#endif // defined(BOOST_DESCRIBE_CXX11)
#endif // #ifndef BOOST_DESCRIBE_DETAIL_VOID_T_HPP_INCLUDED

View File

@@ -5,17 +5,19 @@
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/detail/pp_for_each.hpp>
#include <boost/describe/detail/list.hpp>
#include <boost/describe/detail/config.hpp>
#if !defined(BOOST_DESCRIBE_CXX14)
#define BOOST_DESCRIBE_ENUM(E, ...)
#define BOOST_DESCRIBE_ENUM_CLASS(E, ...)
#define BOOST_DESCRIBE_NESTED_ENUM(E, ...)
#else
#include <boost/describe/detail/pp_for_each.hpp>
#include <boost/describe/detail/list.hpp>
#include <type_traits>
namespace boost
{
namespace describe
@@ -30,40 +32,101 @@ template<class D> struct enum_descriptor
static constexpr decltype(D::name()) name = D::name();
};
#ifndef __cpp_inline_variables
// GCC requires these definitions
template<class D> constexpr decltype(D::value()) enum_descriptor<D>::value;
template<class D> constexpr decltype(D::name()) enum_descriptor<D>::name;
#endif
template<class... T> auto enum_descriptor_fn_impl( int, T... )
{
return list<enum_descriptor<T>...>();
}
#define BOOST_DESCRIBE_ENUM_IMPL(E, e) , []{ struct D { \
static constexpr auto value() noexcept { return e; } \
static constexpr auto name() noexcept { return #e; } }; return D(); }()
#if defined(BOOST_DESCRIBE_CXX20)
#define BOOST_DESCRIBE_ENUM_CLASS_IMPL(E, e) , []{ struct D { \
template<auto V, auto N> struct enum_desc
{
static constexpr auto value() noexcept { return V; }
static constexpr auto name() noexcept { return N(); }
};
#define BOOST_DESCRIBE_ENUM_BEGIN(E) \
inline decltype( boost::describe::detail::enum_descriptor_fn_impl( 0
#define BOOST_DESCRIBE_ENUM_ENTRY(E, e) , boost::describe::detail::enum_desc<E::e, []{ return #e; }>{}
#define BOOST_DESCRIBE_ENUM_END(E) ) ) boost_enum_descriptor_fn( E** ) { return {}; }
#else
#define BOOST_DESCRIBE_ENUM_BEGIN(E) \
inline auto boost_enum_descriptor_fn( E** ) \
{ return boost::describe::detail::enum_descriptor_fn_impl( 0
#define BOOST_DESCRIBE_ENUM_ENTRY(E, e) , []{ struct _boost_desc { \
static constexpr auto value() noexcept { return E::e; } \
static constexpr auto name() noexcept { return #e; } }; return D(); }()
static constexpr auto name() noexcept { return #e; } }; return _boost_desc(); }()
#define BOOST_DESCRIBE_ENUM_END(E) ); }
#endif
} // namespace detail
#define BOOST_DESCRIBE_ENUM(E, ...) inline auto _enum_descriptor_fn( E* ) \
{ return boost::describe::detail::enum_descriptor_fn_impl( 0 BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_ENUM_IMPL, E, __VA_ARGS__) ); }
#if defined(_MSC_VER) && !defined(__clang__)
#define BOOST_DESCRIBE_ENUM_CLASS(E, ...) inline auto _enum_descriptor_fn( E* ) \
{ return boost::describe::detail::enum_descriptor_fn_impl( 0 BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_ENUM_CLASS_IMPL, E, __VA_ARGS__) ); }
#define BOOST_DESCRIBE_ENUM(E, ...) \
namespace should_use_BOOST_DESCRIBE_NESTED_ENUM {} \
static_assert(std::is_enum<E>::value, "BOOST_DESCRIBE_ENUM should only be used with enums"); \
BOOST_DESCRIBE_ENUM_BEGIN(E) \
BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_ENUM_ENTRY, E, __VA_ARGS__) \
BOOST_DESCRIBE_ENUM_END(E)
#define BOOST_DESCRIBE_NESTED_ENUM(E, ...) \
static_assert(std::is_enum<E>::value, "BOOST_DESCRIBE_NESTED_ENUM should only be used with enums"); \
friend BOOST_DESCRIBE_ENUM_BEGIN(E) \
BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_ENUM_ENTRY, E, __VA_ARGS__) \
BOOST_DESCRIBE_ENUM_END(E)
#else
#define BOOST_DESCRIBE_ENUM(E, ...) \
namespace should_use_BOOST_DESCRIBE_NESTED_ENUM {} \
static_assert(std::is_enum<E>::value, "BOOST_DESCRIBE_ENUM should only be used with enums"); \
BOOST_DESCRIBE_MAYBE_UNUSED BOOST_DESCRIBE_ENUM_BEGIN(E) \
BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_ENUM_ENTRY, E, ##__VA_ARGS__) \
BOOST_DESCRIBE_ENUM_END(E)
#define BOOST_DESCRIBE_NESTED_ENUM(E, ...) \
static_assert(std::is_enum<E>::value, "BOOST_DESCRIBE_NESTED_ENUM should only be used with enums"); \
BOOST_DESCRIBE_MAYBE_UNUSED friend BOOST_DESCRIBE_ENUM_BEGIN(E) \
BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_ENUM_ENTRY, E, ##__VA_ARGS__) \
BOOST_DESCRIBE_ENUM_END(E)
#endif
} // namespace describe
} // namespace boost
#endif // defined(BOOST_DESCRIBE_CXX14)
#if defined(_MSC_VER) && !defined(__clang__)
#define BOOST_DEFINE_ENUM(E, ...) enum E { __VA_ARGS__ }; BOOST_DESCRIBE_ENUM(E, __VA_ARGS__)
#define BOOST_DEFINE_ENUM_CLASS(E, ...) enum class E { __VA_ARGS__ }; BOOST_DESCRIBE_ENUM_CLASS(E, __VA_ARGS__)
#define BOOST_DEFINE_ENUM_CLASS(E, ...) enum class E { __VA_ARGS__ }; BOOST_DESCRIBE_ENUM(E, __VA_ARGS__)
#define BOOST_DEFINE_FIXED_ENUM(E, Base, ...) enum E: Base { __VA_ARGS__ }; BOOST_DESCRIBE_ENUM(E, __VA_ARGS__)
#define BOOST_DEFINE_FIXED_ENUM_CLASS(E, Base, ...) enum class E: Base { __VA_ARGS__ }; BOOST_DESCRIBE_ENUM_CLASS(E, __VA_ARGS__)
#define BOOST_DEFINE_FIXED_ENUM_CLASS(E, Base, ...) enum class E: Base { __VA_ARGS__ }; BOOST_DESCRIBE_ENUM(E, __VA_ARGS__)
#else
#define BOOST_DEFINE_ENUM(E, ...) enum E { __VA_ARGS__ }; BOOST_DESCRIBE_ENUM(E, ##__VA_ARGS__)
#define BOOST_DEFINE_ENUM_CLASS(E, ...) enum class E { __VA_ARGS__ }; BOOST_DESCRIBE_ENUM(E, ##__VA_ARGS__)
#define BOOST_DEFINE_FIXED_ENUM(E, Base, ...) enum E: Base { __VA_ARGS__ }; BOOST_DESCRIBE_ENUM(E, ##__VA_ARGS__)
#define BOOST_DEFINE_FIXED_ENUM_CLASS(E, Base, ...) enum class E: Base { __VA_ARGS__ }; BOOST_DESCRIBE_ENUM(E, ##__VA_ARGS__)
#endif
#endif // #ifndef BOOST_DESCRIBE_ENUM_HPP_INCLUDED

View File

@@ -0,0 +1,77 @@
#ifndef BOOST_DESCRIBE_ENUM_FROM_STRING_HPP_INCLUDED
#define BOOST_DESCRIBE_ENUM_FROM_STRING_HPP_INCLUDED
// Copyright 2020, 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/detail/config.hpp>
#if defined(BOOST_DESCRIBE_CXX14)
#include <boost/describe/enumerators.hpp>
#include <boost/mp11/algorithm.hpp>
#include <cstring>
#include <type_traits>
#if defined(_MSC_VER) && _MSC_VER == 1900
# pragma warning(push)
# pragma warning(disable: 4100) // unreferenced formal parameter
#endif
namespace boost
{
namespace describe
{
template<class E, class De = describe_enumerators<E>>
bool enum_from_string( char const* name, E& e ) noexcept
{
bool found = false;
mp11::mp_for_each<De>([&](auto D){
if( !found && std::strcmp( D.name, name ) == 0 )
{
found = true;
e = D.value;
}
});
return found;
}
template<class S, class E, class De = describe_enumerators<E>,
class En = std::enable_if_t<
std::is_same<typename S::value_type, char>::value &&
std::is_same<typename S::traits_type::char_type, char>::value
>
>
bool enum_from_string( S const& name, E& e ) noexcept
{
bool found = false;
mp11::mp_for_each<De>([&](auto D){
if( !found && name == D.name )
{
found = true;
e = D.value;
}
});
return found;
}
} // namespace describe
} // namespace boost
#if defined(_MSC_VER) && _MSC_VER == 1900
# pragma warning(pop)
#endif
#endif // defined(BOOST_DESCRIBE_CXX14)
#endif // #ifndef BOOST_DESCRIBE_ENUM_FROM_STRING_HPP_INCLUDED

View File

@@ -0,0 +1,66 @@
#ifndef BOOST_DESCRIBE_ENUM_TO_STRING_HPP_INCLUDED
#define BOOST_DESCRIBE_ENUM_TO_STRING_HPP_INCLUDED
// Copyright 2020, 2021, 2025 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/detail/config.hpp>
#if defined(BOOST_DESCRIBE_CXX14)
#include <boost/describe/enumerators.hpp>
#include <boost/mp11/algorithm.hpp>
#if defined(_MSC_VER) && _MSC_VER == 1900
# pragma warning(push)
# pragma warning(disable: 4100) // unreferenced formal parameter
#endif
namespace boost
{
namespace describe
{
namespace detail
{
// [&](auto D){ if( e == D.value ) r = D.name; }
// except constexpr under C++14
template<class E> struct ets_lambda
{
E e;
char const** pr;
template<class D> constexpr void operator()( D d ) const noexcept
{
if( e == d.value ) *pr = d.name;
}
};
} // namespace detail
template<class E, class De = describe_enumerators<E>>
#if !( defined(_MSC_VER) && _MSC_VER == 1900 )
constexpr
#endif
char const* enum_to_string( E e, char const* def ) noexcept
{
char const* r = def;
mp11::mp_for_each<De>( detail::ets_lambda<E>{ e, &r } );
return r;
}
} // namespace describe
} // namespace boost
#if defined(_MSC_VER) && _MSC_VER == 1900
# pragma warning(pop)
#endif
#endif // defined(BOOST_DESCRIBE_CXX14)
#endif // #ifndef BOOST_DESCRIBE_ENUM_TO_STRING_HPP_INCLUDED

View File

@@ -1,20 +1,42 @@
#ifndef BOOST_DESCRIBE_ENUMERATORS_HPP_INCLUDED
#define BOOST_DESCRIBE_ENUMERATORS_HPP_INCLUDED
// Copyright 2020 Peter Dimov
// Copyright 2020, 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/detail/void_t.hpp>
#include <boost/describe/detail/config.hpp>
#if defined(BOOST_DESCRIBE_CXX11)
#include <type_traits>
namespace boost
{
namespace describe
{
template<class E> using describe_enumerators = decltype( _enum_descriptor_fn( static_cast<E*>(0) ) );
// describe_enumerators<E>
template<class E> using describe_enumerators = decltype( boost_enum_descriptor_fn( static_cast<E**>(0) ) );
// has_describe_enumerators<E>
namespace detail
{
template<class E, class En = void> struct has_describe_enumerators: std::false_type
{
};
template<class E> struct has_describe_enumerators<E, void_t<describe_enumerators<E>>>: std::true_type
{
};
} // namespace detail
template<class E> using has_describe_enumerators = detail::has_describe_enumerators<E>;
} // namespace describe
} // namespace boost

View File

@@ -7,6 +7,9 @@
#include <boost/describe/modifiers.hpp>
#include <boost/describe/bases.hpp>
#include <boost/describe/detail/void_t.hpp>
#include <boost/describe/detail/cx_streq.hpp>
#include <boost/describe/detail/config.hpp>
#if defined(BOOST_DESCRIBE_CXX11)
@@ -15,6 +18,7 @@
#include <boost/mp11/integral.hpp>
#include <boost/mp11/list.hpp>
#include <boost/mp11/bind.hpp>
#include <type_traits>
namespace boost
{
@@ -25,9 +29,9 @@ namespace detail
// _describe_members<T>
template<class T> using _describe_public_members = decltype( _public_member_descriptor_fn( static_cast<T*>(0) ) );
template<class T> using _describe_protected_members = decltype( _protected_member_descriptor_fn( static_cast<T*>(0) ) );
template<class T> using _describe_private_members = decltype( _private_member_descriptor_fn( static_cast<T*>(0) ) );
template<class T> using _describe_public_members = decltype( boost_public_member_descriptor_fn( static_cast<T**>(0) ) );
template<class T> using _describe_protected_members = decltype( boost_protected_member_descriptor_fn( static_cast<T**>(0) ) );
template<class T> using _describe_private_members = decltype( boost_private_member_descriptor_fn( static_cast<T**>(0) ) );
template<class T> using _describe_members = mp11::mp_append<_describe_public_members<T>, _describe_protected_members<T>, _describe_private_members<T>>;
@@ -57,11 +61,6 @@ template<template<class...> class L, class T, class V> struct describe_inherited
using type = L<>;
};
constexpr bool cx_streq( char const * s1, char const * s2 )
{
return s1[0] == s2[0] && ( s1[0] == 0 || cx_streq( s1 + 1, s2 + 1 ) );
}
template<class D1, class D2> using name_matches = mp11::mp_bool< cx_streq( D1::name, D2::name ) >;
template<class D, class L> using name_is_hidden = mp11::mp_any_of_q<L, mp11::mp_bind_front<name_matches, D>>;
@@ -87,9 +86,11 @@ template<class T, unsigned Bm> struct update_modifiers
};
};
#ifndef __cpp_inline_variables
template<class T, unsigned Bm> template<class D> constexpr decltype(D::pointer) update_modifiers<T, Bm>::fn<D>::pointer;
template<class T, unsigned Bm> template<class D> constexpr decltype(D::name) update_modifiers<T, Bm>::fn<D>::name;
template<class T, unsigned Bm> template<class D> constexpr unsigned update_modifiers<T, Bm>::fn<D>::modifiers;
#endif
template<class D> struct gather_virtual_bases_impl;
template<class D> using gather_virtual_bases = typename gather_virtual_bases_impl<D>::type;
@@ -129,17 +130,29 @@ template<class T, unsigned M> using describe_members = mp11::mp_eval_if_c<(M & m
template<unsigned M> struct member_filter
{
template<class T> using fn = mp11::mp_bool<
( M & mod_any_access & T::modifiers ) != 0 &&
( M & mod_static ) == ( T::modifiers & mod_static ) &&
( M & mod_function ) == ( T::modifiers & mod_function ) &&
( M & mod_hidden ) >= ( T::modifiers & mod_hidden )
(M & mod_any_access & T::modifiers) != 0 &&
( (M & mod_any_member) != 0 || (M & mod_static) == (T::modifiers & mod_static) ) &&
( (M & mod_any_member) != 0 || (M & mod_function) == (T::modifiers & mod_function) ) &&
(M & mod_hidden) >= (T::modifiers & mod_hidden)
>;
};
// has_describe_members
template<class T, class En = void> struct has_describe_members: std::false_type
{
};
template<class T> struct has_describe_members<T, void_t<_describe_members<T>>>: std::true_type
{
};
} // namespace detail
template<class T, unsigned M> using describe_members = mp11::mp_copy_if_q<detail::describe_members<T, M>, detail::member_filter<M>>;
template<class T> using has_describe_members = detail::has_describe_members<T>;
} // namespace describe
} // namespace boost

View File

@@ -0,0 +1,30 @@
#ifndef BOOST_DESCRIBE_MODIFIER_DESCRIPTION_HPP_INCLUDED
#define BOOST_DESCRIBE_MODIFIER_DESCRIPTION_HPP_INCLUDED
// Copyright 2020, 2022 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/modifiers.hpp>
#include <boost/describe/enum.hpp>
namespace boost
{
namespace describe
{
BOOST_DESCRIBE_ENUM(modifiers,
mod_public,
mod_protected,
mod_private,
mod_virtual,
mod_static,
mod_function,
mod_any_member,
mod_inherited,
mod_hidden)
} // namespace describe
} // namespace boost
#endif // #ifndef BOOST_DESCRIBE_MODIFIER_DESCRIPTION_HPP_INCLUDED

View File

@@ -5,7 +5,7 @@
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/enum.hpp>
#include <boost/describe/detail/config.hpp>
namespace boost
{
@@ -20,21 +20,12 @@ enum modifiers
mod_virtual = 8,
mod_static = 16,
mod_function = 32,
mod_inherited = 64,
mod_hidden = 128,
mod_any_member = 64,
mod_inherited = 128,
mod_hidden = 256
};
BOOST_DESCRIBE_ENUM(modifiers,
mod_public,
mod_protected,
mod_private,
mod_virtual,
mod_static,
mod_function,
mod_inherited,
mod_hidden);
BOOST_DESCRIBE_CONSTEXPR_OR_CONST modifiers mod_any_access = static_cast<modifiers>( mod_public | mod_protected | mod_private );
BOOST_DESCRIBE_INLINE_CONSTEXPR modifiers mod_any_access = static_cast<modifiers>( mod_public | mod_protected | mod_private );
} // namespace describe
} // namespace boost

View File

@@ -0,0 +1,179 @@
#ifndef BOOST_DESCRIBE_OPERATORS_HPP_INCLUDED
#define BOOST_DESCRIBE_OPERATORS_HPP_INCLUDED
// Copyright 2020, 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/detail/config.hpp>
#if defined(BOOST_DESCRIBE_CXX14)
#include <boost/describe/bases.hpp>
#include <boost/describe/members.hpp>
#include <boost/describe/modifiers.hpp>
#include <boost/mp11/algorithm.hpp>
#include <type_traits>
#include <iosfwd>
#if defined(_MSC_VER) && _MSC_VER == 1900
# pragma warning(push)
# pragma warning(disable: 4100) // unreferenced formal parameter
#endif
namespace boost
{
namespace describe
{
namespace detail
{
template<class T,
class Bd = describe::describe_bases<T, mod_any_access>,
class Md = describe::describe_members<T, mod_any_access>>
bool eq( T const& t1, T const& t2 )
{
bool r = true;
mp11::mp_for_each<Bd>([&](auto D){
using B = typename decltype(D)::type;
r = r && (B const&)t1 == (B const&)t2;
});
mp11::mp_for_each<Md>([&](auto D){
r = r && t1.*D.pointer == t2.*D.pointer;
});
return r;
}
template<class T,
class Bd = describe::describe_bases<T, mod_any_access>,
class Md = describe::describe_members<T, mod_any_access>>
bool lt( T const& t1, T const& t2 )
{
int r = 0;
mp11::mp_for_each<Bd>([&](auto D){
using B = typename decltype(D)::type;
if( r == 0 && (B const&)t1 < (B const&)t2 ) r = -1;
if( r == 0 && (B const&)t2 < (B const&)t1 ) r = +1;
});
mp11::mp_for_each<Md>([&](auto D){
if( r == 0 && t1.*D.pointer < t2.*D.pointer ) r = -1;
if( r == 0 && t2.*D.pointer < t1.*D.pointer ) r = +1;
});
return r < 0;
}
template<class Os, class T,
class Bd = describe::describe_bases<T, mod_any_access>,
class Md = describe::describe_members<T, mod_any_access>>
void print( Os& os, T const& t )
{
os << "{";
bool first = true;
mp11::mp_for_each<Bd>([&](auto D){
if( !first ) { os << ", "; }
first = false;
using B = typename decltype(D)::type;
os << (B const&)t;
});
mp11::mp_for_each<Md>([&](auto D){
if( !first ) { os << ", "; }
first = false;
os << "." << D.name << " = " << t.*D.pointer;
});
os << "}";
}
} // namespace detail
namespace operators
{
template<class T> std::enable_if_t<
has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
operator==( T const& t1, T const& t2 )
{
return detail::eq( t1, t2 );
}
template<class T> std::enable_if_t<
has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
operator!=( T const& t1, T const& t2 )
{
return !detail::eq( t1, t2 );
}
template<class T> std::enable_if_t<
has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
operator<( T const& t1, T const& t2 )
{
return detail::lt( t1, t2 );
}
template<class T> std::enable_if_t<
has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
operator>=( T const& t1, T const& t2 )
{
return !detail::lt( t1, t2 );
}
template<class T> std::enable_if_t<
has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
operator>( T const& t1, T const& t2 )
{
return detail::lt( t2, t1 );
}
template<class T> std::enable_if_t<
has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
operator<=( T const& t1, T const& t2 )
{
return !detail::lt( t2, t1 );
}
template<class T, class Ch, class Tr> std::enable_if_t<
has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value,
std::basic_ostream<Ch, Tr>&>
operator<<( std::basic_ostream<Ch, Tr>& os, T const& t )
{
os.width( 0 );
detail::print( os, t );
return os;
}
} // namespace operators
} // namespace describe
} // namespace boost
#if defined(_MSC_VER) && _MSC_VER == 1900
# pragma warning(pop)
#endif
#endif // defined(BOOST_DESCRIBE_CXX14)
#endif // #ifndef BOOST_DESCRIBE_OPERATORS_HPP_INCLUDED

View File

@@ -9,6 +9,7 @@
],
"description": "A C++14 reflection library.",
"category": [
"Emulation",
"Metaprogramming"
]
}

11
test/CMakeLists.txt Normal file
View File

@@ -0,0 +1,11 @@
# Copyright 2018, 2021 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# https://www.boost.org/LICENSE_1_0.txt
include(BoostTestJamfile OPTIONAL RESULT_VARIABLE HAVE_BOOST_TEST)
if(HAVE_BOOST_TEST)
boost_test_jamfile(FILE Jamfile LINK_LIBRARIES Boost::describe Boost::core)
endif()

View File

@@ -4,35 +4,100 @@
import testing ;
local WERROR = <toolset>msvc:<warnings-as-errors>on <toolset>clang:<warnings-as-errors>on <toolset>gcc:<warnings-as-errors>on ;
project : requirements
<library>/boost/describe//boost_describe
<library>/boost/container_hash//boost_container_hash
<library>/boost/core//boost_core
<library>/boost/variant2//boost_variant2
<warnings>extra
<toolset>msvc:<warnings-as-errors>on
<toolset>clang:<warnings-as-errors>on
<toolset>gcc:<warnings-as-errors>on
<toolset>msvc-14.0:<cxxflags>"-wd4100"
$(WERROR)
<toolset>clang:<cxxflags>"-Wno-unused-private-field" ;
run quick.cpp ;
run pp_for_each_test.cpp ;
run pp_is_paren_test.cpp ;
run pp_is_empty_test.cpp ;
run pp_call_test.cpp ;
run pp_parse_test.cpp ;
run pp_name_test.cpp ;
run pp_pointer_test.cpp ;
run enumerators_test.cpp ;
run empty_enum_test.cpp ;
run trailing_comma_test.cpp ;
run nested_enum_test.cpp ;
run compute_base_modifiers.cpp ;
run bases_test.cpp ;
run members_test.cpp ;
run members_test2.cpp ;
run members_test3.cpp ;
run members_test4.cpp ;
run members_test5.cpp ;
run members_test6.cpp ;
run members_test7.cpp : : : <toolset>msvc-14.0:<build>no ;
run members_test7.cpp
: : : <toolset>msvc-14.0:<build>no ;
run members_test8.cpp ;
run overloaded_test.cpp ;
run overloaded_test2.cpp ;
compile test_d_type.cpp ;
compile-fail enum_struct_fail.cpp ;
compile-fail struct_enum_fail.cpp ;
compile-fail enum_nested_fail.cpp ;
compile-fail nested_enum_fail.cpp ;
run class_template_test.cpp ;
run has_enumerators_test.cpp ;
run has_bases_test.cpp ;
run has_members_test.cpp ;
run enum_to_string_test.cpp ;
run enum_from_string_test.cpp ;
run operator_eq_test.cpp ;
run operator_lt_test.cpp ;
run descriptor_by_name_test.cpp ;
run descriptor_by_pointer_test.cpp ;
compile unnamed_namespace_test.cpp ;
compile unnamed_namespace_test2.cpp ;
run union_test.cpp ;
run union_test2.cpp ;
run pedantic_enumerators_test.cpp
: : : <warnings>pedantic ;
run pedantic_bases_test.cpp
: : : <warnings>pedantic ;
run pedantic_members_test.cpp
: : : <warnings>pedantic ;
run enum_from_string_test2.cpp ;
compile nested_enum_test2.cpp ;
compile enum_to_string_test_cx.cpp ;
# examples
obj describe_cxx14 : describe_cxx14.cpp ;
explicit describe_cxx14 ;
local CXX14 = [ check-target-builds describe_cxx14 describe_cxx14 : : <build>no ] ;
local CXX14 = [ check-target-builds describe_cxx14 describe_cxx14 : : <build>no ] "<toolset>msvc-14.0:<cxxflags>-wd4100" ;
local JSON = <library>/boost//json/<warnings>off "<toolset>msvc-14.0:<build>no" ;
local SERIALIZATION = <library>/boost//serialization/<warnings>off "-<toolset>clang:<warnings-as-errors>on" ;
local JSON = <library>/boost/json//boost_json/<warnings>off "<toolset>msvc-14.2:<cxxflags>-wd5104" "<toolset>msvc-14.0:<cxxflags>-wd4996" <undefined-sanitizer>norecover:<link>static ;
local SERIALIZATION = <library>/boost/serialization//boost_serialization/<warnings>off -$(WERROR) <undefined-sanitizer>norecover:<link>static ;
run ../example/printing_enums_ct.cpp : : : $(CXX14) ;
run ../example/printing_enums_rt.cpp : : : $(CXX14) ;
@@ -42,4 +107,10 @@ run ../example/print_function.cpp : : : $(CXX14) ;
run ../example/to_json.cpp : : : $(CXX14) $(JSON) ;
run ../example/from_json.cpp : : : $(CXX14) $(JSON) ;
run ../example/serialization.cpp : : : $(CXX14) $(SERIALIZATION) ;
run ../example/json_rpc.cpp : : : $(CXX14) $(JSON) ;
run ../example/json_rpc.cpp : : : $(CXX14) $(JSON) <library>/boost/utility//boost_utility
"<toolset>gcc-14,<cxxstd>14:<build>no" ; # mysterious segmentation fault
run ../example/hash_value.cpp : : : $(CXX14) ;
run ../example/equality.cpp : : : $(CXX14) ;
link ../example/console.cpp : $(CXX14) $(JSON) <library>/boost/utility//boost_utility ;
run ../example/struct_to_tuple.cpp : : : $(CXX14) ;
run ../example/pm_to_string.cpp : : : $(CXX14) ;

View File

@@ -7,6 +7,11 @@
#include <boost/core/lightweight_test.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#if defined(_MSC_VER) && _MSC_VER < 1900
# pragma warning(disable: 4510) // default constructor could not be generated
# pragma warning(disable: 4610) // struct can never be instantiated
#endif
struct X
{
};
@@ -25,15 +30,26 @@ struct X3
{
};
struct X4
struct V1
{
V1(int);
};
struct V2
{
V2(int);
};
struct V3
{
V3(int);
};
struct Y: public X1, protected X2, private X3, public virtual V1, protected virtual V2, private virtual V3
{
};
struct Y: public X1, private X2, public virtual X3, private virtual X4
{
};
BOOST_DESCRIBE_STRUCT(Y, (X1, X2, X3, X4), ())
BOOST_DESCRIBE_STRUCT(Y, (X1, X2, X3, V1, V2, V3), ())
#if !defined(BOOST_DESCRIBE_CXX14)
@@ -46,6 +62,14 @@ int main() {}
#include <boost/mp11.hpp>
template<typename ...Bases>
struct ZT: Bases...
{
BOOST_DESCRIBE_CLASS(ZT, (Bases...), (), (), ());
};
using Z = ZT<X1, X2, X3>;
int main()
{
using namespace boost::describe;
@@ -57,22 +81,46 @@ int main()
BOOST_TEST_EQ( mp_size<L>::value, 0 );
}
{
using L = describe_bases<X, mod_public>;
BOOST_TEST_EQ( mp_size<L>::value, 0 );
}
{
using L = describe_bases<X, mod_protected>;
BOOST_TEST_EQ( mp_size<L>::value, 0 );
}
{
using L = describe_bases<X, mod_private>;
BOOST_TEST_EQ( mp_size<L>::value, 0 );
}
{
using L = describe_bases<Y, mod_any_access>;
BOOST_TEST_EQ( mp_size<L>::value, 4 );
BOOST_TEST_EQ( mp_size<L>::value, 6 );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 0>::type, X1 );
BOOST_TEST_EQ( (mp_at_c<L, 0>::modifiers), mod_public );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 1>::type, X2 );
BOOST_TEST_EQ( (mp_at_c<L, 1>::modifiers), mod_private );
BOOST_TEST_EQ( (mp_at_c<L, 1>::modifiers), mod_protected );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 2>::type, X3 );
BOOST_TEST_EQ( (mp_at_c<L, 2>::modifiers), mod_public | mod_virtual );
BOOST_TEST_EQ( (mp_at_c<L, 2>::modifiers), mod_private );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 3>::type, X4 );
BOOST_TEST_EQ( (mp_at_c<L, 3>::modifiers), mod_private | mod_virtual );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 3>::type, V1 );
BOOST_TEST_EQ( (mp_at_c<L, 3>::modifiers), mod_public | mod_virtual );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 4>::type, V2 );
BOOST_TEST_EQ( (mp_at_c<L, 4>::modifiers), mod_protected | mod_virtual );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 5>::type, V3 );
BOOST_TEST_EQ( (mp_at_c<L, 5>::modifiers), mod_private | mod_virtual );
}
{
@@ -83,26 +131,47 @@ int main()
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 0>::type, X1 );
BOOST_TEST_EQ( (mp_at_c<L, 0>::modifiers), mod_public );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 1>::type, X3 );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 1>::type, V1 );
BOOST_TEST_EQ( (mp_at_c<L, 1>::modifiers), mod_public | mod_virtual );
}
{
using L = describe_bases<Y, mod_protected>;
BOOST_TEST_EQ( mp_size<L>::value, 2 );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 0>::type, X2 );
BOOST_TEST_EQ( (mp_at_c<L, 0>::modifiers), mod_protected );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 1>::type, V2 );
BOOST_TEST_EQ( (mp_at_c<L, 1>::modifiers), mod_protected | mod_virtual );
}
{
using L = describe_bases<Y, mod_private>;
BOOST_TEST_EQ( mp_size<L>::value, 2 );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 0>::type, X2 );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 0>::type, X3 );
BOOST_TEST_EQ( (mp_at_c<L, 0>::modifiers), mod_private );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 1>::type, X4 );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 1>::type, V3 );
BOOST_TEST_EQ( (mp_at_c<L, 1>::modifiers), mod_private | mod_virtual );
}
{
using L = describe_bases<Y, mod_protected>;
using L = describe_bases<Z, mod_any_access>;
BOOST_TEST_EQ( mp_size<L>::value, 0 );
BOOST_TEST_EQ( mp_size<L>::value, 3 );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 0>::type, X1 );
BOOST_TEST_EQ( (mp_at_c<L, 0>::modifiers), mod_public );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 1>::type, X2 );
BOOST_TEST_EQ( (mp_at_c<L, 1>::modifiers), mod_public );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 2>::type, X3 );
BOOST_TEST_EQ( (mp_at_c<L, 2>::modifiers), mod_public );
}
return boost::report_errors();

View File

@@ -0,0 +1,143 @@
// Copyright 2020, 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/bases.hpp>
#include <boost/describe/members.hpp>
#include <boost/describe/class.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/config.hpp>
template<class A1, class A2> struct X
{
A1 a1;
A2 a2;
BOOST_DESCRIBE_CLASS(X, (), (a1, a2), (), ())
};
template<class B1, class B2> class Y
{
private:
B1 b1;
B2 b2;
BOOST_DESCRIBE_CLASS(Y, (), (), (), (b1, b2))
};
template<class T1, class T2> class Z: public X<T1, T2>
{
private:
// error: declaration of 'typedef struct X<T1, T2> Z<T1, T2>::X' changes meaning of 'X' (g++)
// typedef X<T1, T2> X;
typedef X<T1, T2> XB;
protected:
Y<T1, T2> y;
BOOST_DESCRIBE_CLASS(Z, (XB), (), (y), ())
};
#if !defined(BOOST_DESCRIBE_CXX14)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
int main() {}
#elif defined(BOOST_MSVC) && BOOST_MSVC < 1920
BOOST_PRAGMA_MESSAGE("Skipping test because BOOST_MSVC is below 1920")
int main() {}
#elif defined(BOOST_MSVC) && BOOST_MSVC >= 1920 && BOOST_MSVC < 1940 && _MSVC_LANG <= 201703L
BOOST_PRAGMA_MESSAGE("Skipping test because BOOST_MSVC is 192x or 193x and _MSVC_LANG is 201703L or below")
int main() {}
#else
#include <boost/mp11.hpp>
using namespace boost::mp11;
int main()
{
using namespace boost::describe;
using namespace boost::mp11;
{
using L = describe_members<X<int, float>, mod_any_access>;
BOOST_TEST_EQ( mp_size<L>::value, 2 );
using D1 = mp_at_c<L, 0>;
using D2 = mp_at_c<L, 1>;
BOOST_TEST( D1::pointer == (&X<int, float>::a1) );
BOOST_TEST_CSTR_EQ( D1::name, "a1" );
BOOST_TEST_EQ( D1::modifiers, mod_public );
BOOST_TEST( D2::pointer == (&X<int, float>::a2) );
BOOST_TEST_CSTR_EQ( D2::name, "a2" );
BOOST_TEST_EQ( D2::modifiers, mod_public );
}
{
using L = describe_members<Y<int, float>, mod_any_access>;
BOOST_TEST_EQ( mp_size<L>::value, 2 );
using D1 = mp_at_c<L, 0>;
using D2 = mp_at_c<L, 1>;
// BOOST_TEST( D1::pointer == (&Y<int, float>::b1) );
BOOST_TEST_CSTR_EQ( D1::name, "b1" );
BOOST_TEST_EQ( D1::modifiers, mod_private );
// BOOST_TEST( D2::pointer == (&Y<int, float>::b2) );
BOOST_TEST_CSTR_EQ( D2::name, "b2" );
BOOST_TEST_EQ( D2::modifiers, mod_private );
}
{
using L = describe_members<Z<int, float>, mod_any_access>;
BOOST_TEST_EQ( mp_size<L>::value, 1 );
using D1 = mp_at_c<L, 0>;
// BOOST_TEST( D1::pointer == (&Z<int, float>::y) );
BOOST_TEST_CSTR_EQ( D1::name, "y" );
BOOST_TEST_EQ( D1::modifiers, mod_protected );
}
{
using L = describe_members<Z<int, float>, mod_any_access | mod_inherited>;
BOOST_TEST_EQ( mp_size<L>::value, 3 );
using D1 = mp_at_c<L, 0>;
using D2 = mp_at_c<L, 1>;
using D3 = mp_at_c<L, 2>;
BOOST_TEST( D1::pointer == (&X<int, float>::a1) );
BOOST_TEST_CSTR_EQ( D1::name, "a1" );
BOOST_TEST_EQ( D1::modifiers, mod_public | mod_inherited );
BOOST_TEST( D2::pointer == (&X<int, float>::a2) );
BOOST_TEST_CSTR_EQ( D2::name, "a2" );
BOOST_TEST_EQ( D2::modifiers, mod_public | mod_inherited );
// BOOST_TEST( D3::pointer == (&Z<int, float>::y) );
BOOST_TEST_CSTR_EQ( D3::name, "y" );
BOOST_TEST_EQ( D3::modifiers, mod_protected );
}
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX14)

View File

@@ -0,0 +1,17 @@
# Copyright 2018, 2019, 2022 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
cmake_minimum_required(VERSION 3.5...3.20)
project(cmake_install_test LANGUAGES CXX)
find_package(boost_describe REQUIRED)
add_executable(main main.cpp)
target_link_libraries(main Boost::describe)
enable_testing()
add_test(main main)
add_custom_target(check VERBATIM COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $<CONFIG>)

View File

@@ -0,0 +1,49 @@
// Copyright 2017, 2020, 2021, 2022 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe.hpp>
#include <cassert>
#define BOOST_TEST(expr) assert(expr)
#define BOOST_TEST_EQ(x1, x2) assert((x1)==(x2))
struct X
{
int m;
};
BOOST_DESCRIBE_STRUCT(X, (), (m))
struct Y: public X
{
void m() {}
};
BOOST_DESCRIBE_STRUCT(Y, (X), (m))
#if !defined(BOOST_DESCRIBE_CXX14)
#pragma message "Skipping test because C++14 is not available"
int main()
{
}
#else
BOOST_DEFINE_ENUM(E, v1, v2, v3)
#include <boost/mp11.hpp>
int main()
{
using namespace boost::describe;
using namespace boost::mp11;
BOOST_TEST_EQ( (mp_size< describe_enumerators<E> >::value), 3 );
BOOST_TEST_EQ( (mp_size< describe_bases<Y, mod_any_access> >::value), 1 );
BOOST_TEST_EQ( (mp_size< describe_members<Y, mod_any_access | mod_inherited | mod_hidden> >::value), 1 );
}
#endif // !defined(BOOST_DESCRIBE_CXX14)

View File

@@ -0,0 +1,22 @@
# Copyright 2018-2022 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
cmake_minimum_required(VERSION 3.5...3.20)
project(cmake_subdir_test LANGUAGES CXX)
add_subdirectory(../.. boostorg/describe)
add_subdirectory(../../../assert boostorg/assert)
add_subdirectory(../../../config boostorg/config)
add_subdirectory(../../../core boostorg/core)
add_subdirectory(../../../mp11 boostorg/mp11)
add_subdirectory(../../../throw_exception boostorg/throw_exception)
add_executable(quick ../quick.cpp)
target_link_libraries(quick Boost::describe Boost::core)
enable_testing()
add_test(quick quick)
add_custom_target(check VERBATIM COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure --no-tests=error -C $<CONFIG>)

View File

@@ -0,0 +1,119 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/detail/config.hpp>
#if !defined(BOOST_DESCRIBE_CXX14)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
int main() {}
#else
#include <boost/describe/detail/compute_base_modifiers.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/core/lightweight_test_trait.hpp>
struct X1
{
};
struct X2
{
};
struct X3
{
};
struct V1
{
V1(int);
};
struct V2
{
V2(int);
};
struct V3
{
V3(int);
};
struct Y: public X1, protected X2, private X3, public virtual V1, protected virtual V2, private virtual V3
{
};
struct Z final: public X1, protected X2, private X3, public virtual V1, protected virtual V2, private virtual V3
{
};
int main()
{
using namespace boost::describe::detail;
using namespace boost::describe;
BOOST_TEST( (is_public_base_of<X1, Y>::value) );
BOOST_TEST( (!is_virtual_base_of<X1, Y>::value) );
BOOST_TEST_EQ( (compute_base_modifiers<Y, X1>()), mod_public );
BOOST_TEST( (!is_public_base_of<X2, Y>::value) );
BOOST_TEST( (is_protected_base_of<X2, Y>::value) );
BOOST_TEST( (!is_virtual_base_of<X2, Y>::value) );
BOOST_TEST_EQ( (compute_base_modifiers<Y, X2>()), mod_protected );
BOOST_TEST( (!is_public_base_of<X3, Y>::value) );
BOOST_TEST( (!is_protected_base_of<X3, Y>::value) );
BOOST_TEST( (!is_virtual_base_of<X3, Y>::value) );
BOOST_TEST_EQ( (compute_base_modifiers<Y, X3>()), mod_private );
BOOST_TEST( (is_public_base_of<V1, Y>::value) );
BOOST_TEST( (is_virtual_base_of<V1, Y>::value) );
BOOST_TEST_EQ( (compute_base_modifiers<Y, V1>()), mod_public | mod_virtual );
BOOST_TEST( (!is_public_base_of<V2, Y>::value) );
BOOST_TEST( (is_protected_base_of<V2, Y>::value) );
BOOST_TEST( (is_virtual_base_of<V2, Y>::value) );
BOOST_TEST_EQ( (compute_base_modifiers<Y, V2>()), mod_protected | mod_virtual );
BOOST_TEST( (!is_public_base_of<V3, Y>::value) );
BOOST_TEST( (!is_protected_base_of<V3, Y>::value) );
BOOST_TEST( (is_virtual_base_of<V3, Y>::value) );
BOOST_TEST_EQ( (compute_base_modifiers<Y, V3>()), mod_private | mod_virtual );
BOOST_TEST( (is_public_base_of<X1, Z>::value) );
BOOST_TEST( (!is_virtual_base_of<X1, Z>::value) );
BOOST_TEST_EQ( (compute_base_modifiers<Z, X1>()), mod_public );
BOOST_TEST( (!is_public_base_of<X2, Z>::value) );
BOOST_TEST( (!is_protected_base_of<X2, Z>::value) );
BOOST_TEST( (!is_virtual_base_of<X2, Z>::value) );
BOOST_TEST_EQ( (compute_base_modifiers<Z, X2>()), mod_private );
BOOST_TEST( (!is_public_base_of<X3, Z>::value) );
BOOST_TEST( (!is_protected_base_of<X3, Z>::value) );
BOOST_TEST( (!is_virtual_base_of<X3, Z>::value) );
BOOST_TEST_EQ( (compute_base_modifiers<Z, X3>()), mod_private );
BOOST_TEST( (is_public_base_of<V1, Z>::value) );
BOOST_TEST( (is_virtual_base_of<V1, Z>::value) );
BOOST_TEST_EQ( (compute_base_modifiers<Z, V1>()), mod_public | mod_virtual );
BOOST_TEST( (!is_public_base_of<V2, Z>::value) );
BOOST_TEST( (!is_protected_base_of<V2, Z>::value) );
BOOST_TEST( (is_virtual_base_of<V2, Z>::value) );
BOOST_TEST_EQ( (compute_base_modifiers<Z, V2>()), mod_private | mod_virtual );
BOOST_TEST( (!is_public_base_of<V3, Z>::value) );
BOOST_TEST( (!is_protected_base_of<V3, Z>::value) );
BOOST_TEST( (is_virtual_base_of<V3, Z>::value) );
BOOST_TEST_EQ( (compute_base_modifiers<Z, V3>()), mod_private | mod_virtual );
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX14)

View File

@@ -0,0 +1,64 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/descriptor_by_name.hpp>
#include <boost/describe/class.hpp>
#include <boost/describe/members.hpp>
#include <boost/core/lightweight_test.hpp>
#if !defined(BOOST_DESCRIBE_CXX14)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
int main() {}
#else
struct X
{
int a = 1;
int b = 2;
};
BOOST_DESCRIBE_STRUCT(X, (), (a, b))
struct Y
{
int a = 1;
int c = 3;
};
BOOST_DESCRIBE_STRUCT(Y, (), (a, c))
int main()
{
{
using L = boost::describe::describe_members<X, boost::describe::mod_any_access>;
using Na = BOOST_DESCRIBE_MAKE_NAME( a );
using Da = boost::describe::descriptor_by_name<L, Na>;
BOOST_TEST_CSTR_EQ( Da::name, "a" );
using Nb = BOOST_DESCRIBE_MAKE_NAME( b );
using Db = boost::describe::descriptor_by_name<L, Nb>;
BOOST_TEST_CSTR_EQ( Db::name, "b" );
}
{
using L = boost::describe::describe_members<Y, boost::describe::mod_any_access>;
using Na = BOOST_DESCRIBE_MAKE_NAME( a );
using Da = boost::describe::descriptor_by_name<L, Na>;
BOOST_TEST_CSTR_EQ( Da::name, "a" );
using Nc = BOOST_DESCRIBE_MAKE_NAME( c );
using Dc = boost::describe::descriptor_by_name<L, Nc>;
BOOST_TEST_CSTR_EQ( Dc::name, "c" );
}
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX14)

View File

@@ -0,0 +1,65 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/descriptor_by_pointer.hpp>
#include <boost/describe/class.hpp>
#include <boost/describe/members.hpp>
#include <boost/core/lightweight_test.hpp>
#if !defined(__cpp_nontype_template_parameter_auto) || __cpp_nontype_template_parameter_auto < 201606L
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because __cpp_nontype_template_parameter_auto is not defined")
int main() {}
#else
struct X
{
int a = 1;
float b = 3.14f;
};
BOOST_DESCRIBE_STRUCT(X, (), (a, b))
struct Y: public X
{
long a = 2;
double c = 3.14;
};
BOOST_DESCRIBE_STRUCT(Y, (X), (a, c))
int main()
{
using namespace boost::describe;
{
using L = describe_members<X, mod_any_access>;
using Da = descriptor_by_pointer<L, &X::a>;
BOOST_TEST_CSTR_EQ( Da::name, "a" );
using Db = descriptor_by_pointer<L, &X::b>;
BOOST_TEST_CSTR_EQ( Db::name, "b" );
}
{
using L = describe_members<Y, mod_any_access | mod_inherited>;
using Da = descriptor_by_pointer<L, &Y::a>;
BOOST_TEST_CSTR_EQ( Da::name, "a" );
using Db = descriptor_by_pointer<L, &Y::b>;
BOOST_TEST_CSTR_EQ( Db::name, "b" );
using Dc = descriptor_by_pointer<L, &Y::c>;
BOOST_TEST_CSTR_EQ( Dc::name, "c" );
}
return boost::report_errors();
}
#endif // __cpp_nontype_template_parameter_auto

41
test/empty_enum_test.cpp Normal file
View File

@@ -0,0 +1,41 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/enumerators.hpp>
#include <boost/describe/enum.hpp>
#include <boost/core/lightweight_test.hpp>
enum E1 {};
BOOST_DESCRIBE_ENUM(E1)
BOOST_DEFINE_ENUM(E2)
#if !defined(BOOST_DESCRIBE_CXX14)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
int main() {}
#else
#include <boost/mp11.hpp>
using namespace boost::mp11;
int main()
{
{
using D1 = boost::describe::describe_enumerators<E1>;
BOOST_TEST_EQ( mp_size<D1>::value, 0 );
}
{
using D2 = boost::describe::describe_enumerators<E2>;
BOOST_TEST_EQ( mp_size<D2>::value, 0 );
}
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX14)

View File

@@ -0,0 +1,62 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/enum_from_string.hpp>
#include <boost/describe/enum.hpp>
#include <boost/core/lightweight_test.hpp>
#if !defined(BOOST_DESCRIBE_CXX14)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
int main() {}
#else
enum E1 { v101 = 101, v102 = 102 };
BOOST_DESCRIBE_ENUM(E1, v101, v102)
enum class E2 { v201 = 201, v202 = 202 };
BOOST_DESCRIBE_ENUM(E2, v201, v202)
BOOST_DEFINE_ENUM(E3, v301, v302)
BOOST_DEFINE_ENUM_CLASS(E4, v401, v402)
int main()
{
using boost::describe::enum_from_string;
{
E1 w{};
BOOST_TEST( enum_from_string( "v101", w ) ) && BOOST_TEST_EQ( w, v101 );
BOOST_TEST( enum_from_string( "v102", w ) ) && BOOST_TEST_EQ( w, v102 );
BOOST_TEST_NOT( enum_from_string( "v103", w ) );
}
{
E2 w{};
BOOST_TEST( enum_from_string( "v201", w ) ) && BOOST_TEST_EQ( (int)w, (int)E2::v201 );
BOOST_TEST( enum_from_string( "v202", w ) ) && BOOST_TEST_EQ( (int)w, (int)E2::v202 );
BOOST_TEST_NOT( enum_from_string( "v203", w ) );
}
{
E3 w{};
BOOST_TEST( enum_from_string( "v301", w ) ) && BOOST_TEST_EQ( w, v301 );
BOOST_TEST( enum_from_string( "v302", w ) ) && BOOST_TEST_EQ( w, v302 );
BOOST_TEST_NOT( enum_from_string( "v303", w ) );
}
{
E4 w{};
BOOST_TEST( enum_from_string( "v401", w ) ) && BOOST_TEST_EQ( (int)w, (int)E4::v401 );
BOOST_TEST( enum_from_string( "v402", w ) ) && BOOST_TEST_EQ( (int)w, (int)E4::v402 );
BOOST_TEST_NOT( enum_from_string( "v403", w ) );
}
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX14)

View File

@@ -0,0 +1,78 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/enum_from_string.hpp>
#include <boost/describe/enum.hpp>
#include <boost/core/detail/string_view.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/config.hpp>
#if !defined(BOOST_DESCRIBE_CXX14)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
int main() {}
#else
enum E1 { v101 = 101, v102 = 102 };
BOOST_DESCRIBE_ENUM(E1, v101, v102)
enum class E2 { v201 = 201, v202 = 202 };
BOOST_DESCRIBE_ENUM(E2, v201, v202)
BOOST_DEFINE_ENUM(E3, v301, v302)
BOOST_DEFINE_ENUM_CLASS(E4, v401, v402)
template<class St> void test()
{
using boost::describe::enum_from_string;
{
E1 w{};
BOOST_TEST( enum_from_string( St( "v101" ), w ) ) && BOOST_TEST_EQ( w, v101 );
BOOST_TEST( enum_from_string( St( "v102" ), w ) ) && BOOST_TEST_EQ( w, v102 );
BOOST_TEST_NOT( enum_from_string( St( "v103" ), w ) );
}
{
E2 w{};
BOOST_TEST( enum_from_string( St( "v201" ), w ) ) && BOOST_TEST_EQ( (int)w, (int)E2::v201 );
BOOST_TEST( enum_from_string( St( "v202" ), w ) ) && BOOST_TEST_EQ( (int)w, (int)E2::v202 );
BOOST_TEST_NOT( enum_from_string( St( "v203" ), w ) );
}
{
E3 w{};
BOOST_TEST( enum_from_string( St( "v301" ), w ) ) && BOOST_TEST_EQ( w, v301 );
BOOST_TEST( enum_from_string( St( "v302" ), w ) ) && BOOST_TEST_EQ( w, v302 );
BOOST_TEST_NOT( enum_from_string( St( "v303" ), w ) );
}
{
E4 w{};
BOOST_TEST( enum_from_string( St( "v401" ), w ) ) && BOOST_TEST_EQ( (int)w, (int)E4::v401 );
BOOST_TEST( enum_from_string( St( "v402" ), w ) ) && BOOST_TEST_EQ( (int)w, (int)E4::v402 );
BOOST_TEST_NOT( enum_from_string( St( "v403" ), w ) );
}
}
#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
# include <string_view>
#endif
int main()
{
test<std::string>();
test<boost::core::string_view>();
#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
test<std::string_view>();
#endif
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX14)

18
test/enum_nested_fail.cpp Normal file
View File

@@ -0,0 +1,18 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/enum.hpp>
#if !defined(BOOST_DESCRIBE_CXX14)
#error "Skipping test because C++14 is not available"
#else
struct S1 {
enum E1 {};
BOOST_DESCRIBE_ENUM(E1)
};
#endif // !defined(BOOST_DESCRIBE_CXX14)

16
test/enum_struct_fail.cpp Normal file
View File

@@ -0,0 +1,16 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/class.hpp>
#if !defined(BOOST_DESCRIBE_CXX14)
#error "Skipping test because C++14 is not available"
#else
enum E1 {};
BOOST_DESCRIBE_STRUCT(E1, (), ())
#endif // !defined(BOOST_DESCRIBE_CXX14)

View File

@@ -0,0 +1,41 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/enum_to_string.hpp>
#include <boost/describe/enum.hpp>
#include <boost/core/lightweight_test.hpp>
#if !defined(BOOST_DESCRIBE_CXX14)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
int main() {}
#else
enum E1 { v1 };
BOOST_DESCRIBE_ENUM(E1, v1)
enum class E2 { v2 };
BOOST_DESCRIBE_ENUM(E2, v2)
BOOST_DEFINE_ENUM(E3, v3)
BOOST_DEFINE_ENUM_CLASS(E4, v4)
int main()
{
using boost::describe::enum_to_string;
BOOST_TEST_CSTR_EQ( enum_to_string( v1, "" ), "v1" );
BOOST_TEST_CSTR_EQ( enum_to_string( E2::v2, "" ), "v2" );
BOOST_TEST_CSTR_EQ( enum_to_string( static_cast<E2>( 14 ), "__def__" ), "__def__" );
BOOST_TEST_CSTR_EQ( enum_to_string( v3, "" ), "v3" );
BOOST_TEST_CSTR_EQ( enum_to_string( E4::v4, "" ), "v4" );
BOOST_TEST_EQ( enum_to_string( static_cast<E4>( 14 ), 0 ), static_cast<char const*>( 0 ) );
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX14)

View File

@@ -0,0 +1,32 @@
// Copyright 2021, 2025 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/enum_to_string.hpp>
#include <boost/describe/enum.hpp>
#include <boost/describe/detail/cx_streq.hpp>
#include <boost/config/pragma_message.hpp>
#if !defined(BOOST_DESCRIBE_CXX14)
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
#elif defined(_MSC_VER) && _MSC_VER == 1900
BOOST_PRAGMA_MESSAGE("Skipping test because _MSC_VER == 1900")
#else
#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
BOOST_DEFINE_ENUM_CLASS(E, v1, v2, v3)
using boost::describe::enum_to_string;
using boost::describe::detail::cx_streq;
STATIC_ASSERT( cx_streq( enum_to_string( E::v1, "" ), "v1" ) );
STATIC_ASSERT( cx_streq( enum_to_string( E::v2, "" ), "v2" ) );
STATIC_ASSERT( cx_streq( enum_to_string( E::v3, "" ), "v3" ) );
STATIC_ASSERT( cx_streq( enum_to_string( (E)17, "def" ), "def" ) );
#endif // !defined(BOOST_DESCRIBE_CXX14)

View File

@@ -6,6 +6,37 @@
#include <boost/describe/enum.hpp>
#include <boost/core/lightweight_test.hpp>
enum E1
{
v1_1 = 5
};
BOOST_DESCRIBE_ENUM(E1, v1_1)
BOOST_DEFINE_ENUM(E3, v3_1, v3_2, v3_3)
#if !defined(BOOST_DESCRIBE_CXX11)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++11 is not available")
int main() {}
#else
enum class E2
{
v2_1,
v2_2 = 7
};
BOOST_DESCRIBE_ENUM(E2, v2_1, v2_2)
BOOST_DEFINE_FIXED_ENUM(E4, int, v4_1, v4_2, v4_3, v4_4)
BOOST_DEFINE_ENUM_CLASS(E5, v5_1, v5_2, v5_3, v5_4, v5_5)
BOOST_DEFINE_FIXED_ENUM_CLASS(E6, int, v6_1, v6_2, v6_3, v6_4, v6_5, v6_6)
#if !defined(BOOST_DESCRIBE_CXX14)
#include <boost/config/pragma_message.hpp>
@@ -15,27 +46,6 @@ int main() {}
#else
enum E1
{
v1_1 = 5
};
BOOST_DESCRIBE_ENUM(E1, v1_1);
enum class E2
{
v2_1,
v2_2 = 7
};
BOOST_DESCRIBE_ENUM_CLASS(E2, v2_1, v2_2);
BOOST_DEFINE_ENUM(E3, v3_1, v3_2, v3_3);
BOOST_DEFINE_FIXED_ENUM(E4, int, v4_1, v4_2, v4_3, v4_4);
BOOST_DEFINE_ENUM_CLASS(E5, v5_1, v5_2, v5_3, v5_4, v5_5);
BOOST_DEFINE_FIXED_ENUM_CLASS(E6, int, v6_1, v6_2, v6_3, v6_4, v6_5, v6_6);
#include <boost/mp11.hpp>
using namespace boost::mp11;
@@ -144,3 +154,4 @@ int main()
}
#endif // !defined(BOOST_DESCRIBE_CXX14)
#endif // !defined(BOOST_DESCRIBE_CXX11)

60
test/has_bases_test.cpp Normal file
View File

@@ -0,0 +1,60 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/bases.hpp>
#include <boost/describe/class.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#if !defined(BOOST_DESCRIBE_CXX11)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++11 is not available")
int main() {}
#else
struct X1 {};
BOOST_DESCRIBE_STRUCT(X1, (), ())
class X2
{
BOOST_DESCRIBE_CLASS(X2, (), (), (), ())
};
struct X3 {};
class X4 {};
union X5 {};
struct X6: X1 {};
struct X7: X2 {};
int main()
{
using boost::describe::has_describe_bases;
#if defined(BOOST_DESCRIBE_CXX14)
BOOST_TEST_TRAIT_TRUE((has_describe_bases<X1>));
BOOST_TEST_TRAIT_TRUE((has_describe_bases<X2>));
#else
BOOST_TEST_TRAIT_FALSE((has_describe_bases<X1>));
BOOST_TEST_TRAIT_FALSE((has_describe_bases<X2>));
#endif
BOOST_TEST_TRAIT_FALSE((has_describe_bases<X3>));
BOOST_TEST_TRAIT_FALSE((has_describe_bases<X4>));
BOOST_TEST_TRAIT_FALSE((has_describe_bases<X5>));
BOOST_TEST_TRAIT_FALSE((has_describe_bases<X6>));
BOOST_TEST_TRAIT_FALSE((has_describe_bases<X7>));
BOOST_TEST_TRAIT_FALSE((has_describe_bases<int>));
BOOST_TEST_TRAIT_FALSE((has_describe_bases<void>));
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX11)

View File

@@ -0,0 +1,58 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/enumerators.hpp>
#include <boost/describe/enum.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#if !defined(BOOST_DESCRIBE_CXX11)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++11 is not available")
int main() {}
#else
enum E1 { v1 };
BOOST_DESCRIBE_ENUM(E1, v1)
enum class E2 { v2 };
BOOST_DESCRIBE_ENUM(E2, v2)
BOOST_DEFINE_ENUM(E3, v3)
BOOST_DEFINE_ENUM_CLASS(E4, v4)
enum E5 { v5 };
enum class E6 { v6 };
int main()
{
using boost::describe::has_describe_enumerators;
#if defined(BOOST_DESCRIBE_CXX14)
BOOST_TEST_TRAIT_TRUE((has_describe_enumerators<E1>));
BOOST_TEST_TRAIT_TRUE((has_describe_enumerators<E2>));
BOOST_TEST_TRAIT_TRUE((has_describe_enumerators<E3>));
BOOST_TEST_TRAIT_TRUE((has_describe_enumerators<E4>));
#else
BOOST_TEST_TRAIT_FALSE((has_describe_enumerators<E1>));
BOOST_TEST_TRAIT_FALSE((has_describe_enumerators<E2>));
BOOST_TEST_TRAIT_FALSE((has_describe_enumerators<E3>));
BOOST_TEST_TRAIT_FALSE((has_describe_enumerators<E4>));
#endif
BOOST_TEST_TRAIT_FALSE((has_describe_enumerators<E5>));
BOOST_TEST_TRAIT_FALSE((has_describe_enumerators<E6>));
BOOST_TEST_TRAIT_FALSE((has_describe_enumerators<int>));
BOOST_TEST_TRAIT_FALSE((has_describe_enumerators<void>));
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX11)

60
test/has_members_test.cpp Normal file
View File

@@ -0,0 +1,60 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/members.hpp>
#include <boost/describe/class.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#if !defined(BOOST_DESCRIBE_CXX11)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++11 is not available")
int main() {}
#else
struct X1 {};
BOOST_DESCRIBE_STRUCT(X1, (), ())
class X2
{
BOOST_DESCRIBE_CLASS(X2, (), (), (), ())
};
struct X3 {};
class X4 {};
union X5 {};
struct X6: X1 {};
struct X7: X2 {};
int main()
{
using boost::describe::has_describe_members;
#if defined(BOOST_DESCRIBE_CXX14)
BOOST_TEST_TRAIT_TRUE((has_describe_members<X1>));
BOOST_TEST_TRAIT_TRUE((has_describe_members<X2>));
#else
BOOST_TEST_TRAIT_FALSE((has_describe_members<X1>));
BOOST_TEST_TRAIT_FALSE((has_describe_members<X2>));
#endif
BOOST_TEST_TRAIT_FALSE((has_describe_members<X3>));
BOOST_TEST_TRAIT_FALSE((has_describe_members<X4>));
BOOST_TEST_TRAIT_FALSE((has_describe_members<X5>));
BOOST_TEST_TRAIT_FALSE((has_describe_members<X6>));
BOOST_TEST_TRAIT_FALSE((has_describe_members<X7>));
BOOST_TEST_TRAIT_FALSE((has_describe_members<int>));
BOOST_TEST_TRAIT_FALSE((has_describe_members<void>));
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX11)

View File

@@ -40,7 +40,7 @@ private:
BOOST_DESCRIBE_CLASS(A2, (), (m1), (m2), (m3))
};
struct B: public A1, private A2
class A3
{
public:
@@ -54,7 +54,24 @@ private:
int m3;
BOOST_DESCRIBE_CLASS(B, (A1, A2), (m1), (m2), (m3))
BOOST_DESCRIBE_CLASS(A3, (), (m1), (m2), (m3))
};
struct B: public A1, protected A2, private A3
{
public:
int m1;
protected:
int m2;
private:
int m3;
BOOST_DESCRIBE_CLASS(B, (A1, A2, A3), (m1), (m2), (m3))
};
#if !defined(BOOST_DESCRIBE_CXX14)
@@ -93,50 +110,65 @@ int main()
{
using L = describe_members<B, mod_protected | mod_inherited | mod_hidden>;
BOOST_TEST_EQ( mp_size<L>::value, 2 );
BOOST_TEST_EQ( mp_size<L>::value, 4 );
using D1 = mp_at_c<L, 0>;
using D2 = mp_at_c<L, 1>;
using D3 = mp_at_c<L, 2>;
using D4 = mp_at_c<L, 3>;
// BOOST_TEST( D1::pointer == &B::A1::m2 );
BOOST_TEST_CSTR_EQ( D1::name, "m2" );
BOOST_TEST_EQ( D1::modifiers, mod_protected | mod_inherited | mod_hidden );
// BOOST_TEST( D2::pointer == &B::m2 );
BOOST_TEST_CSTR_EQ( D2::name, "m2" );
BOOST_TEST_EQ( D2::modifiers, mod_protected );
// BOOST_TEST( D2::pointer == &B::A2::m1 );
BOOST_TEST_CSTR_EQ( D2::name, "m1" );
BOOST_TEST_EQ( D2::modifiers, mod_protected | mod_inherited | mod_hidden );
// BOOST_TEST( D3::pointer == &B::A2::m2 );
BOOST_TEST_CSTR_EQ( D3::name, "m2" );
BOOST_TEST_EQ( D3::modifiers, mod_protected | mod_inherited | mod_hidden );
// BOOST_TEST( D4::pointer == &B::m2 );
BOOST_TEST_CSTR_EQ( D4::name, "m2" );
BOOST_TEST_EQ( D4::modifiers, mod_protected );
}
{
using L = describe_members<B, mod_private | mod_inherited | mod_hidden>;
BOOST_TEST_EQ( mp_size<L>::value, 5 );
BOOST_TEST_EQ( mp_size<L>::value, 6 );
using D1 = mp_at_c<L, 0>;
using D2 = mp_at_c<L, 1>;
using D3 = mp_at_c<L, 2>;
using D4 = mp_at_c<L, 3>;
using D5 = mp_at_c<L, 4>;
using D6 = mp_at_c<L, 5>;
// BOOST_TEST( D1::pointer == &B::A1::m3 );
BOOST_TEST_CSTR_EQ( D1::name, "m3" );
BOOST_TEST_EQ( D1::modifiers, mod_private | mod_inherited | mod_hidden );
// BOOST_TEST( D2::pointer == &B::A2::m1 );
BOOST_TEST_CSTR_EQ( D2::name, "m1" );
// BOOST_TEST( D2::pointer == &B::A2::m3 );
BOOST_TEST_CSTR_EQ( D2::name, "m3" );
BOOST_TEST_EQ( D2::modifiers, mod_private | mod_inherited | mod_hidden );
// BOOST_TEST( D3::pointer == &B::A2::m2 );
BOOST_TEST_CSTR_EQ( D3::name, "m2" );
// BOOST_TEST( D3::pointer == &B::A3::m1 );
BOOST_TEST_CSTR_EQ( D3::name, "m1" );
BOOST_TEST_EQ( D3::modifiers, mod_private | mod_inherited | mod_hidden );
// BOOST_TEST( D4::pointer == &B::A2::m3 );
BOOST_TEST_CSTR_EQ( D4::name, "m3" );
// BOOST_TEST( D4::pointer == &B::A3::m2 );
BOOST_TEST_CSTR_EQ( D4::name, "m2" );
BOOST_TEST_EQ( D4::modifiers, mod_private | mod_inherited | mod_hidden );
// BOOST_TEST( D5::pointer == &B::m3 );
// BOOST_TEST( D5::pointer == &B::A3::m3 );
BOOST_TEST_CSTR_EQ( D5::name, "m3" );
BOOST_TEST_EQ( D5::modifiers, mod_private );
BOOST_TEST_EQ( D5::modifiers, mod_private | mod_inherited | mod_hidden );
// BOOST_TEST( D6::pointer == &B::m3 );
BOOST_TEST_CSTR_EQ( D6::name, "m3" );
BOOST_TEST_EQ( D6::modifiers, mod_private );
}
return boost::report_errors();

View File

@@ -59,7 +59,7 @@ int main()
using D1 = mp_at_c<L, 0>;
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1930)
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1940)
// https://developercommunity.visualstudio.com/content/problem/1186002/constexpr-pointer-to-member-has-incorrect-value.html
BOOST_TEST( D1::pointer == &C::m2 );
#endif
@@ -79,7 +79,7 @@ int main()
BOOST_TEST_CSTR_EQ( D1::name, "m1" );
BOOST_TEST_EQ( D1::modifiers, mod_public | mod_inherited );
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1930)
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1940)
BOOST_TEST( D2::pointer == &C::m2 );
#endif
BOOST_TEST_CSTR_EQ( D2::name, "m2" );

67
test/members_test8.cpp Normal file
View File

@@ -0,0 +1,67 @@
// Copyright 2020, 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/members.hpp>
#include <boost/describe/class.hpp>
#include <boost/core/lightweight_test.hpp>
struct A
{
int m1;
static int m2;
int f1() const { return m1; }
static int f2() { return m2; }
};
BOOST_DESCRIBE_STRUCT(A, (), (m1, m2, f1, f2))
int A::m2;
#if !defined(BOOST_DESCRIBE_CXX14)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
int main() {}
#else
#include <boost/mp11.hpp>
int main()
{
using namespace boost::describe;
using namespace boost::mp11;
{
using L = describe_members<A, mod_any_access | mod_any_member>;
BOOST_TEST_EQ( mp_size<L>::value, 4 );
using D1 = mp_at_c<L, 0>;
using D2 = mp_at_c<L, 1>;
using D3 = mp_at_c<L, 2>;
using D4 = mp_at_c<L, 3>;
BOOST_TEST( D1::pointer == &A::m1 );
BOOST_TEST_CSTR_EQ( D1::name, "m1" );
BOOST_TEST_EQ( D1::modifiers, mod_public );
BOOST_TEST( D2::pointer == &A::m2 );
BOOST_TEST_CSTR_EQ( D2::name, "m2" );
BOOST_TEST_EQ( D2::modifiers, mod_public | mod_static );
BOOST_TEST( D3::pointer == &A::f1 );
BOOST_TEST_CSTR_EQ( D3::name, "f1" );
BOOST_TEST_EQ( D3::modifiers, mod_public | mod_function );
BOOST_TEST( D4::pointer == &A::f2 );
BOOST_TEST_CSTR_EQ( D4::name, "f2" );
BOOST_TEST_EQ( D4::modifiers, mod_public | mod_static | mod_function );
}
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX14)

16
test/nested_enum_fail.cpp Normal file
View File

@@ -0,0 +1,16 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/enum.hpp>
#if !defined(BOOST_DESCRIBE_CXX14)
#error "Skipping test because C++14 is not available"
#else
enum E1 {};
BOOST_DESCRIBE_NESTED_ENUM(E1);
#endif // !defined(BOOST_DESCRIBE_CXX14)

130
test/nested_enum_test.cpp Normal file
View File

@@ -0,0 +1,130 @@
// Copyright 2020, 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/enumerators.hpp>
#include <boost/describe/enum.hpp>
#include <boost/core/lightweight_test.hpp>
struct X1
{
enum E
{
v1 = 5
};
BOOST_DESCRIBE_NESTED_ENUM(E, v1)
};
class X2
{
private:
enum E
{
v1, v2
};
BOOST_DESCRIBE_NESTED_ENUM(E, v1, v2)
public:
typedef E E2;
};
#if !defined(BOOST_DESCRIBE_CXX11)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++11 is not available")
int main() {}
#else
struct X3
{
enum class E
{
v1 = 7
};
BOOST_DESCRIBE_NESTED_ENUM(E, v1)
};
class X4
{
private:
enum class E
{
v1, v2
};
BOOST_DESCRIBE_NESTED_ENUM(E, v1, v2)
public:
typedef E E2;
};
#if !defined(BOOST_DESCRIBE_CXX14)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
int main() {}
#else
#include <boost/mp11.hpp>
using namespace boost::mp11;
int main()
{
{
using D = boost::describe::describe_enumerators<X1::E>;
BOOST_TEST_EQ( mp_size<D>::value, 1 );
BOOST_TEST_EQ( (mp_at_c<D, 0>::value), X1::v1 );
BOOST_TEST_CSTR_EQ( (mp_at_c<D, 0>::name), "v1" );
}
{
using D = boost::describe::describe_enumerators<X2::E2>;
BOOST_TEST_EQ( mp_size<D>::value, 2 );
BOOST_TEST_EQ( (mp_at_c<D, 0>::value), 0 );
BOOST_TEST_CSTR_EQ( (mp_at_c<D, 0>::name), "v1" );
BOOST_TEST_EQ( (mp_at_c<D, 1>::value), 1 );
BOOST_TEST_CSTR_EQ( (mp_at_c<D, 1>::name), "v2" );
}
{
using D = boost::describe::describe_enumerators<X3::E>;
BOOST_TEST_EQ( mp_size<D>::value, 1 );
BOOST_TEST_EQ( (int)(mp_at_c<D, 0>::value), (int)X3::E::v1 );
BOOST_TEST_CSTR_EQ( (mp_at_c<D, 0>::name), "v1" );
}
{
using D = boost::describe::describe_enumerators<X4::E2>;
BOOST_TEST_EQ( mp_size<D>::value, 2 );
BOOST_TEST_EQ( (int)(mp_at_c<D, 0>::value), 0 );
BOOST_TEST_CSTR_EQ( (mp_at_c<D, 0>::name), "v1" );
BOOST_TEST_EQ( (int)(mp_at_c<D, 1>::value), 1 );
BOOST_TEST_CSTR_EQ( (mp_at_c<D, 1>::name), "v2" );
}
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX14)
#endif // !defined(BOOST_DESCRIBE_CXX11)

View File

@@ -0,0 +1,24 @@
// Copyright 2025 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/enumerators.hpp>
#include <boost/describe/enum.hpp>
#include <boost/config.hpp>
#include <boost/config/pragma_message.hpp>
#if !defined(BOOST_DESCRIBE_CXX20)
BOOST_PRAGMA_MESSAGE("Skipping test because BOOST_DESCRIBE_CXX20 isn't defined")
#else
struct X
{
enum E { v1 };
BOOST_DESCRIBE_NESTED_ENUM(E, v1)
using L = boost::describe::describe_enumerators<E>;
};
#endif

93
test/operator_eq_test.cpp Normal file
View File

@@ -0,0 +1,93 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/operators.hpp>
#include <boost/describe/class.hpp>
#include <boost/core/lightweight_test.hpp>
#if !defined(BOOST_DESCRIBE_CXX14)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
int main() {}
#else
namespace app
{
struct X
{
void f() const {}
static void g() {}
};
BOOST_DESCRIBE_STRUCT(X, (), (f, g))
using boost::describe::operators::operator==;
using boost::describe::operators::operator<<;
struct Y
{
int a = 1;
};
BOOST_DESCRIBE_STRUCT(Y, (), (a))
using boost::describe::operators::operator==;
using boost::describe::operators::operator!=;
using boost::describe::operators::operator<<;
struct Z: X, Y
{
int b = 4;
};
BOOST_DESCRIBE_STRUCT(Z, (X, Y), (b))
using boost::describe::operators::operator==;
using boost::describe::operators::operator!=;
using boost::describe::operators::operator<<;
} // namespace app
int main()
{
using app::X;
{
X x1, x2;
BOOST_TEST_EQ( x1, x2 );
}
using app::Y;
{
Y y1, y2, y3;
y3.a = 2;
BOOST_TEST_EQ( y1, y2 );
BOOST_TEST_NE( y1, y3 );
}
using app::Z;
{
Z z1, z2, z3, z4;
z3.a = 2;
z4.b = 3;
BOOST_TEST_EQ( z1, z2 );
BOOST_TEST_NE( z1, z3 );
BOOST_TEST_NE( z1, z4 );
BOOST_TEST_NE( z3, z4 );
}
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX14)

101
test/operator_lt_test.cpp Normal file
View File

@@ -0,0 +1,101 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/operators.hpp>
#include <boost/describe/class.hpp>
#include <boost/core/lightweight_test.hpp>
#if !defined(BOOST_DESCRIBE_CXX14)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
int main() {}
#else
namespace app
{
struct X
{
void f() const {}
static void g() {}
};
BOOST_DESCRIBE_STRUCT(X, (), (f, g))
using boost::describe::operators::operator<=;
using boost::describe::operators::operator>=;
using boost::describe::operators::operator<<;
struct Y
{
int a = 1;
};
BOOST_DESCRIBE_STRUCT(Y, (), (a))
using boost::describe::operators::operator<;
using boost::describe::operators::operator>;
using boost::describe::operators::operator<=;
using boost::describe::operators::operator>=;
using boost::describe::operators::operator<<;
struct Z: X, Y
{
int b = 4;
};
BOOST_DESCRIBE_STRUCT(Z, (X, Y), (b))
using boost::describe::operators::operator<;
using boost::describe::operators::operator>;
using boost::describe::operators::operator<=;
using boost::describe::operators::operator>=;
using boost::describe::operators::operator<<;
} // namespace app
#define TEST_EQ(x, y) BOOST_TEST_LE(x, y); BOOST_TEST_GE(x, y); BOOST_TEST_NOT((x) < (y)); BOOST_TEST_NOT((x) > (y))
#define TEST_LT(x, y) BOOST_TEST_LT(x, y); BOOST_TEST_LE(x, y); BOOST_TEST_GT(y, x); BOOST_TEST_GE(y, x)
int main()
{
using app::X;
{
X x1, x2;
TEST_EQ( x1, x2 );
}
using app::Y;
{
Y y1, y2, y3;
y3.a = 2;
TEST_EQ( y1, y2 );
TEST_LT( y1, y3 );
}
using app::Z;
{
Z z1, z2, z3, z4;
z3.a = 2;
z4.b = 3;
TEST_EQ( z1, z2 );
TEST_LT( z1, z3 );
TEST_LT( z4, z1 );
TEST_LT( z4, z3 );
}
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX14)

82
test/overloaded_test.cpp Normal file
View File

@@ -0,0 +1,82 @@
// Copyright 2020 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/members.hpp>
#include <boost/describe/class.hpp>
#include <boost/core/lightweight_test.hpp>
struct X
{
int f() { return 1; }
int f() const { return 2; }
static int f( int x ) { return x; }
static int f( int x, int y ) { return x + y; }
};
BOOST_DESCRIBE_STRUCT(X, (), (
(int ()) f,
(int () const) f,
(int (int)) f,
(int (int, int)) f
))
#if !defined(BOOST_DESCRIBE_CXX14)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
int main() {}
#else
#include <boost/mp11.hpp>
int main()
{
using namespace boost::describe;
using namespace boost::mp11;
{
using L = describe_members<X, mod_any_access | mod_function>;
BOOST_TEST_EQ( mp_size<L>::value, 2 );
using D1 = mp_at_c<L, 0>;
using D2 = mp_at_c<L, 1>;
X x;
BOOST_TEST_EQ( (x.*D1::pointer)(), 1 );
BOOST_TEST_CSTR_EQ( D1::name, "f" );
BOOST_TEST_EQ( D1::modifiers, mod_public | mod_function );
BOOST_TEST_EQ( (x.*D2::pointer)(), 2 );
BOOST_TEST_CSTR_EQ( D2::name, "f" );
BOOST_TEST_EQ( D2::modifiers, mod_public | mod_function );
}
{
using L = describe_members<X, mod_any_access | mod_static | mod_function>;
BOOST_TEST_EQ( mp_size<L>::value, 2 );
using D1 = mp_at_c<L, 0>;
using D1 = mp_at_c<L, 0>;
using D2 = mp_at_c<L, 1>;
BOOST_TEST_EQ( (*D1::pointer)( 3 ), 3 );
BOOST_TEST_CSTR_EQ( D1::name, "f" );
BOOST_TEST_EQ( D1::modifiers, mod_public | mod_static | mod_function );
BOOST_TEST_EQ( (*D2::pointer)( 4, 5 ), 9 );
BOOST_TEST_CSTR_EQ( D2::name, "f" );
BOOST_TEST_EQ( D2::modifiers, mod_public | mod_static | mod_function );
}
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX14)

74
test/overloaded_test2.cpp Normal file
View File

@@ -0,0 +1,74 @@
// Copyright 2020 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/members.hpp>
#include <boost/describe/class.hpp>
#include <boost/core/lightweight_test.hpp>
#include <utility>
class X
{
private:
std::pair<int, int> p_;
public:
std::pair<int, int>& f() { return p_; }
std::pair<int, int> const& f() const { return p_; }
BOOST_DESCRIBE_CLASS(X, (), ((std::pair<int, int>& ()) f, (std::pair<int, int> const& () const) f), (), (p_))
};
#if !defined(BOOST_DESCRIBE_CXX14)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
int main() {}
#else
#include <boost/mp11.hpp>
int main()
{
using namespace boost::describe;
using namespace boost::mp11;
{
using L1 = describe_members<X, mod_any_access>;
BOOST_TEST_EQ( mp_size<L1>::value, 1 );
using D1 = mp_at_c<L1, 0>;
BOOST_TEST_CSTR_EQ( D1::name, "p_" );
BOOST_TEST_EQ( D1::modifiers, mod_private );
X x;
auto& p = x.*D1::pointer;
using L2 = describe_members<X, mod_any_access | mod_function>;
BOOST_TEST_EQ( mp_size<L2>::value, 2 );
using D2 = mp_at_c<L2, 0>;
using D3 = mp_at_c<L2, 1>;
BOOST_TEST_EQ( &(x.*D2::pointer)(), &p );
BOOST_TEST_CSTR_EQ( D2::name, "f" );
BOOST_TEST_EQ( D2::modifiers, mod_public | mod_function );
BOOST_TEST_EQ( &(x.*D3::pointer)(), &p );
BOOST_TEST_CSTR_EQ( D3::name, "f" );
BOOST_TEST_EQ( D3::modifiers, mod_public | mod_function );
}
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX14)

View File

@@ -0,0 +1,19 @@
// Copyright 2022 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/bases.hpp>
#include <boost/core/lightweight_test_trait.hpp>
struct X {};
int main()
{
#if defined(BOOST_DESCRIBE_CXX11)
BOOST_TEST_TRAIT_FALSE((boost::describe::has_describe_bases<X>));
#endif
return boost::report_errors();
}

View File

@@ -0,0 +1,19 @@
// Copyright 2022 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/enumerators.hpp>
#include <boost/core/lightweight_test_trait.hpp>
enum E {};
int main()
{
#if defined(BOOST_DESCRIBE_CXX11)
BOOST_TEST_TRAIT_FALSE((boost::describe::has_describe_enumerators<E>));
#endif
return boost::report_errors();
}

View File

@@ -0,0 +1,19 @@
// Copyright 2022 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/members.hpp>
#include <boost/core/lightweight_test_trait.hpp>
struct X {};
int main()
{
#if defined(BOOST_DESCRIBE_CXX11)
BOOST_TEST_TRAIT_FALSE((boost::describe::has_describe_members<X>));
#endif
return boost::report_errors();
}

43
test/pp_call_test.cpp Normal file
View File

@@ -0,0 +1,43 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/detail/pp_utilities.hpp>
#include <boost/describe/detail/config.hpp>
#include <boost/core/lightweight_test.hpp>
#if !defined(BOOST_DESCRIBE_CXX11)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++11 is not available")
int main() {}
#else
#define S(x) S2(x)
#define S2(x) S3(x)
#define S3(x) #x
#define F(a, x) (a, x)
#if defined(_MSC_VER)
# pragma warning(disable: 4003) // not enough arguments for macro invocation
#endif
char const * s1 = S(BOOST_DESCRIBE_PP_CALL(F, a, x));
char const * s2 = "" S(BOOST_DESCRIBE_PP_CALL(F, a, ));
char const * s3 = S(BOOST_DESCRIBE_PP_CALL(F, a, () x));
char const * s4 = S(BOOST_DESCRIBE_PP_CALL(F, a, (b, c) x));
int main()
{
BOOST_TEST_CSTR_EQ( s1, "(a, x)" );
BOOST_TEST_CSTR_EQ( s2, "" );
BOOST_TEST_CSTR_EQ( s3, "(a, () x)" );
BOOST_TEST_CSTR_EQ( s4, "(a, (b, c) x)" );
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX11)

View File

@@ -70,6 +70,19 @@ char const * s49 = BOOST_DESCRIBE_PP_FOR_EACH(F1, ~, a, b, c, d, e, f, g, h, i,
char const * s50 = BOOST_DESCRIBE_PP_FOR_EACH(F1, ~, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X);
char const * s51 = BOOST_DESCRIBE_PP_FOR_EACH(F1, ~, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y);
char const * s52 = BOOST_DESCRIBE_PP_FOR_EACH(F1, ~, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z);
char const * s53 = BOOST_DESCRIBE_PP_FOR_EACH(F1, ~, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, 1);
char const * s54 = BOOST_DESCRIBE_PP_FOR_EACH(F1, ~, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, 1, 2);
char const * s55 = BOOST_DESCRIBE_PP_FOR_EACH(F1, ~, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, 1, 2, 3);
char const * s56 = BOOST_DESCRIBE_PP_FOR_EACH(F1, ~, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, 1, 2, 3, 4);
char const * s57 = BOOST_DESCRIBE_PP_FOR_EACH(F1, ~, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, 1, 2, 3, 4, 5);
char const * s58 = BOOST_DESCRIBE_PP_FOR_EACH(F1, ~, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, 1, 2, 3, 4, 5, 6);
char const * s59 = BOOST_DESCRIBE_PP_FOR_EACH(F1, ~, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, 1, 2, 3, 4, 5, 6, 7);
char const * s60 = BOOST_DESCRIBE_PP_FOR_EACH(F1, ~, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, 1, 2, 3, 4, 5, 6, 7, 8);
char const * s61 = BOOST_DESCRIBE_PP_FOR_EACH(F1, ~, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, 1, 2, 3, 4, 5, 6, 7, 8, 9);
char const * s62 = BOOST_DESCRIBE_PP_FOR_EACH(F1, ~, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0);
char const * s63 = BOOST_DESCRIBE_PP_FOR_EACH(F1, ~, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, @);
char const * s64 = BOOST_DESCRIBE_PP_FOR_EACH(F1, ~, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, @, _);
int main()
{
@@ -126,6 +139,18 @@ int main()
BOOST_TEST_CSTR_EQ( s50, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWX" );
BOOST_TEST_CSTR_EQ( s51, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXY" );
BOOST_TEST_CSTR_EQ( s52, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" );
BOOST_TEST_CSTR_EQ( s53, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1" );
BOOST_TEST_CSTR_EQ( s54, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12" );
BOOST_TEST_CSTR_EQ( s55, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123" );
BOOST_TEST_CSTR_EQ( s56, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234" );
BOOST_TEST_CSTR_EQ( s57, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345" );
BOOST_TEST_CSTR_EQ( s58, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456" );
BOOST_TEST_CSTR_EQ( s59, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567" );
BOOST_TEST_CSTR_EQ( s60, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345678" );
BOOST_TEST_CSTR_EQ( s61, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789" );
BOOST_TEST_CSTR_EQ( s62, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890" );
BOOST_TEST_CSTR_EQ( s63, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890@" );
BOOST_TEST_CSTR_EQ( s64, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890@_" );
return boost::report_errors();
}

40
test/pp_is_empty_test.cpp Normal file
View File

@@ -0,0 +1,40 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/detail/pp_utilities.hpp>
#include <boost/describe/detail/config.hpp>
#include <boost/core/lightweight_test.hpp>
#if !defined(BOOST_DESCRIBE_CXX11)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++11 is not available")
int main() {}
#else
#define S(x) S2(x)
#define S2(x) #x
#if defined(_MSC_VER)
# pragma warning(disable: 4003) // not enough arguments for macro invocation
#endif
char const * s1 = S(BOOST_DESCRIBE_PP_IS_EMPTY());
char const * s2 = S(BOOST_DESCRIBE_PP_IS_EMPTY(x));
char const * s3 = S(BOOST_DESCRIBE_PP_IS_EMPTY(() x));
char const * s4 = S(BOOST_DESCRIBE_PP_IS_EMPTY((a, b) x));
int main()
{
BOOST_TEST_CSTR_EQ( s1, "1" );
BOOST_TEST_CSTR_EQ( s2, "0" );
BOOST_TEST_CSTR_EQ( s3, "0" );
BOOST_TEST_CSTR_EQ( s4, "0" );
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX11)

41
test/pp_is_paren_test.cpp Normal file
View File

@@ -0,0 +1,41 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/detail/pp_utilities.hpp>
#include <boost/describe/detail/config.hpp>
#include <boost/core/lightweight_test.hpp>
#if !defined(BOOST_DESCRIBE_CXX11)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++11 is not available")
int main() {}
#else
#define S(x) S2(x)
#define S2(x) S3(x)
#define S3(x) #x
#if defined(_MSC_VER)
# pragma warning(disable: 4003) // not enough arguments for macro invocation
#endif
char const * s1 = S(BOOST_DESCRIBE_PP_IS_PAREN());
char const * s2 = S(BOOST_DESCRIBE_PP_IS_PAREN(x));
char const * s3 = S(BOOST_DESCRIBE_PP_IS_PAREN(() x));
char const * s4 = S(BOOST_DESCRIBE_PP_IS_PAREN((a, b) x));
int main()
{
BOOST_TEST_CSTR_EQ( s1, "0" );
BOOST_TEST_CSTR_EQ( s2, "0" );
BOOST_TEST_CSTR_EQ( s3, "1" );
BOOST_TEST_CSTR_EQ( s4, "1" );
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX11)

33
test/pp_name_test.cpp Normal file
View File

@@ -0,0 +1,33 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/detail/pp_utilities.hpp>
#include <boost/describe/detail/config.hpp>
#include <boost/core/lightweight_test.hpp>
#if !defined(BOOST_DESCRIBE_CXX11)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++11 is not available")
int main() {}
#else
char const * s1 = BOOST_DESCRIBE_PP_NAME(x);
char const * s2 = BOOST_DESCRIBE_PP_NAME(() y);
char const * s3 = BOOST_DESCRIBE_PP_NAME((a) z);
char const * s4 = BOOST_DESCRIBE_PP_NAME((a, b) w);
int main()
{
BOOST_TEST_CSTR_EQ( s1, "x" );
BOOST_TEST_CSTR_EQ( s2, "y" );
BOOST_TEST_CSTR_EQ( s3, "z" );
BOOST_TEST_CSTR_EQ( s4, "w" );
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX11)

37
test/pp_parse_test.cpp Normal file
View File

@@ -0,0 +1,37 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/detail/pp_utilities.hpp>
#include <boost/describe/detail/config.hpp>
#include <boost/core/lightweight_test.hpp>
#if !defined(BOOST_DESCRIBE_CXX11)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++11 is not available")
int main() {}
#else
#define S(x) S2(x)
#define S2(x) S3(x)
#define S3(x) #x
char const * s1 = S((BOOST_DESCRIBE_PP_PARSE(x)));
char const * s2 = S((BOOST_DESCRIBE_PP_PARSE(() y)));
char const * s3 = S((BOOST_DESCRIBE_PP_PARSE((a) z)));
char const * s4 = S((BOOST_DESCRIBE_PP_PARSE((a, b) w)));
int main()
{
BOOST_TEST_CSTR_EQ( s1, "(0, ~, x)" );
BOOST_TEST_CSTR_EQ( s2, "(1, (), y)" );
BOOST_TEST_CSTR_EQ( s3, "(1, (a), z)" );
BOOST_TEST_CSTR_EQ( s4, "(1, (a, b), w)" );
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX11)

40
test/pp_pointer_test.cpp Normal file
View File

@@ -0,0 +1,40 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/detail/pp_utilities.hpp>
#include <boost/describe/detail/config.hpp>
#include <boost/core/lightweight_test.hpp>
#if !defined(BOOST_DESCRIBE_CXX11)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++11 is not available")
int main() {}
#else
#define S(x) S2(x)
#define S2(x) S3(x)
#define S3(x) S4(x)
#define S4(x) #x
char const * s1 = S(BOOST_DESCRIBE_PP_POINTER(C1, x));
char const * s2 = S((BOOST_DESCRIBE_PP_POINTER(C2, (R ()) y)));
char const * s3 = S((BOOST_DESCRIBE_PP_POINTER(C3, (R () const) z)));
char const * s4 = S((BOOST_DESCRIBE_PP_POINTER(C4, (R (A1)) v)));
char const * s5 = S((BOOST_DESCRIBE_PP_POINTER(C5, (R (A1, A2) const &&) w)));
int main()
{
BOOST_TEST_CSTR_EQ( s1, "&C1::x" );
BOOST_TEST_CSTR_EQ( s2, "(::boost::describe::detail::mfn<C2, R ()>(&C2::y))" );
BOOST_TEST_CSTR_EQ( s3, "(::boost::describe::detail::mfn<C3, R () const>(&C3::z))" );
BOOST_TEST_CSTR_EQ( s4, "(::boost::describe::detail::mfn<C4, R (A1)>(&C4::v))" );
BOOST_TEST_CSTR_EQ( s5, "(::boost::describe::detail::mfn<C5, R (A1, A2) const &&>(&C5::w))" );
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX11)

16
test/struct_enum_fail.cpp Normal file
View File

@@ -0,0 +1,16 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/enum.hpp>
#if !defined(BOOST_DESCRIBE_CXX14)
#error "Skipping test because C++14 is not available"
#else
struct X {};
BOOST_DESCRIBE_ENUM(X)
#endif // !defined(BOOST_DESCRIBE_CXX14)

76
test/test_d_type.cpp Normal file
View File

@@ -0,0 +1,76 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/enum.hpp>
#include <boost/describe/class.hpp>
namespace N1
{
enum D
{
d
};
BOOST_DESCRIBE_ENUM(D, d)
}
namespace N2
{
enum E
{
D
};
BOOST_DESCRIBE_ENUM(E, D)
}
namespace N3
{
struct D
{
int d;
};
BOOST_DESCRIBE_STRUCT(D, (), (d))
}
namespace N4
{
struct E
{
int D;
};
BOOST_DESCRIBE_STRUCT(E, (), (D))
}
namespace N5
{
class D
{
int d;
BOOST_DESCRIBE_CLASS(D, (), (), (), (d))
};
}
namespace N6
{
struct D {};
struct E: D {};
BOOST_DESCRIBE_STRUCT(E, (D), ())
}
namespace N7
{
struct D {};
class E: D
{
int d;
BOOST_DESCRIBE_CLASS(E, (D), (), (), (d))
};
}
int main()
{
}

View File

@@ -0,0 +1,45 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/enumerators.hpp>
#include <boost/describe/enum.hpp>
#include <boost/core/lightweight_test.hpp>
#if defined(_MSC_VER)
# pragma warning(disable: 4003) // not enough arguments for macro invocation
#endif
enum E1 { a1, b1, c1, };
BOOST_DESCRIBE_ENUM(E1, a1, b1, c1, )
BOOST_DEFINE_ENUM(E2, a2, b2, c2, )
#if !defined(BOOST_DESCRIBE_CXX14)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
int main() {}
#else
#include <boost/mp11.hpp>
using namespace boost::mp11;
int main()
{
{
using D1 = boost::describe::describe_enumerators<E1>;
BOOST_TEST_EQ( mp_size<D1>::value, 3 );
}
{
using D2 = boost::describe::describe_enumerators<E2>;
BOOST_TEST_EQ( mp_size<D2>::value, 3 );
}
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX14)

79
test/union_test.cpp Normal file
View File

@@ -0,0 +1,79 @@
// Copyright 2020, 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/members.hpp>
#include <boost/describe/class.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/config/pragma_message.hpp>
#if !defined(BOOST_DESCRIBE_CXX11)
BOOST_PRAGMA_MESSAGE("Skipping test because C++11 is not available")
int main() {}
#elif defined(__GNUC__) && __GNUC__ < 5
BOOST_PRAGMA_MESSAGE("Skipping test because g++ 4.8")
int main() {}
#else
union A
{
int m1;
static int m2;
int f1() const { return m1; }
static int f2() { return m2; }
};
BOOST_DESCRIBE_STRUCT(A, (), (m1, m2, f1, f2))
int A::m2;
#if !defined(BOOST_DESCRIBE_CXX14)
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
int main() {}
#else
#include <boost/mp11.hpp>
int main()
{
using namespace boost::describe;
using namespace boost::mp11;
{
using L = describe_members<A, mod_any_access | mod_any_member>;
BOOST_TEST_EQ( mp_size<L>::value, 4 );
using D1 = mp_at_c<L, 0>;
using D2 = mp_at_c<L, 1>;
using D3 = mp_at_c<L, 2>;
using D4 = mp_at_c<L, 3>;
BOOST_TEST( D1::pointer == &A::m1 );
BOOST_TEST_CSTR_EQ( D1::name, "m1" );
BOOST_TEST_EQ( D1::modifiers, mod_public );
BOOST_TEST( D2::pointer == &A::m2 );
BOOST_TEST_CSTR_EQ( D2::name, "m2" );
BOOST_TEST_EQ( D2::modifiers, mod_public | mod_static );
BOOST_TEST( D3::pointer == &A::f1 );
BOOST_TEST_CSTR_EQ( D3::name, "f1" );
BOOST_TEST_EQ( D3::modifiers, mod_public | mod_function );
BOOST_TEST( D4::pointer == &A::f2 );
BOOST_TEST_CSTR_EQ( D4::name, "f2" );
BOOST_TEST_EQ( D4::modifiers, mod_public | mod_static | mod_function );
}
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX14)
#endif // !defined(BOOST_DESCRIBE_CXX11)

153
test/union_test2.cpp Normal file
View File

@@ -0,0 +1,153 @@
// Copyright 2020, 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/members.hpp>
#include <boost/describe/class.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/config/pragma_message.hpp>
#if !defined(BOOST_DESCRIBE_CXX11)
BOOST_PRAGMA_MESSAGE("Skipping test because C++11 is not available")
int main() {}
#elif defined(__GNUC__) && __GNUC__ < 5
BOOST_PRAGMA_MESSAGE("Skipping test because g++ 4.8")
int main() {}
#else
union A
{
public:
int m1;
static int m2;
int f1() const { return m1; }
static int f2() { return m2; }
protected:
int m3;
static int m4;
int f3() const { return m3; }
static int f4() { return m4; }
private:
int m5;
static int m6;
int f5() const { return m5; }
static int f6() { return m6; }
BOOST_DESCRIBE_CLASS(A, (), (m1, m2, f1, f2), (m3, m4, f3, f4), (m5, m6, f5, f6))
friend int main();
};
int A::m2;
int A::m4;
int A::m6;
#if !defined(BOOST_DESCRIBE_CXX14)
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
int main() {}
#else
#include <boost/mp11.hpp>
int main()
{
using namespace boost::describe;
using namespace boost::mp11;
{
using L = describe_members<A, mod_public | mod_any_member>;
BOOST_TEST_EQ( mp_size<L>::value, 4 );
using D1 = mp_at_c<L, 0>;
using D2 = mp_at_c<L, 1>;
using D3 = mp_at_c<L, 2>;
using D4 = mp_at_c<L, 3>;
BOOST_TEST( D1::pointer == &A::m1 );
BOOST_TEST_CSTR_EQ( D1::name, "m1" );
BOOST_TEST_EQ( D1::modifiers, mod_public );
BOOST_TEST( D2::pointer == &A::m2 );
BOOST_TEST_CSTR_EQ( D2::name, "m2" );
BOOST_TEST_EQ( D2::modifiers, mod_public | mod_static );
BOOST_TEST( D3::pointer == &A::f1 );
BOOST_TEST_CSTR_EQ( D3::name, "f1" );
BOOST_TEST_EQ( D3::modifiers, mod_public | mod_function );
BOOST_TEST( D4::pointer == &A::f2 );
BOOST_TEST_CSTR_EQ( D4::name, "f2" );
BOOST_TEST_EQ( D4::modifiers, mod_public | mod_static | mod_function );
}
{
using L = describe_members<A, mod_protected | mod_any_member>;
BOOST_TEST_EQ( mp_size<L>::value, 4 );
using D1 = mp_at_c<L, 0>;
using D2 = mp_at_c<L, 1>;
using D3 = mp_at_c<L, 2>;
using D4 = mp_at_c<L, 3>;
BOOST_TEST( D1::pointer == &A::m3 );
BOOST_TEST_CSTR_EQ( D1::name, "m3" );
BOOST_TEST_EQ( D1::modifiers, mod_protected );
BOOST_TEST( D2::pointer == &A::m4 );
BOOST_TEST_CSTR_EQ( D2::name, "m4" );
BOOST_TEST_EQ( D2::modifiers, mod_protected | mod_static );
BOOST_TEST( D3::pointer == &A::f3 );
BOOST_TEST_CSTR_EQ( D3::name, "f3" );
BOOST_TEST_EQ( D3::modifiers, mod_protected | mod_function );
BOOST_TEST( D4::pointer == &A::f4 );
BOOST_TEST_CSTR_EQ( D4::name, "f4" );
BOOST_TEST_EQ( D4::modifiers, mod_protected | mod_static | mod_function );
}
{
using L = describe_members<A, mod_private | mod_any_member>;
BOOST_TEST_EQ( mp_size<L>::value, 4 );
using D1 = mp_at_c<L, 0>;
using D2 = mp_at_c<L, 1>;
using D3 = mp_at_c<L, 2>;
using D4 = mp_at_c<L, 3>;
BOOST_TEST( D1::pointer == &A::m5 );
BOOST_TEST_CSTR_EQ( D1::name, "m5" );
BOOST_TEST_EQ( D1::modifiers, mod_private );
BOOST_TEST( D2::pointer == &A::m6 );
BOOST_TEST_CSTR_EQ( D2::name, "m6" );
BOOST_TEST_EQ( D2::modifiers, mod_private | mod_static );
BOOST_TEST( D3::pointer == &A::f5 );
BOOST_TEST_CSTR_EQ( D3::name, "f5" );
BOOST_TEST_EQ( D3::modifiers, mod_private | mod_function );
BOOST_TEST( D4::pointer == &A::f6 );
BOOST_TEST_CSTR_EQ( D4::name, "f6" );
BOOST_TEST_EQ( D4::modifiers, mod_private | mod_static | mod_function );
}
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX14)
#endif // !defined(BOOST_DESCRIBE_CXX11)

Some files were not shown because too many files have changed in this diff Show More