forked from frc971/971-Robot-Code
-
Notifications
You must be signed in to change notification settings - Fork 0
/
options.h
87 lines (67 loc) · 2.61 KB
/
options.h
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
#ifndef AOS_UTIL_OPTIONS_H_
#define AOS_UTIL_OPTIONS_H_
namespace aos {
// An "option" that can be combined with other options and passed as one
// argument. This class is designed to emulate integral constants (except be
// type-safe), so its instances can be combined with operator| (creating an
// Options), and an Options can be tested for membership with operator&.
// Owner is the only class that can construct Option instances and is used to
// differentiate between options for different classes. It is safe to only have
// a forward declaration for Owner in scope when instantiating either of these
// template classes.
template <class Owner>
class Options {
public:
// Represents a single options. Instances of this should be created as
// constants by Owner.
class Option {
public:
constexpr Options operator|(Option option) const {
return Options(bit_ | option.bit_);
}
constexpr bool operator==(Option other) const { return bit_ == other.bit_; }
constexpr unsigned int printable() const { return bit_; }
private:
// Bit must have exactly 1 bit set and that must be a different one for each
// instance.
explicit constexpr Option(unsigned int bit) : bit_(bit) {}
unsigned int bit_;
friend class Options;
friend Owner;
};
constexpr Options(Option option) : bits_(option.bit_) {}
constexpr bool operator&(Option option) const {
return (bits_ & option.bit_) != 0;
}
constexpr Options operator|(Option option) const {
return Options(bits_ | option.bit_);
}
constexpr Options operator|(Options options) const {
return Options(bits_ | options.bits_);
}
constexpr bool operator==(Options other) const {
return bits_ == other.bits_;
}
constexpr unsigned int printable() const { return bits_; }
// Returns true if no Options other than the ones in options are set.
// Useful for validating that no illegal options are passed.
constexpr bool NoOthersSet(Options options) const {
return (bits_ & ~options.bits_) == 0;
}
// Returns true if exactly 1 of the Options in options is set.
// Useful for validating that one of a group of mutually exclusive options has
// been passed.
constexpr bool ExactlyOneSet(Options options) const {
return __builtin_popcount(bits_ & options.bits_) == 1;
}
// Returns true if all of the Options in options are set.
constexpr bool AllSet(Options options) const {
return (bits_ & options.bits_) == options.bits_;
}
private:
explicit constexpr Options(unsigned int bits) : bits_(bits) {}
unsigned int bits_;
friend class Option;
};
} // namespace aos
#endif // AOS_UTIL_OPTIONS_H_