From 3db9e156824a73c7c44b66a2875337b198562657 Mon Sep 17 00:00:00 2001
From: David Dight
Date: Thu, 20 Jun 2024 09:03:28 +1000
Subject: [PATCH 01/12] updated
---
README.md | 26 ++++++++++++++++++++++++--
1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index d5a03e91..0f243a59 100644
--- a/README.md
+++ b/README.md
@@ -414,7 +414,7 @@ _output_
true
false
```
-## n) `for_each`
+## n) `for_each`, `for_each_n`
```c++
template
requires std::invocable
@@ -423,9 +423,18 @@ requires std::invocable
template // specialisation for member function with object
requires std::invocable
[[maybe_unused]] static constexpr auto for_each(Fn&& func, C *obj, Args&&... args);
+
+template
+requires std::invocable
+[[maybe_unused]] static constexpr auto for_each_n(int n, Fn&& func, Args&&... args);
+
+template // specialisation for member function with object
+requires std::invocable
+[[maybe_unused]] static constexpr auto for_each_n(int n, Fn&& func, C *obj, Args&&... args);
```
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`).
-Optionally provide any additional parameters. Works with lambdas, member functions, functions etc. The second version is intended to be used
+Optionally provide any additional parameters. Works with lambdas, member functions, functions etc. You can limit the number of calls to your
+invokable 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
when using a member function - the _second_ parameter passed by your call must be the `this` pointer of the object.
If you wish to pass a `reference` parameter, you must wrap it in `std::ref`.
@@ -452,6 +461,19 @@ _output_
13 10
14 10
```
+Above example using `for_each_n`, limiting to 3:
+```c++
+conjure_enum::for_each_n(3, [](component val, int other)
+{
+ std::cout << static_cast(val) << ' ' << other << '\n';
+}, 10);
+```
+_output_
+```CSV
+0 10
+1 10
+2 10
+```
Example using returned object and additional reference parameter:
```c++
int total{};
From 833a8665c859a7148232be213102344e88ccb87f Mon Sep 17 00:00:00 2001
From: David Dight
Date: Thu, 20 Jun 2024 12:21:42 +1000
Subject: [PATCH 02/12] updated
---
README.md | 24 ++++++++++++++++++++++--
1 file changed, 22 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 0f243a59..b4560d4b 100644
--- a/README.md
+++ b/README.md
@@ -97,6 +97,7 @@ unlocked the potential of `constexpr` algorithms and concepts. This translates t
- `add_scope`
- `remove_scope`
- `unscoped_string_to_enum`
+ - `for_each_n`
- iterators and more!
- ***Transparency***: Compiler implementation variability fully documented, verifiable and reportable (see 9 above)
@@ -909,7 +910,7 @@ _output_
0001001010
---+--+-+-
```
-### iii. `for_each`
+### iii. `for_each`, `for_each_n`
```c++
template
requires std::invocable
@@ -918,9 +919,18 @@ requires std::invocable
template // specialisation for member function with object
requires std::invocable
[[maybe_unused]] constexpr auto for_each(Fn&& func, C *obj, Args&&... args);
+
+template
+requires std::invocable
+[[maybe_unused]] constexpr auto for_each_n(int n, Fn&& func, Args&&... args);
+
+template // specialisation for member function with object
+requires std::invocable
+[[maybe_unused]] constexpr auto for_each_n(int n, Fn&& func, C *obj, Args&&... args);
```
Call supplied invocable for _each bit that is on_. Similar to `std::for_each` except first parameter of your invocable must accept an enum value (passed by `for_each`).
-Optionally provide any additional parameters. Works with lambdas, member functions, functions etc. The second version is intended to be used
+Optionally provide any additional parameters. Works with lambdas, member functions, functions etc. You can limit the number of calls to your
+invokable 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
when using a member function - the _second_ parameter passed by your call must be the `this` pointer of the object.
If you wish to pass a `reference` parameter, you must wrap it in `std::ref`.
@@ -949,6 +959,16 @@ numbers::two
numbers::five
numbers::nine
```
+Above example using `for_each_n`, limiting to 3:
+```c++
+ec.for_each_n(3, &foo::printer, &bar, std::ref(std::cout));
+```
+_output_
+```CSV
+numbers::zero
+numbers::two
+numbers::five
+```
---
# 5. API and Examples using `conjure_type`
From 32d97432f58cdf5514991991bba96269c2cb8083 Mon Sep 17 00:00:00 2001
From: David Dight
Date: Thu, 20 Jun 2024 12:43:07 +1000
Subject: [PATCH 03/12] pre-rel 1.0c
---
examples/example.cpp | 2 ++
include/fix8/conjure_enum.hpp | 46 ++++++++++++++++++++++++++++++++++
utests/unittests.cpp | 47 +++++++++++++++++++++++++++++++++++
3 files changed, 95 insertions(+)
diff --git a/examples/example.cpp b/examples/example.cpp
index f091990c..53775a8d 100644
--- a/examples/example.cpp
+++ b/examples/example.cpp
@@ -73,6 +73,7 @@ const std::string demangle() noexcept
int main(void)
{
+ conjure_enum::for_each_n(3, [](component val, int other) { std::cout << static_cast(val) << ' ' << other << '\n'; }, 200);
int total{};
auto myfunc { conjure_enum::for_each([](component val, int other, int& tot)
{
@@ -195,6 +196,7 @@ int main(void)
}
};
const foo bar;
+ conjure_enum::for_each_n(3, &foo::printer, &bar, 1000);
ek.for_each(std::bind(&foo::printer, &bar, std::placeholders::_1, 10));
ek.for_each(&foo::printer, &bar, 10);
[[maybe_unused]] enum_bitset er("one|three|four|eight"sv, true);
diff --git a/include/fix8/conjure_enum.hpp b/include/fix8/conjure_enum.hpp
index 10240cfd..edab6c96 100644
--- a/include/fix8/conjure_enum.hpp
+++ b/include/fix8/conjure_enum.hpp
@@ -458,6 +458,28 @@ class conjure_enum
return for_each(std::bind(std::forward(func), obj, std::placeholders::_1, std::forward(args)...));
}
+ template
+ requires std::invocable
+ [[maybe_unused]] static constexpr auto for_each_n(int n, Fn&& func, Args&&... args) noexcept
+ {
+ for (int ii{}; const auto ev : values)
+ {
+ if (ii++ < n)
+ std::invoke(std::forward(func), ev, std::forward(args)...);
+ else
+ break;
+ }
+ return std::bind(std::forward(func), std::placeholders::_1, std::forward(args)...);
+ }
+
+ // specialisation for member function with object
+ template
+ requires std::invocable
+ [[maybe_unused]] static constexpr auto for_each_n(int n, Fn&& func, C *obj, Args&&... args) noexcept
+ {
+ return for_each_n(n, std::bind(std::forward(func), obj, std::placeholders::_1, std::forward(args)...));
+ }
+
// public constexpr data structures
static constexpr auto values { _values() };
static constexpr auto entries { _entries(std::make_index_sequence()) };
@@ -655,6 +677,30 @@ class enum_bitset
return for_each(std::bind(std::forward(func), obj, std::placeholders::_1, std::forward(args)...));
}
+ template
+ requires std::invocable
+ [[maybe_unused]] constexpr auto for_each_n(int n, Fn&& func, Args&&... args) noexcept
+ {
+ for (int ii{}; const auto ev : conjure_enum::values)
+ {
+ if (test(ev))
+ {
+ if (ii++ < n)
+ std::invoke(std::forward(func), ev, std::forward(args)...);
+ else
+ break;
+ }
+ }
+ return std::bind(std::forward(func), std::placeholders::_1, std::forward(args)...);
+ }
+
+ template // specialisation for member function with object
+ requires std::invocable
+ [[maybe_unused]] constexpr auto for_each_n(int n, Fn&& func, C *obj, Args&&... args) noexcept
+ {
+ return for_each_n(n, std::bind(std::forward(func), obj, std::placeholders::_1, std::forward(args)...));
+ }
+
/// create a bitset from custom separated enum string
static constexpr U factory(std::string_view src, bool anyscope, char sep, bool ignore_errors)
{
diff --git a/utests/unittests.cpp b/utests/unittests.cpp
index ca3784b7..b450be04 100644
--- a/utests/unittests.cpp
+++ b/utests/unittests.cpp
@@ -326,6 +326,29 @@ TEST_CASE("for_each")
REQUIRE(total == 160);
}
+//-----------------------------------------------------------------------------------------
+TEST_CASE("for_each_n")
+{
+ int total{};
+ conjure_enum::for_each_n(3, [](component val, int& tot)
+ {
+ tot += static_cast(val);
+ }, std::ref(total));
+ REQUIRE(total == 3);
+
+ struct foo
+ {
+ void process(component val, int offset, int& tot)
+ {
+ tot += offset + static_cast(val);
+ }
+ };
+ foo bar;
+ total = 0;
+ conjure_enum::for_each_n(3, &foo::process, &bar, 10, std::ref(total));
+ REQUIRE(total == 33);
+}
+
//-----------------------------------------------------------------------------------------
TEST_CASE("enum_bitset")
{
@@ -424,3 +447,27 @@ numbers::seven(7)
REQUIRE(total == 16);
}
+//-----------------------------------------------------------------------------------------
+TEST_CASE("enum_bitset::for_each_n")
+{
+ enum_bitset ee(0b10101010);
+ std::ostringstream ostr;
+ ee.for_each_n(3, [&ostr](numbers val) noexcept
+ {
+ ostr << conjure_enum::enum_to_string(val) << '(' << static_cast(val) << ')' << '\n';
+ });
+ REQUIRE(ostr.str() ==
+R"(numbers::one(1)
+numbers::three(3)
+numbers::five(5)
+)");
+
+ int total{};
+ enum_bitset enc(numbers::two,numbers::three,numbers::four,numbers::seven);
+ enc.for_each_n(3, [](numbers val, int& tot)
+ {
+ tot += static_cast(val);
+ }, std::ref(total));
+ REQUIRE(total == 9);
+}
+
From dcc04047f15774d694d17d1cecbd758a624cd752 Mon Sep 17 00:00:00 2001
From: David Dight
Date: Thu, 20 Jun 2024 14:33:40 +1000
Subject: [PATCH 04/12] updated
---
README.md | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/README.md b/README.md
index b4560d4b..f0c3ca59 100644
--- a/README.md
+++ b/README.md
@@ -842,14 +842,19 @@ All of the standard accessors and mutators are supported.
| `count` | count of bits on |
| `size` | number of bits in bitset |
| `operator[]` | test bit at position |
+| `any` | return true if any bit is on |
+| `all` | return true if all bits are on |
+| `none` | return true if no bits are on |
Additional methods
| Method | Description |
| :--- | :--- |
| `set_all` | set all specified bits |
| `reset_all` | reset all specified bits |
-| `test_any` | test for one or more bits |
-| `test_all` | test for all specified bits |
+| `any_of` | test for one or more bits |
+| `all_of` | test for all specified bits |
+
+Take a look at the [implementation](include/fix8/conjure_enum.hpp) for more detail on the various API functions available.
All accessors and mutators work with enum values or integers as with operators. They also work with multiple values, either as template parameters or
as variadic arguments:
@@ -857,11 +862,11 @@ as variadic arguments:
enum_bitset eb;
eb.set_all();
std::cout << eb << '\n';
-std::cout << std::boolalpha << eb.test_all() << '\n';
+std::cout << std::boolalpha << eb.all_of() << '\n';
eb.reset();
-std::cout << std::boolalpha << eb.test_all(0, 2, 5, 9) << '\n';
-std::cout << std::boolalpha << eb.test_any(0, 2, 5, 9) << '\n';
-std::cout << std::boolalpha << eb.test_all(numbers::zero,numbers::nine) << '\n';
+std::cout << std::boolalpha << eb.all_of(0, 2, 5, 9) << '\n';
+std::cout << std::boolalpha << eb.any_of(0, 2, 5, 9) << '\n';
+std::cout << std::boolalpha << eb.all_of(numbers::zero,numbers::nine) << '\n';
std::cout << eb << '\n';
eb.reset(numbers::nine)
std::cout << ec << '\n';
From 617258ae180b24e71e1b3ac69c966f1cfd247cf5 Mon Sep 17 00:00:00 2001
From: David Dight
Date: Fri, 21 Jun 2024 11:40:11 +1000
Subject: [PATCH 05/12] updated
---
README.md | 20 +++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)
diff --git a/README.md b/README.md
index f0c3ca59..86172013 100644
--- a/README.md
+++ b/README.md
@@ -32,7 +32,7 @@
-Lightweight header-only C++20 enum and type reflection
+Lightweight header-only C++20 enum and typename reflection
---
@@ -64,7 +64,7 @@
Based on the awesome work in [`magic_enum`](https://github.com/Neargye/magic_enum)[^2] and [`boost::describe`](https://github.com/boostorg/describe),
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,
focusing on the main features developers usually want while enhancing and expanding them for a more efficient and expressive experience. We've also
-added general purpose type reflection for any type.
+added general purpose typename reflection for any type.
## b) Embrace the Future with C++20
@@ -834,7 +834,7 @@ All of the standard accessors and mutators are supported.
| Method | Description |
| :--- | :--- |
| `test` | test for bit(s)|
-| `set` | set bit(s)|
+| `set` | set all or 1 bit, optionally set to off|
| `reset` | reset bits(s)|
| `flip` | flip bits(s)|
| `to_ulong` | convert to `unsigned long` |
@@ -849,10 +849,12 @@ All of the standard accessors and mutators are supported.
Additional methods
| Method | Description |
| :--- | :--- |
-| `set_all` | set all specified bits |
-| `reset_all` | reset all specified bits |
-| `any_of` | test for one or more bits |
-| `all_of` | test for all specified bits |
+| `set` | set all specified bits, templated |
+| `reset` | reset all specified bits, templated |
+| `any_of` | test for one or more bits, templated, function, types and underlyings |
+| `all_of` | test for all specified bits, templated, function, types and underlyings |
+| `none_of` | test for all specified bits set to off, templated, function, types and underlyings |
+| `not_count` | complement of count, count of off bits |
Take a look at the [implementation](include/fix8/conjure_enum.hpp) for more detail on the various API functions available.
@@ -860,7 +862,7 @@ All accessors and mutators work with enum values or integers as with operators.
as variadic arguments:
```c++
enum_bitset eb;
-eb.set_all();
+eb.set();
std::cout << eb << '\n';
std::cout << std::boolalpha << eb.all_of() << '\n';
eb.reset();
@@ -977,7 +979,7 @@ numbers::five
---
# 5. API and Examples using `conjure_type`
-`conjure_type` is a general purpose class allowing you to extract a string representation of any type.
+`conjure_type` is a general purpose class allowing you to extract a string representation of any typename.
The string will be stored statically by the compiler, so you can use the statically generated value `name` to obtain your type.
```c++
template
From c36f2f9874e271126ae16c87e1db60ec395e4f41 Mon Sep 17 00:00:00 2001
From: David Dight
Date: Fri, 21 Jun 2024 11:52:17 +1000
Subject: [PATCH 06/12] updated
---
README.md | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 86172013..a9a84d9d 100644
--- a/README.md
+++ b/README.md
@@ -731,7 +731,7 @@ constexpr enum_bitset(U bits);
constexpr enum_bitset(std::string_view from, bool anyscope=false,
char sep='|', bool ignore_errors=true);
-template
+template
constexpr enum_bitset(E... comp);
template
@@ -1168,6 +1168,10 @@ static const char *conjure_type::tpeek() [T = TEST::TES
$
```
+## e) Contributing
+Contributions are welcome. Make your changes in [your fork on the dev branch](https://github.com/fix8mt/conjure_enum/tree/dev) and open a pull request from there. PRs to
+master will not be accepted.
+
---
# 7. Notes
## a) enum limits
From 35c9df6347a9d5a64ba0a8d1b2091da3893f0490 Mon Sep 17 00:00:00 2001
From: David Dight
Date: Sat, 22 Jun 2024 12:00:10 +1000
Subject: [PATCH 07/12] updated
---
README.md | 2 +-
SECURITY.md | 8 ++++----
reference/source_location.md | 2 +-
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/README.md b/README.md
index a9a84d9d..c930985d 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@
// by David L. Dight
// see https://github.com/fix8mt/conjure_enum
//
-// Lightweight header-only C++20 enum and type reflection
+// Lightweight header-only C++20 enum and typename reflection
//
// Licensed under the MIT License .
//
diff --git a/SECURITY.md b/SECURITY.md
index 2d7888ea..c0816e9f 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -7,7 +7,7 @@
// by David L. Dight
// see https://github.com/fix8mt/conjure_enum
//
-// Lightweight header-only C++20 enum and type reflection
+// Lightweight header-only C++20 enum and typename reflection
//
// Licensed under the MIT License .
//
@@ -30,18 +30,18 @@
//---------------------------------------------------------------------------------------->
# Security Policy
Security Policy
-This document outlines the security policy for the conjure_enum project. Here, we detail how to report vulnerabilities and how we handle them.
+This document outlines the security policy for the `conjure_enum` project. Here, we detail how to report vulnerabilities and how we handle them.
## Reporting a Vulnerability
-If you discover a potential security vulnerability in conjure_enum, we encourage you to report it responsibly. Here's how:
+If you discover a potential security vulnerability in `conjure_enum`, we encourage you to report it responsibly. Here's how:
- **Privately Contact Us:** Please file a [detailed report](https://github.com/fix8mt/conjure_enum/security/advisories/new).
- **Include Details:** In your email, please provide the following information (if applicable):
- A clear description of the vulnerability.
- Steps to reproduce the vulnerability (if possible).
- The potential impact of the vulnerability.
-We appreciate your cooperation in keeping conjure_enum secure. We will work with you confidentially to address the vulnerability as quickly as possible.
+We appreciate your cooperation in keeping `conjure_enum` secure. We will work with you confidentially to address the vulnerability as quickly as possible.
## Disclosure Process
diff --git a/reference/source_location.md b/reference/source_location.md
index 6aa9a2b0..34eb6ff9 100644
--- a/reference/source_location.md
+++ b/reference/source_location.md
@@ -7,7 +7,7 @@
// by David L. Dight
// see https://github.com/fix8mt/conjure_enum
//
-// Lightweight header-only C++20 enum and type reflection
+// Lightweight header-only C++20 enum and typename reflection
//
// Licensed under the MIT License .
//
From 680b236b5701f9ad48ad15092d15dc845ab29425 Mon Sep 17 00:00:00 2001
From: David Dight
Date: Sat, 22 Jun 2024 12:01:23 +1000
Subject: [PATCH 08/12] pre-rel 1.0d
---
CMakeLists.txt | 8 +-
examples/example.cpp | 14 +--
examples/srcloctest.cpp | 2 +-
examples/statictest.cpp | 2 +-
include/fix8/conjure_enum.hpp | 193 ++++++++++++++++++++--------------
utests/edgetests.cpp | 2 +-
utests/unittests.cpp | 31 ++++--
7 files changed, 152 insertions(+), 100 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2b1a060d..55f1f0ff 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,7 +7,7 @@
# by David L. Dight
# see https://github.com/fix8mt/conjure_enum
#
-# Lightweight header-only C++20 enum and type reflection
+# Lightweight header-only C++20 enum and typename reflection
#
# Licensed under the MIT License .
#
@@ -32,7 +32,7 @@ cmake_minimum_required (VERSION 3.20)
project (conjure_enum
LANGUAGES CXX
HOMEPAGE_URL https://github.com/fix8mt/conjure_enum
- DESCRIPTION "Lightweight C++20 enum and type reflection"
+ DESCRIPTION "Lightweight C++20 enum and typename reflection"
VERSION 1.0.0)
# to disable strip:
@@ -52,7 +52,9 @@ message("-- Build unit tests: ${BUILD_UNITTESTS}")
function(build loc x)
add_executable(${x} ${loc}/${x}.cpp)
- add_dependencies(${x} srcloctest) # srcloctest should be built even if errors with conjure_enum
+ if(NOT ${x} STREQUAL srcloctest)
+ add_dependencies(${x} srcloctest) # srcloctest should be built even if errors with conjure_enum
+ endif()
set_target_properties(${x} PROPERTIES CXX_STANDARD 20 CXX_STANDARD_REQUIRED true)
target_include_directories(${x} PRIVATE include)
if(BUILD_ALL_WARNINGS)
diff --git a/examples/example.cpp b/examples/example.cpp
index 53775a8d..9cf0ed2b 100644
--- a/examples/example.cpp
+++ b/examples/example.cpp
@@ -7,7 +7,7 @@
// by David L. Dight
// see https://github.com/fix8mt/conjure_enum
//
-// Lightweight header-only C++20 enum and type reflection
+// Lightweight header-only C++20 enum and typename reflection
//
// Licensed under the MIT License .
//
@@ -84,13 +84,13 @@ int main(void)
std::cout << total << '\n';
enum_bitset eb;
- eb.set_all();
+ eb.set();
std::cout << eb << '\n';
- std::cout << std::boolalpha << eb.test_all() << '\n';
- eb.reset_all();
- std::cout << std::boolalpha << eb.test_all(0, 2, 5, 9) << '\n';
- std::cout << std::boolalpha << eb.test_any(0, 2, 5, 9) << '\n';
- std::cout << std::boolalpha << eb.test_all(numbers::zero,numbers::nine) << '\n';
+ std::cout << std::boolalpha << eb.all_of() << '\n';
+ eb.reset();
+ std::cout << std::boolalpha << eb.all_of(0, 2, 5, 9) << '\n';
+ std::cout << std::boolalpha << eb.any_of(0, 2, 5, 9) << '\n';
+ std::cout << std::boolalpha << eb.all_of(numbers::zero,numbers::nine) << '\n';
std::cout << eb << '\n';
eb.reset(numbers::nine);
std::cout << eb << '\n';
diff --git a/examples/srcloctest.cpp b/examples/srcloctest.cpp
index df63f14c..a72a5196 100644
--- a/examples/srcloctest.cpp
+++ b/examples/srcloctest.cpp
@@ -7,7 +7,7 @@
// by David L. Dight
// see https://github.com/fix8mt/conjure_enum
//
-// Lightweight header-only C++20 enum and type reflection
+// Lightweight header-only C++20 enum and typename reflection
//
// Licensed under the MIT License .
//
diff --git a/examples/statictest.cpp b/examples/statictest.cpp
index f8165ee4..367af156 100644
--- a/examples/statictest.cpp
+++ b/examples/statictest.cpp
@@ -7,7 +7,7 @@
// by David L. Dight
// see https://github.com/fix8mt/conjure_enum
//
-// Lightweight header-only C++20 enum and type reflection
+// Lightweight header-only C++20 enum and typename reflection
//
// Licensed under the MIT License .
//
diff --git a/include/fix8/conjure_enum.hpp b/include/fix8/conjure_enum.hpp
index edab6c96..2b059f47 100644
--- a/include/fix8/conjure_enum.hpp
+++ b/include/fix8/conjure_enum.hpp
@@ -7,7 +7,7 @@
// by David L. Dight
// see https://github.com/fix8mt/conjure_enum
//
-// Lightweight header-only C++20 enum and type reflection
+// Lightweight header-only C++20 enum and typename reflection
//
// Parts based on magic_enum
// Copyright (c) 2019 - 2024 Daniil Goncharov .
@@ -179,7 +179,7 @@ class conjure_enum
static constexpr auto _unscoped_entries(std::index_sequence) noexcept
{
std::array tmp{{{ values[I], _remove_scope(_enum_name_v)}...}};
- std::sort(tmp.begin(), tmp.end(), tuple_comp_rev);
+ std::sort(tmp.begin(), tmp.end(), _tuple_comp_rev);
return tmp;
}
@@ -194,7 +194,7 @@ class conjure_enum
static constexpr auto _scoped_entries(std::index_sequence) noexcept
{
std::array tmp{{{ _remove_scope(_enum_name_v), _enum_name_v}...}};
- std::sort(tmp.begin(), tmp.end(), scoped_comp);
+ std::sort(tmp.begin(), tmp.end(), _scoped_comp);
return tmp;
}
@@ -202,14 +202,14 @@ class conjure_enum
static constexpr auto _rev_scoped_entries(std::index_sequence) noexcept
{
std::array tmp{{{ _enum_name_v, _remove_scope(_enum_name_v)}...}};
- std::sort(tmp.begin(), tmp.end(), scoped_comp);
+ std::sort(tmp.begin(), tmp.end(), _scoped_comp);
return tmp;
}
static constexpr auto _sorted_entries() noexcept
{
auto tmp { entries };
- std::sort(tmp.begin(), tmp.end(), tuple_comp_rev);
+ std::sort(tmp.begin(), tmp.end(), _tuple_comp_rev);
return tmp;
}
@@ -296,23 +296,48 @@ class conjure_enum
return {};
}
- static constexpr bool value_comp(const T& pl, const T& pr) noexcept
+ static constexpr std::string_view _process_scope(const auto& entr, std::string_view what) noexcept
+ {
+ if constexpr (is_scoped())
+ if (const auto result { std::equal_range(entr.cbegin(),
+ entr.cend(), scoped_tuple(what, std::string_view()), _scoped_comp) };
+ result.first != result.second)
+ return std::get<1>(*result.first);
+ return what;
+ }
+
+ /// comparators
+ static constexpr bool _value_comp(const T& pl, const T& pr) noexcept
{
return static_cast(pl) < static_cast(pr);
}
- static constexpr bool tuple_comp(const enum_tuple& pl, const enum_tuple& pr) noexcept
+ static constexpr bool _tuple_comp(const enum_tuple& pl, const enum_tuple& pr) noexcept
{
return static_cast(std::get(pl)) < static_cast(std::get(pr));
}
- static constexpr bool tuple_comp_rev(const enum_tuple& pl, const enum_tuple& pr) noexcept
+ static constexpr bool _tuple_comp_rev(const enum_tuple& pl, const enum_tuple& pr) noexcept
{
return std::get(pl) < std::get(pr);
}
- static constexpr bool scoped_comp(const scoped_tuple& pl, const scoped_tuple& pr) noexcept
+ static constexpr bool _scoped_comp(const scoped_tuple& pl, const scoped_tuple& pr) noexcept
{
return std::get<0>(pl) < std::get<0>(pr);
}
+ /// for_each base
+ template
+ [[maybe_unused]] static constexpr auto _for_each_n(int n, Fn&& func, Args&&... args) noexcept
+ {
+ for (int ii{}; const auto ev : values)
+ {
+ if (ii++ < n)
+ std::invoke(std::forward(func), ev, std::forward(args)...);
+ else
+ break;
+ }
+ return std::bind(std::forward(func), std::placeholders::_1, std::forward(args)...);
+ }
+
public:
static consteval const char *tpeek() noexcept { return std::source_location::current().function_name(); }
@@ -361,22 +386,12 @@ class conjure_enum
static constexpr std::string_view remove_scope(std::string_view what) noexcept
{
- if constexpr (is_scoped())
- if (const auto result { std::equal_range(rev_scoped_entries.cbegin(),
- rev_scoped_entries.cend(), scoped_tuple(what, std::string_view()), scoped_comp) };
- result.first != result.second)
- return std::get<1>(*result.first);
- return what;
+ return _process_scope(rev_scoped_entries, what);
}
static constexpr std::string_view add_scope(std::string_view what) noexcept
{
- if constexpr (is_scoped())
- if (const auto result { std::equal_range(scoped_entries.cbegin(),
- scoped_entries.cend(), scoped_tuple(what, std::string_view()), scoped_comp) };
- result.first != result.second)
- return std::get<1>(*result.first);
- return what;
+ return _process_scope(scoped_entries, what);
}
static constexpr bool has_scope(std::string_view what) noexcept
@@ -404,54 +419,52 @@ class conjure_enum
}
static constexpr std::optional int_to_enum(int value) noexcept
{
- if (const auto result { std::equal_range(values.cbegin(), values.cend(), static_cast(value), value_comp) };
+ if (const auto result { std::equal_range(values.cbegin(), values.cend(), static_cast(value), _value_comp) };
result.first != result.second)
return *result.first;
return {};
}
static constexpr bool contains(T value) noexcept
{
- const auto result { std::equal_range(values.cbegin(), values.cend(), value, value_comp) };
+ const auto result { std::equal_range(values.cbegin(), values.cend(), value, _value_comp) };
return result.first != result.second;
}
static constexpr bool contains(std::string_view str) noexcept
{
- const auto result { std::equal_range(sorted_entries.cbegin(), sorted_entries.cend(), enum_tuple(T{}, str), tuple_comp_rev) };
+ const auto result { std::equal_range(sorted_entries.cbegin(), sorted_entries.cend(), enum_tuple(T{}, str), _tuple_comp_rev) };
return result.first != result.second;
}
static constexpr std::string_view enum_to_string(T value, bool noscope=false) noexcept
{
- if (const auto result { std::equal_range(entries.cbegin(), entries.cend(), enum_tuple(value, std::string_view()), tuple_comp) };
+ if (const auto result { std::equal_range(entries.cbegin(), entries.cend(), enum_tuple(value, std::string_view()), _tuple_comp) };
result.first != result.second)
return noscope ? remove_scope(std::get(*result.first)) : std::get(*result.first);
return {};
}
static constexpr std::optional string_to_enum(std::string_view str) noexcept
{
- if (const auto result { std::equal_range(sorted_entries.cbegin(), sorted_entries.cend(), enum_tuple(T{}, str), tuple_comp_rev) };
+ if (const auto result { std::equal_range(sorted_entries.cbegin(), sorted_entries.cend(), enum_tuple(T{}, str), _tuple_comp_rev) };
result.first != result.second)
return std::get(*result.first);
return {};
}
static constexpr std::optional unscoped_string_to_enum(std::string_view str) noexcept
{
- if (const auto result { std::equal_range(unscoped_entries.cbegin(), unscoped_entries.cend(), enum_tuple(T{}, str), tuple_comp_rev) };
+ if (const auto result { std::equal_range(unscoped_entries.cbegin(), unscoped_entries.cend(), enum_tuple(T{}, str), _tuple_comp_rev) };
result.first != result.second)
return std::get(*result.first);
return {};
}
+ /// for_each, for_each_n
template
requires std::invocable
[[maybe_unused]] static constexpr auto for_each(Fn&& func, Args&&... args) noexcept
{
- for (const auto ev : values)
- std::invoke(std::forward(func), ev, std::forward(args)...);
- return std::bind(std::forward(func), std::placeholders::_1, std::forward(args)...);
+ return _for_each_n(count(), std::forward(func), std::forward(args)...);
}
- // specialisation for member function with object
- template
+ template // specialisation for member function with object
requires std::invocable
[[maybe_unused]] static constexpr auto for_each(Fn&& func, C *obj, Args&&... args) noexcept
{
@@ -462,18 +475,10 @@ class conjure_enum
requires std::invocable
[[maybe_unused]] static constexpr auto for_each_n(int n, Fn&& func, Args&&... args) noexcept
{
- for (int ii{}; const auto ev : values)
- {
- if (ii++ < n)
- std::invoke(std::forward(func), ev, std::forward(args)...);
- else
- break;
- }
- return std::bind(std::forward(func), std::placeholders::_1, std::forward(args)...);
+ return _for_each_n(n, std::forward(func), std::forward(args)...);
}
- // specialisation for member function with object
- template
+ template // specialisation for member function with object
requires std::invocable
[[maybe_unused]] static constexpr auto for_each_n(int n, Fn&& func, C *obj, Args&&... args) noexcept
{
@@ -540,6 +545,23 @@ class enum_bitset
static constexpr U all_bits { (1 << countof) - 1 };
U _present{};
+ /// for_each base
+ template
+ [[maybe_unused]] constexpr auto _for_each_n(int n, Fn&& func, Args&&... args) noexcept
+ {
+ for (int ii{}; const auto ev : conjure_enum::values)
+ {
+ if (test(ev))
+ {
+ if (ii++ < n)
+ std::invoke(std::forward(func), ev, std::forward(args)...);
+ else
+ break;
+ }
+ }
+ return std::bind(std::forward(func), std::placeholders::_1, std::forward(args)...);
+ }
+
public:
explicit constexpr enum_bitset(U bits) noexcept : _present(bits) {}
constexpr enum_bitset(std::string_view from, bool anyscope=false, char sep='|', bool ignore_errors=true)
@@ -556,6 +578,7 @@ class enum_bitset
constexpr std::size_t count() const noexcept
{ return std::popcount(static_cast>(_present)); } // C++23: upgrade to std::bitset when count is constexpr
+ constexpr std::size_t not_count() const noexcept { return countof - count(); }
constexpr std::size_t size() const noexcept { return countof; }
constexpr U to_ulong() const noexcept { return _present; }
constexpr unsigned long long to_ullong() const noexcept { return _present; }
@@ -563,34 +586,39 @@ class enum_bitset
constexpr bool operator[](std::size_t pos) const noexcept { return test(pos); }
constexpr bool operator[](T what) const noexcept { return test(what); }
- constexpr void set(U pos) noexcept { _present |= (1 << pos); }
- constexpr void set(T what) noexcept { set(to_underlying(what)); }
+ /// set
+ constexpr void set(U pos, bool value=true) noexcept { value ? _present |= 1 << pos : _present &= ~(1 << pos); }
+ constexpr void set(T what, bool value=true) noexcept { set(to_underlying(what), value); }
constexpr void set() noexcept { _present = all_bits; }
template
constexpr void set() noexcept
{
if constexpr (constexpr auto uu{to_underlying()}; uu < countof)
- _present |= (1 << uu);
+ _present |= 1 << uu;
}
template
- constexpr void set_all() noexcept { (set(),...); }
+ requires (sizeof...(comp) > 1)
+ constexpr void set() noexcept { (set(),...); }
template
- constexpr void set_all(E... comp) noexcept { return (... | (set(comp))); }
+ requires (sizeof...(E) > 1)
+ constexpr void set(E... comp) noexcept { return (... | (set(comp))); }
+ /// flip
template
constexpr void flip() noexcept
{
if constexpr (constexpr auto uu{to_underlying()}; uu < countof)
- _present ^= (1 << uu);
+ _present ^= 1 << uu;
}
constexpr void flip() noexcept { _present = ~_present & all_bits; }
- constexpr void flip(U pos) noexcept { _present ^= (1 << pos); }
+ constexpr void flip(U pos) noexcept { _present ^= 1 << pos; }
constexpr void flip(T what) noexcept { flip(to_underlying(what)); }
+ /// reset
template
constexpr void reset() noexcept
{
@@ -603,12 +631,14 @@ class enum_bitset
constexpr void reset(T what) noexcept { reset(to_underlying(what)); }
template
- constexpr void reset_all() noexcept { (reset(),...); }
+ requires (sizeof...(comp) > 1)
+ constexpr void reset() noexcept { (reset(),...); }
template
- constexpr void reset_all(I...comp) noexcept { (reset(comp),...); }
+ constexpr void reset(I...comp) noexcept { (reset(comp),...); }
- constexpr bool test(U pos) const noexcept { return _present & (1 << pos); }
+ /// test
+ constexpr bool test(U pos) const noexcept { return _present & 1 << pos; }
constexpr bool test(T what) const noexcept { return test(to_underlying(what)); }
constexpr bool test() const noexcept { return _present; }
@@ -622,52 +652,63 @@ class enum_bitset
}
template
- constexpr bool test_any() const noexcept { return (... || test()); }
+ constexpr bool any_of() const noexcept { return (... || test()); }
+
+ template
+ constexpr bool any_of(I...comp) const noexcept { return (... || test(comp)); }
+
+ template
+ constexpr bool any_of(E...comp) const noexcept { return (... || test(comp)); }
+
+ template
+ constexpr bool all_of() const noexcept { return (... && test()); }
template
- constexpr bool test_any(I...comp) const noexcept { return (... || test(comp)); }
+ constexpr bool all_of(I...comp) const noexcept { return (... && test(comp)); }
template
- constexpr bool test_any(E...comp) const noexcept { return (... || test(comp)); }
+ constexpr bool all_of(E...comp) const noexcept { return (... && test(comp)); }
template
- constexpr bool test_all() const noexcept { return (... && test()); }
+ constexpr bool none_of() const noexcept { return (... && !test()); }
template
- constexpr bool test_all(I...comp) const noexcept { return (... && test(comp)); }
+ constexpr bool none_of(I...comp) const noexcept { return (... && !test(comp)); }
template
- constexpr bool test_all(E...comp) const noexcept { return (... && test(comp)); }
+ constexpr bool none_of(E...comp) const noexcept { return (... && !test(comp)); }
+ constexpr bool any() const noexcept { return count(); }
+ constexpr bool all() const noexcept { return _present == all_bits; }
+ constexpr bool none() const noexcept { return !*this; }
+
+ /// operators
+ constexpr operator bool() const noexcept { return count(); }
constexpr enum_bitset& operator<<=(std::size_t pos) noexcept { _present <<= pos; return *this; }
constexpr enum_bitset& operator>>=(std::size_t pos) noexcept { _present >>= pos; return *this; }
- constexpr enum_bitset& operator&=(T other) noexcept { _present &= (1 << to_underlying(other)); return *this; }
- constexpr enum_bitset& operator|=(T other) noexcept { _present |= (1 << to_underlying(other)); return *this; }
- constexpr enum_bitset& operator^=(T other) noexcept { _present ^= (1 << to_underlying(other)); return *this; }
+ constexpr enum_bitset& operator&=(T other) noexcept { _present &= 1 << to_underlying(other); return *this; }
+ constexpr enum_bitset& operator|=(T other) noexcept { _present |= 1 << to_underlying(other); return *this; }
+ constexpr enum_bitset& operator^=(T other) noexcept { _present ^= 1 << to_underlying(other); return *this; }
constexpr enum_bitset& operator&=(U other) noexcept { _present &= other; return *this; }
constexpr enum_bitset& operator|=(U other) noexcept { _present |= other; return *this; }
constexpr enum_bitset& operator^=(U other) noexcept { _present ^= other; return *this; }
constexpr enum_bitset operator<<(int pos) const noexcept { return enum_bitset(_present << pos); }
constexpr enum_bitset operator>>(int pos) const noexcept { return enum_bitset(_present >> pos); }
- constexpr enum_bitset operator&(T other) const noexcept { return enum_bitset(_present & (1 << to_underlying(other))); }
- constexpr enum_bitset operator|(T other) const noexcept { return enum_bitset(_present | (1 << to_underlying(other))); }
- constexpr enum_bitset operator^(T other) const noexcept { return enum_bitset(_present ^ (1 << to_underlying(other))); }
+ constexpr enum_bitset operator&(T other) const noexcept { return enum_bitset(_present & 1 << to_underlying(other)); }
+ constexpr enum_bitset operator|(T other) const noexcept { return enum_bitset(_present | 1 << to_underlying(other)); }
+ constexpr enum_bitset operator^(T other) const noexcept { return enum_bitset(_present ^ 1 << to_underlying(other)); }
constexpr enum_bitset operator&(U other) const noexcept { return enum_bitset(_present & other); }
constexpr enum_bitset operator|(U other) const noexcept { return enum_bitset(_present | other); }
constexpr enum_bitset operator^(U other) const noexcept { return enum_bitset(_present ^ other); }
constexpr enum_bitset operator~() const noexcept { return enum_bitset(~_present & all_bits); }
- constexpr operator bool() const noexcept { return count(); }
-
+ /// for_each, for_each_n
template
requires std::invocable
[[maybe_unused]] constexpr auto for_each(Fn&& func, Args&&... args) noexcept
{
- for (const auto ev : conjure_enum::values)
- if (test(ev))
- std::invoke(std::forward(func), ev, std::forward(args)...);
- return std::bind(std::forward(func), std::placeholders::_1, std::forward(args)...);
+ return _for_each_n(countof, std::forward(func), std::forward(args)...);
}
template // specialisation for member function with object
@@ -681,17 +722,7 @@ class enum_bitset
requires std::invocable
[[maybe_unused]] constexpr auto for_each_n(int n, Fn&& func, Args&&... args) noexcept
{
- for (int ii{}; const auto ev : conjure_enum::values)
- {
- if (test(ev))
- {
- if (ii++ < n)
- std::invoke(std::forward(func), ev, std::forward(args)...);
- else
- break;
- }
- }
- return std::bind(std::forward(func), std::placeholders::_1, std::forward(args)...);
+ return _for_each_n(n, std::forward(func), std::forward(args)...);
}
template // specialisation for member function with object
diff --git a/utests/edgetests.cpp b/utests/edgetests.cpp
index c635ce50..479f72bc 100644
--- a/utests/edgetests.cpp
+++ b/utests/edgetests.cpp
@@ -7,7 +7,7 @@
// by David L. Dight
// see https://github.com/fix8mt/conjure_enum
//
-// Lightweight header-only C++20 enum and type reflection
+// Lightweight header-only C++20 enum and typename reflection
//
// Licensed under the MIT License .
//
diff --git a/utests/unittests.cpp b/utests/unittests.cpp
index b450be04..cc0eb188 100644
--- a/utests/unittests.cpp
+++ b/utests/unittests.cpp
@@ -7,7 +7,7 @@
// by David L. Dight
// see https://github.com/fix8mt/conjure_enum
//
-// Lightweight header-only C++20 enum and type reflection
+// Lightweight header-only C++20 enum and typename reflection
//
// Licensed under the MIT License .
//
@@ -353,10 +353,10 @@ TEST_CASE("for_each_n")
TEST_CASE("enum_bitset")
{
enum_bitset eb;
- eb.set_all();
- REQUIRE(eb.test_all());
+ eb.set();
+ REQUIRE(eb.all_of());
eb.reset(); // use alias
- REQUIRE(!eb.test_all());
+ REQUIRE(!eb.all_of());
eb.reset(numbers::nine);
REQUIRE(!eb.test(numbers::nine));
@@ -383,14 +383,15 @@ TEST_CASE("enum_bitset")
REQUIRE(!ec.test());
ec.set(numbers::three);
REQUIRE(ec.test());
+ ec.set(numbers::three, false);
+ REQUIRE(ec.test() == false);
+ REQUIRE(ec.any());
}
//-----------------------------------------------------------------------------------------
TEST_CASE("enum_bitset ops")
{
enum_bitset ed(numbers::two,numbers::three,numbers::four,numbers::seven);
- REQUIRE(ed.test_all());
- REQUIRE(ed.test_any());
REQUIRE((ed << 1).to_ulong() == 0b0100111000);
ed <<= 1;
REQUIRE(ed.to_ulong() == 0b0100111000);
@@ -413,6 +414,24 @@ TEST_CASE("enum_bitset ops")
REQUIRE(ed.to_ulong() == 0b010);
}
+//-----------------------------------------------------------------------------------------
+TEST_CASE("enum_bitset ext ops")
+{
+ enum_bitset ed;
+ REQUIRE(ed.none());
+ ed.set();
+ REQUIRE(ed.all());
+ enum_bitset ee(numbers::one,numbers::two,numbers::three,numbers::four,numbers::five);
+ REQUIRE(ee.all_of());
+ REQUIRE(ee.any_of());
+ int a{static_cast(numbers::two)}, b{static_cast(numbers::three)}, c{static_cast(numbers::four)}, d{static_cast(numbers::five)};
+ REQUIRE(ee.any_of(a,b,c,d));
+ ee.reset();
+ REQUIRE(ee.none_of());
+ REQUIRE(ee.all_of());
+ REQUIRE(ee.not_count() == 10 - 2);
+}
+
//-----------------------------------------------------------------------------------------
TEST_CASE("enum_bitset(std::string_view)")
{
From cefd90bfe973724f96ea50c8528b76707c77ba87 Mon Sep 17 00:00:00 2001
From: David Dight
Date: Sat, 22 Jun 2024 12:04:41 +1000
Subject: [PATCH 09/12] updated
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index c930985d..27ffe111 100644
--- a/README.md
+++ b/README.md
@@ -1170,7 +1170,7 @@ $
## e) Contributing
Contributions are welcome. Make your changes in [your fork on the dev branch](https://github.com/fix8mt/conjure_enum/tree/dev) and open a pull request from there. PRs to
-master will not be accepted.
+master will not be considered.
---
# 7. Notes
From cde3f946778061d3d21fa8abbd8a04cb3c22dc92 Mon Sep 17 00:00:00 2001
From: David Dight
Date: Sat, 22 Jun 2024 12:10:53 +1000
Subject: [PATCH 10/12] pre-rel 1.0d
---
include/fix8/conjure_enum.hpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/include/fix8/conjure_enum.hpp b/include/fix8/conjure_enum.hpp
index 2b059f47..e3ad5cb2 100644
--- a/include/fix8/conjure_enum.hpp
+++ b/include/fix8/conjure_enum.hpp
@@ -296,7 +296,7 @@ class conjure_enum
return {};
}
- static constexpr std::string_view _process_scope(const auto& entr, std::string_view what) noexcept
+ static constexpr std::string_view _process_scope([[maybe_unused]] const auto& entr, std::string_view what) noexcept
{
if constexpr (is_scoped())
if (const auto result { std::equal_range(entr.cbegin(),
@@ -461,7 +461,7 @@ class conjure_enum
requires std::invocable
[[maybe_unused]] static constexpr auto for_each(Fn&& func, Args&&... args) noexcept
{
- return _for_each_n(count(), std::forward(func), std::forward(args)...);
+ return _for_each_n(static_cast(count()), std::forward(func), std::forward(args)...);
}
template // specialisation for member function with object
@@ -708,7 +708,7 @@ class enum_bitset
requires std::invocable
[[maybe_unused]] constexpr auto for_each(Fn&& func, Args&&... args) noexcept
{
- return _for_each_n(countof, std::forward(func), std::forward(args)...);
+ return _for_each_n(static_cast(countof), std::forward(func), std::forward(args)...);
}
template // specialisation for member function with object
From 3041f4edd1904a3d79f57fe742c9da8f6d2a6bf8 Mon Sep 17 00:00:00 2001
From: David Dight
Date: Sat, 22 Jun 2024 12:26:22 +1000
Subject: [PATCH 11/12] pre-rel 1.0d
---
include/fix8/conjure_enum.hpp | 56 +++++++++++++----------------------
1 file changed, 21 insertions(+), 35 deletions(-)
diff --git a/include/fix8/conjure_enum.hpp b/include/fix8/conjure_enum.hpp
index e3ad5cb2..af605b77 100644
--- a/include/fix8/conjure_enum.hpp
+++ b/include/fix8/conjure_enum.hpp
@@ -324,20 +324,6 @@ class conjure_enum
return std::get<0>(pl) < std::get<0>(pr);
}
- /// for_each base
- template
- [[maybe_unused]] static constexpr auto _for_each_n(int n, Fn&& func, Args&&... args) noexcept
- {
- for (int ii{}; const auto ev : values)
- {
- if (ii++ < n)
- std::invoke(std::forward(func), ev, std::forward(args)...);
- else
- break;
- }
- return std::bind(std::forward(func), std::placeholders::_1, std::forward(args)...);
- }
-
public:
static consteval const char *tpeek() noexcept { return std::source_location::current().function_name(); }
@@ -461,7 +447,7 @@ class conjure_enum
requires std::invocable
[[maybe_unused]] static constexpr auto for_each(Fn&& func, Args&&... args) noexcept
{
- return _for_each_n(static_cast(count()), std::forward(func), std::forward(args)...);
+ return for_each_n(static_cast(count()), std::forward(func), std::forward(args)...);
}
template // specialisation for member function with object
@@ -475,7 +461,14 @@ class conjure_enum
requires std::invocable
[[maybe_unused]] static constexpr auto for_each_n(int n, Fn&& func, Args&&... args) noexcept
{
- return _for_each_n(n, std::forward(func), std::forward(args)...);
+ for (int ii{}; const auto ev : values)
+ {
+ if (ii++ < n)
+ std::invoke(std::forward(func), ev, std::forward(args)...);
+ else
+ break;
+ }
+ return std::bind(std::forward(func), std::placeholders::_1, std::forward(args)...);
}
template // specialisation for member function with object
@@ -545,23 +538,6 @@ class enum_bitset
static constexpr U all_bits { (1 << countof) - 1 };
U _present{};
- /// for_each base
- template
- [[maybe_unused]] constexpr auto _for_each_n(int n, Fn&& func, Args&&... args) noexcept
- {
- for (int ii{}; const auto ev : conjure_enum::values)
- {
- if (test(ev))
- {
- if (ii++ < n)
- std::invoke(std::forward(func), ev, std::forward(args)...);
- else
- break;
- }
- }
- return std::bind(std::forward(func), std::placeholders::_1, std::forward(args)...);
- }
-
public:
explicit constexpr enum_bitset(U bits) noexcept : _present(bits) {}
constexpr enum_bitset(std::string_view from, bool anyscope=false, char sep='|', bool ignore_errors=true)
@@ -708,7 +684,7 @@ class enum_bitset
requires std::invocable
[[maybe_unused]] constexpr auto for_each(Fn&& func, Args&&... args) noexcept
{
- return _for_each_n(static_cast(countof), std::forward(func), std::forward(args)...);
+ return for_each_n(static_cast(countof), std::forward(func), std::forward(args)...);
}
template // specialisation for member function with object
@@ -722,7 +698,17 @@ class enum_bitset
requires std::invocable
[[maybe_unused]] constexpr auto for_each_n(int n, Fn&& func, Args&&... args) noexcept
{
- return _for_each_n(n, std::forward(func), std::forward(args)...);
+ for (int ii{}; const auto ev : conjure_enum::values)
+ {
+ if (test(ev))
+ {
+ if (ii++ < n)
+ std::invoke(std::forward(func), ev, std::forward(args)...);
+ else
+ break;
+ }
+ }
+ return std::bind(std::forward(func), std::placeholders::_1, std::forward(args)...);
}
template // specialisation for member function with object
From 194e0c6e6d17a6b7a42612562dc8f2992ed0ddbb Mon Sep 17 00:00:00 2001
From: David Dight
Date: Sat, 22 Jun 2024 12:39:25 +1000
Subject: [PATCH 12/12] pre-rel 1.0d
---
include/fix8/conjure_enum.hpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/include/fix8/conjure_enum.hpp b/include/fix8/conjure_enum.hpp
index af605b77..87c23158 100644
--- a/include/fix8/conjure_enum.hpp
+++ b/include/fix8/conjure_enum.hpp
@@ -518,7 +518,6 @@ namespace ostream_enum_operator
template
concept valid_bitset_enum = valid_enum and requires(T)
{
- requires conjure_enum::count() > 0;
requires static_cast(conjure_enum::values.back()) < conjure_enum::count();
};