Skip to content

Commit

Permalink
Merge pull request #8 from fix8mt/dev
Browse files Browse the repository at this point in the history
Dev to main pre1.0g
  • Loading branch information
dakka authored Jul 2, 2024
2 parents fa9cb13 + 743c418 commit 1def7bf
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 60 deletions.
53 changes: 28 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,7 @@ unlocked the potential of `constexpr` algorithms and concepts. This translates t
- ***Modern C++20***: Entirely `constexpr` for compile-time safety, efficiency and performance
- ***Broad Support***: Works with:
- scoped and unscoped enums
- enum **aliases**
- **gaps**
- enums with **aliases** and **gaps**
- anonymous and named namespaced enums and types
- ***Simple & Easy to Use***: Class-based approach with intuitive syntax
- ***Convenient***: `enum_bitset` provides an enhanced enum aware `std::bitset` (see 3 above)
Expand All @@ -92,7 +91,7 @@ unlocked the potential of `constexpr` algorithms and concepts. This translates t
- Clang
- MSVC
- XCode/Apple Clang
- ***Confidence in Quality***: Includes comprehensive unit tests for reliable functionality
- ***Confidence in Quality***: Includes comprehensive unit test suite for reliable functionality
- ***Expanded***: Enhanced API:
- `add_scope`
- `remove_scope`
Expand Down Expand Up @@ -719,10 +718,9 @@ static consteval const char* FIX8::conjure_enum<T>::tpeek() [with T = component]
# 4. API and Examples using `enum_bitset`
`enum_bitset` is a convenient way of creating bitsets based on `std::bitset`. It uses your enum (scoped or unscoped)
for the bit positions (and names).
> [!NOTE]
> Your enum should be continuous. The last value must be less than the count of enumerations.
We decided on this restriction for both simplicity and practicality - bitsets only really make sense when represented in this manner.
> [!WARNING]
> Your enum _must_ be continuous. The last value must be less than the count of enumerations.
> We decided on this restriction for both simplicity and practicality - bitsets only really make sense when represented in this manner.
## a) Creating an `enum_bitset`
```c++
Expand All @@ -739,6 +737,7 @@ constexpr enum_bitset(I... comp);
```
You can use the enum values directly in your constructor. _No_ need to `|` them - this is assumed. Just supply them comma separated:
```c++
enum class numbers { zero, one, two, three, four, five, six, seven, eight, nine };
enum_bitset<numbers> b(numbers::zero, numbers::one, numbers::two, numbers::three);
std::cout << b << '\n';
```
Expand Down Expand Up @@ -782,7 +781,7 @@ _output_
0000001111
```
A typical use of the above is for parsing configuration bitsets. Here you can tell the constructor to throw an `std::invalid_argument`
if a substring is invalid:
if a substring is invalid by specifying `false` for `ignore_errors`:
```c++
try
{
Expand All @@ -803,17 +802,17 @@ All of the standard operators are supported. Assignment operators return a `enum

| Operator | Description |
| :--- | :--- |
| `<<=` | right shift assign |
| `>>=` | left shift assign |
| `&=` | `and` assign |
| `\|=` | `or` shift assign |
| `^=` | `xor` shift assign |
| `&` | binary AND |
| `\|` | binary OR |
| `^` | binary XOR |
| `~` | binary NOT (ones' complement)|
| `<<` | left shift |
| `>>` | right shift |
| `&` | `and` |
| `\|` | `or` |
| `^` | `xor` |
| `~` | `not` |
| `<<=` | left shift assign |
| `>>=` | right shift assign |
| `&=` | AND assign |
| `\|=` | OR assign |
| `^=` | XOR assign |

Operators work with enum values or integers:
```c++
Expand All @@ -836,15 +835,15 @@ All of the standard accessors and mutators are supported.
| `test` | test for bit(s)|
| `set` | set all or 1 bit, optionally set to off|
| `reset` | reset bits(s)|
| `flip` | flip bits(s)|
| `flip` | flip bits(s) (ones' complement)|
| `to_ulong` | convert to `unsigned long` |
| `to_ullong` | convert to `unsigned long long` |
| `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 |
| `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 |
Expand All @@ -857,6 +856,7 @@ Additional methods
| `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.
You can also review the unit test cases for examples of use.
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:
Expand Down Expand Up @@ -1109,6 +1109,7 @@ target_include_directories(myproj PRIVATE ${conjure_enum_SOURCE_DIR}/include)
Raise an [issue](https://github.com/fix8mt/conjure_enum/issues) on the github page.
The executable `srcloctest` should be built when you build the package by default. This application
does not use any of the `conjure_enum` library and is designed to report on how your compiler handles `std::source_location`.
The actual output is implementation dependent. See [Results of `source_location`](reference/source_location.md) for implementation specific `std::source_location` results.
You should attach the output of this application with your issue.
> [!TIP]
> Passing the switch `-m` causes `srcloctest` to generate github markdown which you can paste directly into the issue.
Expand Down Expand Up @@ -1151,12 +1152,12 @@ static const char *conjure_type<Foo>::tpeek() [T = Foo]
static const char *conjure_type<Namespace::Namespace_Foo>::tpeek() [T = Namespace::Namespace_Foo]
static const char *conjure_type<(anonymous namespace)::Anon_Foo>::tpeek() [T = (anonymous namespace)::Anon_Foo]

## 8. other types
8. other types
static const char *conjure_type<int>::tpeek() [T = int]
static const char *conjure_type<std::basic_string_view<char>>::tpeek() [T = std::basic_string_view<char>]
static const char *conjure_type<std::vector<std::tuple<int, char, std::basic_string_view<char>>>>::tpeek() [T = std::vector<std::tuple<int, char, std::basic_string_view<char>>>]

## 9. edge enum types
9. edge enum types
static const char *conjure_type<(anonymous namespace)::NineEnums>::tpeek() [T = (anonymous namespace)::NineEnums]
static const char *conjure_type<(anonymous namespace)::NineEnums1>::tpeek() [T = (anonymous namespace)::NineEnums1]
static const char *conjure_type<TEST::NineEnums>::tpeek() [T = TEST::NineEnums]
Expand Down Expand Up @@ -1357,8 +1358,10 @@ It can be observed that there is only _one_ copy of the scoped enum value string
| :--- | :--- | :--- | ---: |
| clang | `16`, `17`, `18`| Compiler reports integers outside valid range [x,y]| specify underlying type when declaring enum eg. `enum class foo : int` |

[^1]:&copy; 2024 Fix8 Market Technologies Pty Ltd, David L. Dight.
[^2]:&copy; 2019 - 2024 Daniil Goncharov
[^1]: &copy; 2024 Fix8 Market Technologies Pty Ltd, David L. Dight.
Logo by [Adrian An](mailto:adrian.an[at]mac.com).
[^2]: &copy; 2019 - 2024 Daniil Goncharov

#
<p align="center">
<a href="https://www.fix8mt.com"><img src="assets/fix8mt_Master_Logo_Green_Trans.png" width="120"></a>
Expand Down
9 changes: 4 additions & 5 deletions examples/srcloctest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
//----------------------------------------------------------------------------------------
#include <iostream>
#include <array>
#include <map>
#include <vector>
#include <cctype>
#include <tuple>
Expand Down Expand Up @@ -151,12 +152,10 @@ int main(int argc, char **argv)
};

bool mkd{}, cpl{true}, hlp{};
auto opts { std::to_array<std::tuple<std::string_view, bool&>>({{"-m",mkd},{"-c",cpl},{"-h",hlp}}) };
std::map<std::string_view, bool&> opts { {"-m",mkd},{"-c",cpl},{"-h",hlp} };
for (int ii{1}; ii < argc; ++ii)
for (const auto& pp : opts)
if (std::string_view(argv[ii]) == std::get<std::string_view>(pp))
std::get<bool&>(pp) ^= true;

if (auto result{opts.find(std::string_view(argv[ii]))}; result != opts.cend())
result->second ^= true;
if (hlp)
{
std::cout << "Usage: " << argv[0] << " [-cmh]" << R"(
Expand Down
52 changes: 25 additions & 27 deletions include/fix8/conjure_enum.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,26 @@ class fixed_string final
friend std::ostream& operator<<(std::ostream& os, const fixed_string& what) noexcept { return os << what.get(); }
};

//-----------------------------------------------------------------------------------------
class static_only
{
protected:
static_only() = delete;
#if defined _MSC_VER
~static_only() = default; // warning C4624
#else
~static_only() = delete;
#endif
static_only(const static_only&) = delete;
static_only& operator=(const static_only&) = delete;
static_only(static_only&&) = delete;
static_only& operator=(static_only&&) = delete;
};

//-----------------------------------------------------------------------------------------
// compiler specifics
//-----------------------------------------------------------------------------------------
class cs
class cs : public static_only
{
static constexpr auto _specifics
{
Expand All @@ -106,13 +122,6 @@ class cs
};

public:
cs() = delete;
~cs() = delete;
cs(const cs&) = delete;
cs& operator=(const cs&) = delete;
cs(cs&&) = delete;
cs& operator=(cs&&) = delete;

enum class stype { enum_t, type_t, extype_t0, extype_t1, extype_t2, extype_t3 };
enum class sval { start, end, anon_str, anon_start };

Expand Down Expand Up @@ -142,19 +151,12 @@ concept valid_enum = requires(T)

//-----------------------------------------------------------------------------------------
template<valid_enum T>
class conjure_enum
class conjure_enum : public static_only
{
static constexpr int enum_min_value{ENUM_MIN_VALUE}, enum_max_value{ENUM_MAX_VALUE};
static_assert(enum_max_value > enum_min_value, "ENUM_MAX_VALUE must be greater than ENUM_MIN_VALUE");

public:
conjure_enum() = delete;
~conjure_enum() = delete;
conjure_enum(const conjure_enum&) = delete;
conjure_enum& operator=(const conjure_enum&) = delete;
conjure_enum(conjure_enum&&) = delete;
conjure_enum& operator=(conjure_enum&&) = delete;

using enum_tuple = std::tuple<T, std::string_view>;
using scoped_tuple = std::tuple<std::string_view, std::string_view>;

Expand Down Expand Up @@ -461,9 +463,12 @@ class conjure_enum
requires std::invocable<Fn&&, T, Args...>
[[maybe_unused]] static constexpr auto for_each_n(int n, Fn&& func, Args&&... args) noexcept
{
const auto mnv { std::min(static_cast<int>(count()), n) };
for (int ii{}; ii < mnv; ++ii)
std::invoke(std::forward<Fn>(func), values[ii], std::forward<Args>(args)...);
for (int ii{}; const auto ev : conjure_enum<T>::values)
{
if (ii++ >= n)
break;
std::invoke(std::forward<Fn>(func), ev, std::forward<Args>(args)...);
}
return std::bind(std::forward<Fn>(func), std::placeholders::_1, std::forward<Args>(args)...);
}

Expand Down Expand Up @@ -766,7 +771,7 @@ constexpr enum_bitset<T> operator^(const enum_bitset<T>& lh, const enum_bitset<T
//-----------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------
template<typename T>
class conjure_type
class conjure_type : public static_only
{
static constexpr std::string_view _get_name() noexcept
{
Expand Down Expand Up @@ -808,13 +813,6 @@ class conjure_type
#endif

public:
conjure_type() = delete;
~conjure_type() = delete;
conjure_type(const conjure_type&) = delete;
conjure_type& operator=(const conjure_type&) = delete;
conjure_type(conjure_type&&) = delete;
conjure_type& operator=(conjure_type&&) = delete;

static consteval const char *tpeek() noexcept { return std::source_location::current().function_name(); }
static constexpr auto name
{
Expand Down
3 changes: 1 addition & 2 deletions utests/edgetests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,7 @@ namespace test::rsp::gd
namespace test::util
{
template <typename E>
[[nodiscard]]
constexpr size_t countOf() { return FIX8::conjure_enum<E>::count(); }
[[nodiscard]] constexpr size_t countOf() { return FIX8::conjure_enum<E>::count(); }
}

//-----------------------------------------------------------------------------------------
Expand Down
4 changes: 3 additions & 1 deletion utests/unittests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,10 @@ TEST_CASE("iterators")
REQUIRE(cnt == conjure_enum<component>::count());
REQUIRE(std::get<component>(conjure_enum<component>::back()) == component::fragment);
REQUIRE(std::get<component>(conjure_enum<component>::front()) == component::scheme);
REQUIRE(std::get<component>(conjure_enum<component>::front()) == component::scheme);
REQUIRE(std::get<component>(conjure_enum<component>::back()) == std::get<component>(*conjure_enum<component>::crbegin()));
REQUIRE(std::get<component1>(conjure_enum<component1>::front()) == scheme);
REQUIRE(std::get<component1>(conjure_enum<component1>::back()) == fragment);
REQUIRE(std::get<component1>(conjure_enum<component1>::back()) == std::get<component1>(*conjure_enum<component1>::crbegin()));
}

//-----------------------------------------------------------------------------------------
Expand Down

0 comments on commit 1def7bf

Please sign in to comment.