You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
## a) Supercharge Your C++ Enums with This Lightweight Reflection Library!
67
67
68
-
Based on the awesome work in [`magic_enum`](https://github.com/Neargye/magic_enum)[^2] and [`boost::describe`](https://github.com/boostorg/describe),
68
+
Based on some of the awesome work in [`magic_enum`](https://github.com/Neargye/magic_enum)[^2] and [`boost::describe`](https://github.com/boostorg/describe),
69
69
this library offers a streamlined and powerful way to add reflection capabilities to your C++ enums and other types. We've optimized the core functionality,
70
70
focusing on the main features developers usually want. We've also added general purpose typename reflection for any type.
template<typename Fn, typename C, typename... Args> // specialisation for member function with object
474
479
requires std::invocable<Fn&&, C, T, Args...>
475
-
[[maybe_unused]] static constexpr auto for_each(Fn&& func, C*obj, Args&&... args);
480
+
[[maybe_unused]] static constexpr auto for_each(Fn&& func, C&& obj, Args&&... args);
476
481
477
482
template<typename Fn, typename... Args>
478
483
requires std::invocable<Fn&&, T, Args...>
479
484
[[maybe_unused]] static constexpr auto for_each_n(int n, Fn&& func, Args&&... args);
480
485
481
486
template<typename Fn, typename C, typename... Args> // specialisation for member function with object
482
487
requires std::invocable<Fn&&, C, T, Args...>
483
-
[[maybe_unused]] static constexpr auto for_each_n(int n, Fn&& func, C*obj, Args&&... args);
488
+
[[maybe_unused]] static constexpr auto for_each_n(int n, Fn&& func, C&& obj, Args&&... args);
484
489
```
485
490
Call supplied invocable for _each_ enum value. Similar to `std::for_each` except the first parameter of your invocable must accept an enum value (passed by `for_each`).
486
491
Optionally provide any additional parameters. You can limit the number of calls to your invocable by using the `for_each_n` version with the first parameter
487
492
being the maximum number to call. The second version of `for_each` and `for_each_n` is intended to be used
488
-
when using a member function - the _second_ parameter passed by your call must be the `this` pointer of the object.
493
+
when using a member function - the _second_ parameter passed by your call must be a pointer or reference to the object.
489
494
If you wish to pass a `reference` parameter, you must wrap it in `std::ref`.
490
495
491
496
Works with lambdas, member functions, functions etc, compatible with `std::invoke`.
template<std::size_t I, typename R, typename Fn, typename C, typename... Args> // specialisation for member function with not found value(nval) for return
588
593
requires std::invocable<Fn&&, C, T, Args...>
589
-
[[maybe_unused]] static constexpr R dispatch(T ev, R nval, const std::array<std::tuple<T, Fn>, I>& disp, C*obj, Args&&... args);
594
+
[[maybe_unused]] static constexpr R dispatch(T ev, R nval, const std::array<std::tuple<T, Fn>, I>& disp, C&& obj, Args&&... args);
590
595
591
596
template<std::size_t I, typename Fn, typename... Args> // void func with not found call to last element
592
597
requires (std::invocable<Fn&&, T, Args...> && I > 0)
With a given enum, search and call user supplied invocable. A typical use case would be where you want to demux a complex event, allowing you to easily declare predefined invocable actions
600
-
for different enum values.
604
+
With a given enum, search and call user supplied invocable. So for example, if you want to demux a complex event predicated on an enum, you can easily declare predefined invocable actions
605
+
for different enum values and then use `dispatch` to test and execute those actions.
601
606
602
607
- Where invocable returns a value, return this value or a user supplied "not found" value.
603
608
- Where invocable is void, call user supplied invocable or "not found" invocable (last in supplied array).
@@ -611,7 +616,7 @@ There are two versions of `dispatch` - the first takes an enum value, a 'not fou
611
616
The second version takes an enum value, and a `std::array` of `std::tuple` of enum and invocable. The last element of the array is called if the enum is not found.
612
617
This version is intended for use with `void` return invocables.
613
618
614
-
The second version of each of the above is intended to be used when using a member function - the _first_ parameter passed after your array must be the `this` pointer of the object.
619
+
The second version of each of the above is intended to be used when using a member function - the _first_ parameter passed after your array must be a pointer or reference to the object.
615
620
You can also use `std::bind` to bind the this pointer and any parameter placeholders when declaring your array.
616
621
If you wish to pass a `reference` parameter, you must wrap it in `std::ref`.
617
622
@@ -620,7 +625,7 @@ If you wish to pass a `reference` parameter, you must wrap it in `std::ref`.
620
625
621
626
> [!IMPORTANT]
622
627
> Your `std::array` of `std::tuple` should be sorted by enum.
623
-
> The `dispatch` method performs a binary search on the array. Complexity for a sorted array is at most  $2log_2(N)+O(1)$  comparisons.
628
+
> The `dispatch` method performs a [binary search](https://en.cppreference.com/w/cpp/algorithm/binary_search) on the array. Complexity for a sorted array is at most  $2log_2(N)+O(1)$  comparisons.
624
629
> If the array is _not_ sorted, complexity is linear.
625
630
626
631
The following example uses a `static constexpr` array of pointers to functions. For brevity they all point to the same function except the last which is
@@ -985,16 +990,16 @@ _output_
985
990
```CSV
986
991
0000001111
987
992
```
988
-
You can use the underlying type as well:
993
+
You can use the underlying type in an initialiser_list as well:
989
994
```c++
990
-
enum_bitset<numbers> b(0,1,2,3);
995
+
enum_bitset<numbers> b({0,1,2,3});
991
996
std::cout << b << '\n';
992
997
```
993
998
_output_
994
999
```CSV
995
1000
0000001111
996
1001
```
997
-
You can use an `int` initialiser too:
1002
+
You can use an `unsigned integer` initialiser too (interpreted as an underlying type):
template<typename C, typename Fn, typename... Args> // specialisation for member function with object
1222
1227
requires std::invocable<Fn&&, C, T, Args...>
1223
-
[[maybe_unused]] constexpr auto for_each(Fn&& func, C*obj, Args&&... args);
1228
+
[[maybe_unused]] constexpr auto for_each(Fn&& func, C&& obj, Args&&... args);
1224
1229
1225
1230
template<typename Fn, typename... Args>
1226
1231
requires std::invocable<Fn&&, T, Args...>
1227
1232
[[maybe_unused]] constexpr auto for_each_n(int n, Fn&& func, Args&&... args);
1228
1233
1229
1234
template<typename C, typename Fn, typename... Args> // specialisation for member function with object
1230
1235
requires std::invocable<Fn&&, C, T, Args...>
1231
-
[[maybe_unused]] constexpr auto for_each_n(int n, Fn&& func, C*obj, Args&&... args);
1236
+
[[maybe_unused]] constexpr auto for_each_n(int n, Fn&& func, C&& obj, Args&&... args);
1232
1237
```
1233
1238
Call supplied invocable for _every bit that is on_. Similar to `std::for_each` except first parameter of your invocable must accept an enum value (passed by `for_each`).
1234
1239
Optionally provide any additional parameters. Works with lambdas, member functions, functions etc. You can limit the number of calls to your
1235
1240
invocable by using the `for_each_n` version with the first parameter being the maximum number to call. The second version of `for_each` and `for_each_n` is intended to be used
1236
-
when using a member function - the _second_ parameter passed by your call must be the `this` pointer of the object.
1241
+
when using a member function - the _second_ parameter passed by your call must be a pointer or reference to the object.
1237
1242
If you wish to pass a `reference` parameter, you must wrap it in `std::ref`.
1238
1243
1239
1244
Returns `std::bind(std::forward<Fn>(func), std::placeholders::_1, std::forward<Args>(args)...)` or
`fixed_string` is a specialisation of `std::array` that provides statics storage for an ASCII zero (asciiz) string. The purpose of this class is to allow the
1430
-
creation of `constexpr` strings with specfic storage, adding a trailing `0`. It is used by `conjure_enum` to store all strings. API is described below.
1434
+
`fixed_string` is a specialisation of `std::array` that provides static storage for an ASCII zero (asciiz) string. The purpose of this class is to allow the
1435
+
creation of `constexpr` strings with specfic storage whilst adding a trailing `0`. It is used by `conjure_enum` to store all strings. API is described below.
1431
1436
1432
1437
## a) Creating a `fixed_string`
1433
1438
```c++
@@ -1505,22 +1510,34 @@ by default.
1505
1510
1506
1511
The package is also available on [vckpg](https://vcpkg.io/en/package/conjure-enum).
1507
1512
1508
-
### ii. Default compiler warnings
1513
+
### ii. Installing
1514
+
To install the headers in your target environment, you can either specify the installation prefix when you first run cmake or set the
1515
+
environment variable `CMAKE_INSTALL_PREFIX`. Omitting the prefix will install to the default target directory for your platform.
@@ -1650,12 +1667,14 @@ The following are the default settings:
1650
1667
These definitions set the minimum and maximum enum values that are supported. You can adjust them to suit your requirements but for most use cases the defaults are sufficient.
1651
1668
> [!TIP]
1652
1669
> You can reduce compile times in some circumstances by narrowing the range of `FIX8_CONJURE_ENUM_MIN_VALUE` and `FIX8_CONJURE_ENUM_MAX_VALUE`. For example
1653
-
> if your enums are only within the range of say `0-16` you can set `FIX8_CONJURE_ENUM_MIN_VALUE` and `FIX8_CONJURE_ENUM_MAX_VALUE` to `0` and `16` respectively. If the range is _too_ narrow
1654
-
> `conjure_enum` will **ignore enum values outside your range**.
1670
+
> if your enums are only within the range of say `0-16` you can set `FIX8_CONJURE_ENUM_MIN_VALUE` and `FIX8_CONJURE_ENUM_MAX_VALUE` to `0` and `16` respectively.
1655
1671
1656
1672
> [!TIP]
1657
1673
> If you wish to set ranges on a per enum basis, use `enum_range` (see below).
1658
1674
1675
+
> [!WARNING]
1676
+
> If the range is _too_ narrow `conjure_enum` will **ignore enum values outside your specified range**.
1677
+
1659
1678
### ii. using `enum_range`
1660
1679
You can specialise thisclassto override the defaults and set your own range on a per enum basis.
1661
1680
```c++
@@ -2047,16 +2066,18 @@ From a compilation performance perspective, `conjure_enum` roughly matches the p
2047
2066
| Compiler | Version(s) | Notes | Unsupported |
2048
2067
| :--- | :--- | :--- | ---: |
2049
2068
|[gcc](https://gcc.gnu.org/projects/cxx-status.html)|`11`, `12`, `13`, `14`|`std::format` not complete in `11`, `12`|`<= 10`|
2050
-
|[clang](https://clang.llvm.org/cxx_status.html)|`15`, `16`, `17`, `18`| Catch2 needs `cxx_std_20` in `15`|`<= 14`|
2051
-
|[msvc](https://learn.microsoft.com/en-us/cpp/overview/visual-cpp-language-conformance)|`16`, `17`| Visual Studio 2019,2022, latest `17.11.3`|`<= 16.9`|
2052
-
|[xcode](https://developer.apple.com/support/xcode/)|`15`| Apple Xcode Clang 15.0.0(LLVM 16), some issues with `constexpr`, workarounds|`<= 14`|
|[msvc](https://learn.microsoft.com/en-us/cpp/overview/visual-cpp-language-conformance)|`16`, `17`| Visual Studio 2019,2022, latest `17.14.3`|`<= 16.9`|
2071
+
|[xcode](https://developer.apple.com/support/xcode/)|`15`, `16`| Apple Xcode Clang `15.0.0`, `16.3.0`(LLVM `16`, `17`), some issues with `constexpr`, workarounds|`<= 14`|
2053
2072
2054
2073
# 11. Compiler issues
2055
2074
| Compiler | Version(s) | Issues | Workaround |
2056
2075
| :--- | :--- | :--- | ---: |
2057
2076
| clang |`16`, `17`, `18`| Compiler reports integers outside valid range [x,y]| specify underlying type when declaring enum eg. `enum class foo : int`|
2077
+
| xcode clang |`17`| Compiler reports `constexpr evaluation hit maximum step limit; possible infinite loop?` error with large enum ranges | use compiler option `-fconstexpr-steps=4194304`|
2078
+
| gcc |`12`, `13`, `14`| Compiler reports warnings with catch2 with `CATCH2_INTERNAL_TEST_*``is partly outside array bounds of ‘CATCH2_INTERNAL_TEST` warnings | can be ignored |
0 commit comments