LCOV - code coverage report
Current view: top level - issm-precice - enums.hpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 23 23
Test Date: 2026-08-10 06:53:29 Functions: 100.0 % 23 23

            Line data    Source code
       1              : #pragma once
       2              : 
       3              : #include "issm-precice/config.hpp"
       4              : 
       5              : #include <compare>
       6              : #include <ostream>
       7              : #include <type_traits>
       8              : #include <utility>
       9              : 
      10              : #include "fmt/format.h"
      11              : 
      12              : namespace ipc
      13              : {
      14              : 
      15              : /**
      16              :  * Traits class that enables an enum type to be used in the typesafe enum flag.
      17              :  * Specialize for your enum and derive from std::true_type.
      18              :  * This enables usage of the enum class as flags using the usual | and & bitwise operators.
      19              :  * Example:
      20              :  * ```
      21              :  * enum class Foo { None = 0, Flag1 = 0B1, Flag2 = 0B10, Flag3 = 0B100, };
      22              :  * template<> struct EnumFlagTraits<Foo> : std::true_type { }
      23              :  * FlagType<Foo> flags = Flag1 | Flag3;
      24              :  * //...
      25              :  * if (flags & Foo::Flag1) { printf("Flag1 is set."); }
      26              :  * ```
      27              :  */
      28              : template<class E>
      29              : struct EnumFlagTraits : std::false_type
      30              : {
      31              : };
      32              : 
      33              : /**
      34              :  * A type safe bitfield based on flags defined by an enum type.
      35              :  * Ensures that only values of the specified enum type are set.
      36              :  * @tparam E an enum type whose members are flags.
      37              :  */
      38              : template<class E>
      39              : struct FlagType
      40              : {
      41              :     static_assert(std::is_enum_v<E>);
      42              : 
      43              :     /**
      44              :      * The combined values of all flags.
      45              :      */
      46           12 :     std::underlying_type_t<E> value;
      47              : 
      48              :     /**
      49              :      * Default constructor.
      50              :      * No flags are set.
      51              :      */
      52            2 :     FlagType() : value(0) { }
      53              : 
      54              :     /**
      55              :      * Constructor from the underlying type of the enum type.
      56              :      */
      57           77 :     explicit FlagType(std::underlying_type_t<E> v) : value(v) { }
      58              :     
      59              :     /**
      60              :      * Constructor to set a single flag.
      61              :      * Implicit conversion from E to FlagType<E>.
      62              :      */
      63           27 :     FlagType(E e) : value(std::underlying_type_t<E>(e)) { }
      64              : 
      65              :     /**
      66              :      * Default comparison operator.
      67              :      * Equal if the same flags are set in both operands.
      68              :      * Can also be used to compare with single flags due to implicit conversion.
      69              :      * @{
      70              :      */
      71           12 :     bool operator==(const FlagType& b) const = default;
      72              :     bool operator!=(const FlagType& b) const = default;
      73              :     /** @} */
      74              : 
      75              :     /**
      76              :      * Check if a specific flag is set.
      77              :      * `if (f.is_set(a))` is equivalent to `if (f & a)`.
      78              :      */
      79            1 :     bool is_set(E e) const { return (*this & e) != 0; }
      80              : 
      81              :     /**
      82              :      * Check if any flag is set.
      83              :      */
      84           44 :     bool any() const { return value != 0; }
      85              : 
      86              :     /**
      87              :      * Check if any flag is set.
      88              :      */
      89           42 :     operator bool() const { return any(); }
      90              : 
      91              :     /**
      92              :      * Form the union of the flags from two bitfields in place.
      93              :      */
      94            2 :     FlagType& operator|=(const FlagType& b) { return (*this = (*this | b)); }
      95              : 
      96              :     /**
      97              :      * Output the underlying flag value.
      98              :      */
      99              :     std::ostream& operator<<(std::ostream& os)
     100              :     {
     101              :         os << E(value);
     102              :         return os;
     103              :     }
     104              : };
     105              : 
     106              : /**
     107              :  * Extension for the fmt library.
     108              :  */
     109              : template<class E, class = std::enable_if_t<EnumFlagTraits<E>::value>>
     110              : auto format_as(FlagType<E> flags)
     111              : {
     112              :     return flags.value;
     113              : }
     114              : 
     115              : /**
     116              :  * Union of two flags.
     117              :  */
     118              : template<class E>
     119           14 : std::enable_if_t<EnumFlagTraits<E>::value, FlagType<E>> operator|(E a, E b)
     120              : {
     121           14 :     return FlagType<E>{std::underlying_type_t<E>(a) | std::underlying_type_t<E>(b)};
     122              : }
     123              : 
     124              : /**
     125              :  * Union of a flag and an exisiting set.
     126              :  * @{
     127              :  */
     128              : template<class E>
     129           10 : std::enable_if_t<EnumFlagTraits<E>::value, FlagType<E>> operator|(FlagType<E> a, E b)
     130              : {
     131           10 :     return FlagType<E>{a.value | std::underlying_type_t<E>(b)};
     132              : }
     133              : template<class E>
     134            1 : std::enable_if_t<EnumFlagTraits<E>::value, FlagType<E>> operator|(E a, FlagType<E> b)
     135              : {
     136            1 :     return FlagType<E>{std::underlying_type_t<E>(a) | b.value};
     137              : }
     138              : /** @} */
     139              : 
     140              : /**
     141              :  * Form the union of the flags from two bitfields.
     142              :  */
     143              : template<class E>
     144            3 : std::enable_if_t<EnumFlagTraits<E>::value, FlagType<E>> operator|(FlagType<E> a, FlagType<E> b)
     145              : {
     146            3 :     return FlagType<E>{a.value | b.value};
     147              : }
     148              : 
     149              : /**
     150              :  * Intersection of two flags.
     151              :  * Use with `FlagType::any` or `FlagType::operator bool` to check if the flag is set.
     152              :  */
     153              : template<class E>
     154              : std::enable_if_t<EnumFlagTraits<E>::value, FlagType<E>> operator&(E a, E b)
     155              : {
     156              :     return FlagType<E>{std::underlying_type_t<E>(a) & std::underlying_type_t<E>(b)};
     157              : }
     158              : 
     159              : /**
     160              :  * Intersection of a bitfield and a single flag.
     161              :  * Use with `FlagType::any` or `FlagType::operator bool` to check if the flag is set.
     162              :  * @{
     163              :  */
     164              : template<class E>
     165           41 : std::enable_if_t<EnumFlagTraits<E>::value, FlagType<E>> operator&(FlagType<E> a, E b)
     166              : {
     167           41 :     return FlagType<E>{a.value & std::underlying_type_t<E>(b)};
     168              : }
     169              : template<class E>
     170            1 : std::enable_if_t<EnumFlagTraits<E>::value, FlagType<E>> operator&(E b, FlagType<E> a)
     171              : {
     172            1 :     return FlagType<E>{a.value & std::underlying_type_t<E>(b)};
     173              : }
     174              : /** @} */
     175              : 
     176              : /**
     177              :  * Intersection of two bit fields.
     178              :  */
     179              : template<class E>
     180            1 : std::enable_if_t<EnumFlagTraits<E>::value, FlagType<E>> operator&(FlagType<E> a, FlagType<E> b)
     181              : {
     182            1 :     return FlagType<E>{a.value & std::underlying_type_t<E>(b)};
     183              : }
     184              : 
     185              : } // namespace ipc
        

Generated by: LCOV version 2.0-1