File: flagenumclass.h

package info (click to toggle)
martchus-cpp-utilities 5.28.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,352 kB
  • sloc: cpp: 12,471; awk: 18; ansic: 12; makefile: 10
file content (113 lines) | stat: -rw-r--r-- 6,183 bytes parent folder | download
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#ifndef CPP_UTILITIES_FLAG_ENUM_CLASS_H
#define CPP_UTILITIES_FLAG_ENUM_CLASS_H

#include "./traits.h"

namespace CppUtilities {

/*!
 * \brief The IsFlagEnumClass class is used to decide whether to enable operations for flag enums for \tparam T.
 */
template <typename T> struct IsFlagEnumClass : public Traits::Bool<false> {};

// clang-format off
/*!
 * \brief The \def CPP_UTILITIES_MARK_FLAG_ENUM_CLASS macro enables flag enum operators for \a EnumClassType within namespace \a Namespace.
 * \remarks Must be used outside a namespace.
 */
#define CPP_UTILITIES_MARK_FLAG_ENUM_CLASS(Namespace, EnumClassType)                                                                                 \
    namespace CppUtilities {                                                                                                                         \
    template <> struct IsFlagEnumClass<EnumClassType> : Traits::Bool<true> {                                                                         \
    };                                                                                                                                               \
    }                                                                                                                                                \
    namespace Namespace {                                                                                                                            \
    using CppUtilities::FlagEnumClassOperations::operator|;                                                                                          \
    using CppUtilities::FlagEnumClassOperations::operator&;                                                                                          \
    using CppUtilities::FlagEnumClassOperations::operator&&;                                                                                         \
    using CppUtilities::FlagEnumClassOperations::operator|=;                                                                                         \
    using CppUtilities::FlagEnumClassOperations::operator+=;                                                                                         \
    using CppUtilities::FlagEnumClassOperations::operator-=;                                                                                         \
    }
// clang-format on

/*!
 * \brief The FlagEnumClassOperations namespace contains operations for flag enums.
 */
namespace FlagEnumClassOperations {

template <typename FlagEnumClass, Traits::EnableIf<IsFlagEnumClass<FlagEnumClass>> * = nullptr>
constexpr FlagEnumClass operator|(FlagEnumClass lhs, FlagEnumClass rhs)
{
    return static_cast<FlagEnumClass>(
        static_cast<typename std::underlying_type<FlagEnumClass>::type>(lhs) | static_cast<typename std::underlying_type<FlagEnumClass>::type>(rhs));
}

#ifdef CPP_UTILITIES_FLAG_ENUM_CLASS_NO_LEGACY_AND
template <typename FlagEnumClass, Traits::EnableIf<IsFlagEnumClass<FlagEnumClass>> * = nullptr>
constexpr FlagEnumClass operator&(FlagEnumClass lhs, FlagEnumClass rhs)
{
    return static_cast<FlagEnumClass>(
        static_cast<typename std::underlying_type<FlagEnumClass>::type>(lhs) & static_cast<typename std::underlying_type<FlagEnumClass>::type>(rhs));
}
#else
template <typename FlagEnumClass, Traits::EnableIf<IsFlagEnumClass<FlagEnumClass>> * = nullptr>
constexpr bool operator&(FlagEnumClass lhs, FlagEnumClass rhs)
{
    return static_cast<typename std::underlying_type<FlagEnumClass>::type>(lhs)
        & static_cast<typename std::underlying_type<FlagEnumClass>::type>(rhs);
}
#endif

template <typename FlagEnumClass, Traits::EnableIf<IsFlagEnumClass<FlagEnumClass>> * = nullptr>
constexpr bool operator&&(FlagEnumClass lhs, FlagEnumClass rhs)
{
    return static_cast<typename std::underlying_type<FlagEnumClass>::type>(lhs)
        & static_cast<typename std::underlying_type<FlagEnumClass>::type>(rhs);
}

template <typename FlagEnumClass, Traits::EnableIf<IsFlagEnumClass<FlagEnumClass>> * = nullptr>
constexpr FlagEnumClass &operator|=(FlagEnumClass &lhs, FlagEnumClass rhs)
{
    return lhs = static_cast<FlagEnumClass>(static_cast<typename std::underlying_type<FlagEnumClass>::type>(lhs)
               | static_cast<typename std::underlying_type<FlagEnumClass>::type>(rhs));
}

template <typename FlagEnumClass, Traits::EnableIf<IsFlagEnumClass<FlagEnumClass>> * = nullptr>
constexpr FlagEnumClass &operator+=(FlagEnumClass &lhs, FlagEnumClass rhs)
{
    return lhs = static_cast<FlagEnumClass>(static_cast<typename std::underlying_type<FlagEnumClass>::type>(lhs)
               | static_cast<typename std::underlying_type<FlagEnumClass>::type>(rhs));
}

template <typename FlagEnumClass, Traits::EnableIf<IsFlagEnumClass<FlagEnumClass>> * = nullptr>
constexpr FlagEnumClass &operator-=(FlagEnumClass &lhs, FlagEnumClass rhs)
{
    return lhs = static_cast<FlagEnumClass>(static_cast<typename std::underlying_type<FlagEnumClass>::type>(lhs)
               & (~static_cast<typename std::underlying_type<FlagEnumClass>::type>(rhs)));
}

} // namespace FlagEnumClassOperations

/*!
 * \brief Sets the specified \a relevantFlags in the specified \a flagVariable to the specified \a value.
 */
template <typename FlagEnumClass, Traits::EnableIf<IsFlagEnumClass<FlagEnumClass>> * = nullptr>
constexpr FlagEnumClass &modFlagEnum(FlagEnumClass &flagVariable, FlagEnumClass relevantFlags, bool value)
{
    return value ? (flagVariable += relevantFlags) : (flagVariable -= relevantFlags);
}

/*!
 * \brief Returns whether the specified \a flagVariable has set all flags specified via \a flagsToCheck to true.
 */
template <typename FlagEnumClass, Traits::EnableIf<IsFlagEnumClass<FlagEnumClass>> * = nullptr>
constexpr bool checkFlagEnum(FlagEnumClass flagVariable, FlagEnumClass flagsToCheck)
{
    return (static_cast<typename std::underlying_type<FlagEnumClass>::type>(flagVariable)
               & static_cast<typename std::underlying_type<FlagEnumClass>::type>(flagsToCheck))
        == static_cast<typename std::underlying_type<FlagEnumClass>::type>(flagsToCheck);
}

} // namespace CppUtilities

#endif // CPP_UTILITIES_FLAG_ENUM_CLASS_H