3 * @brief Class holding flags: template implementation file.
4 * @author Gianluca Petrillo (petrillo@fnal.gov)
5 * @date January 25, 2017
10 #ifndef LARDATAOBJ_UTILITIES_BITMASK_TCC
11 #define LARDATAOBJ_UTILITIES_BITMASK_TCC
13 #ifndef LARDATAOBJ_UTILITIES_BITMASK_H
14 # error "Do not include BitMask.tcc directly: include BitMask.h instead."
15 #endif // !LARDATAOBJ_UTILITIES_BITMASK_H
18 // C/C++ standard library
19 #include <type_traits> // std::integral_constant, std::make_unsigned_t, ...
20 #include <algorithm> // std::for_each()
29 //------------------------------------------------------------------------
30 template <typename First, typename... Others>
31 struct GrowingSizeTypes;
33 template <typename First, typename Next, typename... Others>
34 struct GrowingSizeTypes<First, Next, Others...>
35 : public std::integral_constant<
37 (sizeof(First) <= sizeof(Next))
38 && GrowingSizeTypes<Next, Others...>::value
42 template <typename First>
43 struct GrowingSizeTypes<First>: public std::true_type {};
46 //------------------------------------------------------------------------
47 template <unsigned int NBits, typename... TestTypes>
48 struct FirstUnsignedTypeNoSmallerThanImpl;
50 template <unsigned int NBits, typename TestType, typename... Others>
51 struct FirstUnsignedTypeNoSmallerThanImpl<NBits, TestType, Others...> {
52 static_assert(sizeof...(Others) > 0, "Wrong specialisation!");
53 static_assert(GrowingSizeTypes<TestType, Others...>(),
54 "Types are not in increasing size order!");
56 using unsigned_test_type = std::make_unsigned_t<TestType>;
57 static_assert(sizeof(TestType) == sizeof(unsigned_test_type),
58 "Strange: signed and unsigned type sizes differ.");
60 using type = std::conditional_t<
61 (sizeof(unsigned_test_type) * 8 >= NBits),
63 typename FirstUnsignedTypeNoSmallerThanImpl<NBits, Others...>::type
66 }; // FirstUnsignedTypeNoSmallerThanImpl<>
68 template <unsigned int NBits, typename TestType>
69 struct FirstUnsignedTypeNoSmallerThanImpl<NBits, TestType>
70 { using type = TestType; };
72 template <unsigned int NBits, typename... TestTypes>
73 struct FirstUnsignedTypeNoSmallerThan {
76 typename FirstUnsignedTypeNoSmallerThanImpl<NBits, TestTypes...>
79 static_assert(sizeof(type) * 8 >= NBits, "No type is large enough!");
80 }; // FirstUnsignedTypeNoSmallerThan
82 /// Trait containing the smallest integral type accommodating `NBits`
84 template <unsigned int NBits>
85 struct SmallestUIntType {
87 using type = typename FirstUnsignedTypeNoSmallerThan
88 <NBits, char, short int, int, long int, long long int>::type;
90 }; // struct SmallestUIntType
92 /// Returns the number of Storage variables needed to hold that many bits
93 template <typename Storage>
94 constexpr unsigned int computePages(unsigned int bits) {
96 + ((sizeof(Storage) * 8 >= bits)? 0: computePages<Storage>(bits - 8));
99 //------------------------------------------------------------------------
101 template <typename T>
102 constexpr Index_t firstBitIndexImpl(T bits, Index_t carry)
103 { return (bits & 1) ? carry: firstBitIndexImpl(bits >> 1, carry + 1); }
105 /// Returns the index of the least significant set bit, or max() if none.
106 template <typename T>
107 constexpr Index_t firstBitIndex(T bits) {
108 return bits? firstBitIndexImpl(bits, 0): sizeof(T) * 8;
112 //------------------------------------------------------------------------
113 template <typename Storage>
115 BitMask<Storage> const& flags,
116 typename BitMask<Storage>::Flag_t flag,
117 char const unset = '0', char const set = '1', char const undefined = '-',
118 char const unexpected = '?'
121 if (flags.isUndefined(flag)) return undefined;
122 if (flags.isSet(flag)) return set;
123 if (flags.isUnset(flag)) return unset;
127 //------------------------------------------------------------------------
128 template <typename Storage>
129 constexpr typename util::flags::BitMask<Storage>::Mask_t createMaskImpl
130 (util::flags::BitMask<Storage> const baseMask)
133 template <typename Storage, typename First, typename... Others>
134 constexpr typename util::flags::BitMask<Storage>::Mask_t createMaskImpl(
135 util::flags::BitMask<Storage> const baseMask,
136 First first, Others... others
139 return createMaskImpl(
140 util::flags::BitMask<Storage>::mergeIntoMask(baseMask, first),
146 //------------------------------------------------------------------------
148 } // namespace details
156 //------------------------------------------------------------------------------
159 template <typename Storage>
160 constexpr util::flags::Index_t util::flags::Flag_t<Storage>::index() const
161 { return details::firstBitIndex(bits); }
164 //------------------------------------------------------------------------------
167 template <typename Storage>
168 constexpr bool util::flags::Bits_t<Storage>::all(This_t bits) const
169 { return select(bits) == bits; }
171 template <typename Storage>
172 constexpr bool util::flags::Bits_t<Storage>::any(This_t bits) const
173 { return bool(select(bits)) || !bits; }
175 template <typename Storage>
176 constexpr bool util::flags::Bits_t<Storage>::none(This_t bits) const
177 { return !any(bits) || !bits; }
179 template <typename Storage>
180 constexpr bool util::flags::Bits_t<Storage>::only(This_t bits) const
181 { return !exclude(bits); }
184 //------------------------------------------------------------------------------
185 template <typename Storage>
186 constexpr util::flags::Bits_t<Storage> util::flags::Bits_t<Storage>::combine
188 { return This_t(Storage_t(data | bits.data)); }
190 template <typename Storage>
191 constexpr util::flags::Bits_t<Storage> util::flags::Bits_t<Storage>::select
193 { return This_t(Storage_t(data & bits.data)); }
195 template <typename Storage>
196 constexpr util::flags::Bits_t<Storage> util::flags::Bits_t<Storage>::exclude
198 { return select(bits.invert()); }
200 template <typename Storage>
201 constexpr util::flags::Bits_t<Storage> util::flags::Bits_t<Storage>::invert
203 { return This_t(Storage_t(~data)); }
206 //------------------------------------------------------------------------------
207 template <typename Storage>
208 void util::flags::Bits_t<Storage>::set(This_t bits)
209 { setBits(data, bits.data); }
211 template <typename Storage>
212 void util::flags::Bits_t<Storage>::unset(This_t bits)
213 { unsetBits(data, bits.data); }
215 template <typename Storage>
216 void util::flags::Bits_t<Storage>::keepOnly(This_t bits)
217 { unsetBits(data, bits.negate().data); }
220 //------------------------------------------------------------------------------
221 template <typename Storage>
222 constexpr util::flags::Bits_t<Storage> util::flags::operator|
223 (util::flags::Bits_t<Storage> left, util::flags::Bits_t<Storage> right)
224 { return left.combine(right); }
226 template <typename Storage>
227 constexpr util::flags::Bits_t<Storage> util::flags::operator| (
228 util::flags::Bits_t<Storage> left,
229 typename util::flags::Bits_t<Storage>::Flag_t right
231 { return left | util::flags::Bits_t<Storage>(right); }
233 template <typename Storage>
234 constexpr util::flags::Bits_t<Storage> util::flags::operator| (
235 typename util::flags::Bits_t<Storage>::Flag_t left,
236 util::flags::Bits_t<Storage> right
238 { return right | left; }
240 template <typename Storage>
241 constexpr util::flags::Bits_t<Storage> util::flags::operator| (
242 util::flags::Flag_t<Storage> left,
243 util::flags::Flag_t<Storage> right
245 { return util::flags::Bits_t<Storage>(left) | right; }
248 template <typename Storage>
249 constexpr util::flags::Bits_t<Storage> util::flags::operator+
250 (util::flags::Bits_t<Storage> left, util::flags::Bits_t<Storage> right)
251 { return left | right; }
253 template <typename Storage>
254 constexpr util::flags::Bits_t<Storage> util::flags::operator+ (
255 util::flags::Bits_t<Storage> left,
256 typename util::flags::Bits_t<Storage>::Flag_t right
258 { return left | right; }
260 template <typename Storage>
261 constexpr util::flags::Bits_t<Storage> util::flags::operator+ (
262 typename util::flags::Bits_t<Storage>::Flag_t left,
263 util::flags::Bits_t<Storage> right
265 { return left | right; }
267 template <typename Storage>
268 constexpr util::flags::Bits_t<Storage> util::flags::operator+ (
269 util::flags::Flag_t<Storage> left,
270 util::flags::Flag_t<Storage> right
272 { return left | right; }
276 //------------------------------------------------------------------------------
279 template <typename Storage>
280 constexpr util::flags::BitMask<Storage>::BitMask
281 (BitMaskFromValuesTag, Bits_t defined, Bits_t values)
283 , presence(defined.combine(values))
286 template <typename Storage>
287 constexpr util::flags::BitMask<Storage>::BitMask
288 (BitMaskFromValuesTag tag, Bits_t bits)
289 : BitMask(tag, bits, bits)
292 template <typename Storage>
293 constexpr util::flags::BitMask<Storage>::BitMask
294 (BitMaskFromValuesTag tag, Storage_t defined, Storage_t values)
295 : BitMask(tag, Bits_t(defined), Bits_t(values))
298 template <typename Storage>
299 constexpr util::flags::BitMask<Storage>::BitMask
300 (BitMaskFromValuesTag tag, Storage_t values)
301 : BitMask(tag, Bits_t(values))
304 //------------------------------------------------------------------------------
305 template <typename Storage>
306 constexpr typename util::flags::BitMask<Storage>::Bits_t
307 util::flags::BitMask<Storage>::definedOnly() const
308 { return values.select(presence); }
310 //------------------------------------------------------------------------------
311 template <typename Storage>
312 constexpr size_t util::flags::BitMask<Storage>::capacity()
313 { return sizeof(Storage) * 8; }
315 //------------------------------------------------------------------------------
316 template <typename Storage>
317 constexpr bool util::flags::BitMask<Storage>::isDefined(Flag_t flag) const
318 { return presence.any(flag); }
320 template <typename Storage>
321 constexpr bool util::flags::BitMask<Storage>::isDefined(Bits_t bits) const
322 { return presence.all(bits); }
324 //------------------------------------------------------------------------------
325 template <typename Storage>
326 constexpr bool util::flags::BitMask<Storage>::isUndefined(Flag_t flag) const
327 { return !isDefined(flag); }
329 template <typename Storage>
330 constexpr bool util::flags::BitMask<Storage>::isUndefined(Bits_t bits) const
331 { return !isDefined(bits); }
333 //------------------------------------------------------------------------------
334 template <typename Storage>
335 constexpr bool util::flags::BitMask<Storage>::get(Flag_t flag) const
336 { return values.any(flag); }
338 //------------------------------------------------------------------------------
339 template <typename Storage>
340 constexpr bool util::flags::BitMask<Storage>::isSet(Flag_t flag) const
341 { return get(flag) && isDefined(flag); }
343 //------------------------------------------------------------------------------
344 template <typename Storage>
345 constexpr bool util::flags::BitMask<Storage>::isUnset(Flag_t flag) const
346 { return !get(flag) && isDefined(flag); }
348 //------------------------------------------------------------------------------
349 template <typename Storage>
350 constexpr bool util::flags::BitMask<Storage>::all(Bits_t bits) const
351 { return isDefined(bits) && values.all(bits); }
353 //------------------------------------------------------------------------------
354 template <typename Storage>
355 constexpr bool util::flags::BitMask<Storage>::any(Bits_t bits) const {
356 // check values only for the flags in bits that are actually defined;
357 // values.any() will return true if no bit is specified,
358 // which is semantically correct but does not serve the scope here;
359 // if no bits are defined, this method should return false instead.
360 return values.any(presence.select(bits)) && !(presence.select(bits).empty());
363 //------------------------------------------------------------------------------
364 template <typename Storage>
365 constexpr bool util::flags::BitMask<Storage>::none(Bits_t bits) const
366 { return isDefined(bits) && values.none(bits); }
368 //------------------------------------------------------------------------------
369 template <typename Storage>
370 constexpr bool util::flags::BitMask<Storage>::anySet(Mask_t const& mask) const {
372 !definedOnly().select(mask.definedOnly()).empty()
373 || mask.values.select(mask.presence).empty();
376 //------------------------------------------------------------------------------
377 template <typename Storage>
378 constexpr bool util::flags::BitMask<Storage>::noneSet(Mask_t const& mask) const
379 { return !anySet(mask); }
382 //------------------------------------------------------------------------------
383 template <typename Storage>
384 constexpr bool util::flags::BitMask<Storage>::match(Mask_t const& mask) const {
385 // 1) no undefined flags that are defined in mask
386 // 2) all our flags defined also in mask must have the same values as in mask
387 return mask.presence.exclude(presence).empty()
388 && values.select(mask.presence) == mask.definedOnly();
392 //------------------------------------------------------------------------------
393 template <typename Storage>
394 template <typename Stream>
395 void util::flags::BitMask<Storage>::dump(Stream&& out, unsigned int nBits) const
401 typename BitMask<Storage>::FlagIndex_t i = nBits;
402 out << details::flagChar(*this, --i);
405 if ((i % 4) == 3) out << ':';
406 out << details::flagChar(*this, i);
412 } // util::flags::BitMask<>::dump()
415 //------------------------------------------------------------------------------
416 template <typename Storage>
417 template <typename... Args>
418 constexpr typename util::flags::BitMask<Storage>::Mask_t
419 util::flags::BitMask<Storage>::create(Args... args)
420 { return details::createMaskImpl(Mask_t(), args...); }
422 //------------------------------------------------------------------------------
423 template <typename Storage>
424 void util::flags::BitMask<Storage>::defineSingle(Flag_t flag)
425 { presence.set(flag); }
427 //------------------------------------------------------------------------------
428 template <typename Storage>
429 template <typename... Flags>
430 void util::flags::BitMask<Storage>::undefineImpl(Flag_t flag, Flags... others)
431 { undefineSingle(flag); undefineImpl(others...); }
433 //------------------------------------------------------------------------------
434 template <typename Storage>
435 void util::flags::BitMask<Storage>::undefineSingle(Flag_t flag)
436 { presence.unset(flag); }
438 //------------------------------------------------------------------------------
439 template <typename Storage>
440 template <typename... Flags>
441 void util::flags::BitMask<Storage>::setImpl(Flag_t flag, Flags... others)
442 { setSingle(flag); setImpl(others...); }
444 //------------------------------------------------------------------------------
445 template <typename Storage>
446 void util::flags::BitMask<Storage>::setSingle(Flag_t flag)
447 { defineSingle(flag); values.set(flag); }
449 //------------------------------------------------------------------------------
450 template <typename Storage>
451 template <typename... Flags>
452 void util::flags::BitMask<Storage>::unsetImpl(Flag_t flag, Flags... others)
453 { unsetSingle(flag); unsetImpl(others...); }
455 //------------------------------------------------------------------------------
456 template <typename Storage>
457 void util::flags::BitMask<Storage>::unsetSingle(Flag_t flag)
458 { defineSingle(flag); values.unset(flag); }
460 //------------------------------------------------------------------------------
461 template <typename Storage>
462 template <typename BeginIter, typename EndIter>
463 void util::flags::BitMask<Storage>::rangeSet(BeginIter begin, EndIter end)
464 { std::for_each(begin, end, [this](auto&& flag){ this->set(flag); }); }
466 //------------------------------------------------------------------------------
467 template <typename Storage>
468 template <typename BeginIter, typename EndIter>
469 void util::flags::BitMask<Storage>::rangeUnset(BeginIter begin, EndIter end)
470 { std::for_each(begin, end, [this](auto&& flag){ this->unset(flag); }); }
473 //------------------------------------------------------------------------------
474 template <typename Storage>
475 constexpr typename util::flags::BitMask<Storage>::Mask_t
476 util::flags::BitMask<Storage>::mergeIntoMask
477 (Mask_t baseMask, Mask_t mask)
479 return Mask_t(fromValues,
480 baseMask.presence.combine(mask.presence),
481 (baseMask.values.exclude(mask.presence)) | mask.values
483 } // util::flags::BitMask<>::mergeIntoMask(Mask_t)
486 //------------------------------------------------------------------------------
487 template <typename Storage>
488 constexpr typename util::flags::BitMask<Storage>::Mask_t
489 util::flags::BitMask<Storage>::mergeIntoMask
490 (Mask_t baseMask, Bits_t bits)
492 return Mask_t(fromValues,
493 baseMask.presence.combine(bits),
494 baseMask.values.combine(bits)
496 } // util::flags::BitMask<>::mergeIntoMask(Mask_t)
499 //------------------------------------------------------------------------------
500 template <typename Storage>
501 constexpr typename util::flags::BitMask<Storage>::Mask_t
502 util::flags::BitMask<Storage>::mergeIntoMask
503 (Mask_t baseMask, Flag_t flags)
504 { return mergeIntoMask(baseMask, Bits_t(flags)); }
507 //------------------------------------------------------------------------------
508 template <typename Storage>
509 constexpr typename util::flags::BitMask<Storage>::Mask_t
510 util::flags::BitMask<Storage>::combineWithMask
513 return Mask_t(fromValues,
514 A.presence.combine(B.presence),
515 A.presence.combine(B.presence).select(A.values.combine(B.values))
517 } // util::flags::BitMask<>::combineWithMask(Mask_t)
520 //------------------------------------------------------------------------------
521 template <typename Storage>
522 constexpr typename util::flags::BitMask<Storage>::Mask_t
523 util::flags::BitMask<Storage>::combineWithMask
524 (Mask_t baseMask, Bits_t bits)
525 { return mergeIntoMask(baseMask, bits); }
528 //------------------------------------------------------------------------------
529 template <typename Storage>
530 constexpr typename util::flags::BitMask<Storage>::Mask_t
531 util::flags::BitMask<Storage>::combineWithMask
532 (Mask_t baseMask, Flag_t flags)
533 { return combineWithMask(baseMask, Bits_t(flags)); }
536 //------------------------------------------------------------------------------
537 template <typename Storage>
538 constexpr typename util::flags::BitMask<Storage>::Mask_t
539 util::flags::BitMask<Storage>::intersectWithMask
543 // flags undefined in B are copied from A; for the others, B wins.
545 return Mask_t(fromValues,
546 A.presence.combine(B.presence),
547 // the bits that are defined in both get AND'ed:
548 A.presence.select(B.presence).select(A.values).select(B.values)
549 // the bits that are not, are copied:
551 A.values.combine(B.values).exclude(A.presence.select(B.presence))
556 //------------------------------------------------------------------------------
557 template <typename Storage>
558 constexpr typename util::flags::BitMask<Storage>::Mask_t
559 util::flags::BitMask<Storage>::intersectWithMask
560 (Mask_t baseMask, Bits_t bits)
562 // defined: (presentInA | B)
563 // values: (presentInA & B) & (valuesA & B) : if in both terms, use AND
564 // | (!(presentInA & B) & (valuesA | B) : otherwise, set from either
565 return Mask_t(fromValues,
566 baseMask.presence.combine(bits),
567 // the bits that are defined in both get AND'ed:
568 baseMask.presence.select(bits).select(baseMask.values)
569 // the bits that are not, are copied:
571 baseMask.values.combine(bits).exclude(baseMask.presence.select(bits))
574 } // util::flags::BitMask<>::intersectWithMask(Mask_t)
577 //------------------------------------------------------------------------------
578 template <typename Storage>
579 constexpr typename util::flags::BitMask<Storage>::Mask_t
580 util::flags::BitMask<Storage>::intersectWithMask
581 (Mask_t baseMask, Flag_t flags)
582 { return intersectWithMask(baseMask, Bits_t(flags)); }
585 //------------------------------------------------------------------------------
586 template <typename Storage>
587 constexpr typename util::flags::BitMask<Storage>::Mask_t
588 util::flags::BitMask<Storage>::unsetMask(Mask_t baseMask, Mask_t mask) {
589 return Mask_t(fromValues,
590 baseMask.presence.combine(mask.presence),
591 baseMask.presence.combine(mask.presence)
592 .select(baseMask.values.exclude(mask.values))
596 //------------------------------------------------------------------------------
597 template <typename Storage>
598 constexpr typename util::flags::BitMask<Storage>::Mask_t
599 util::flags::BitMask<Storage>::unsetMask(Mask_t baseMask, Bits_t bits) {
600 return Mask_t(fromValues,
601 baseMask.presence.combine(bits),
602 baseMask.values.exclude(bits)
604 } // util::flags::BitMask<>::unsetMask(Mask_t)
607 //------------------------------------------------------------------------------
608 template <typename Storage>
609 constexpr typename util::flags::BitMask<Storage>::Mask_t
610 util::flags::BitMask<Storage>::unsetMask
611 (Mask_t baseMask, Flag_t flags)
612 { return unsetMask(baseMask, Bits_t(flags)); }
615 //------------------------------------------------------------------------------
616 template <typename Storage>
617 constexpr typename util::flags::BitMask<Storage>::Mask_t
618 util::flags::BitMask<Storage>::negateMask(Mask_t mask) {
620 (fromValues, mask.presence, mask.presence.select(mask.values.invert()));
623 //------------------------------------------------------------------------------
624 template <typename Storage>
625 constexpr typename util::flags::BitMask<Storage>::Mask_t
626 util::flags::BitMask<Storage>::negateMask(Bits_t bits)
627 { return Mask_t(fromValues, bits, Bits_t(0)); }
629 template <typename Storage>
630 constexpr typename util::flags::BitMask<Storage>::Mask_t
631 util::flags::BitMask<Storage>::negateMask(Flag_t flags)
632 { return negateMask(Bits_t(flags)); }
635 //------------------------------------------------------------------------------
636 //--- free functions and operators
638 template <typename Storage>
639 constexpr util::flags::BitMask<Storage> util::flags::makeMask
640 (Bits_t<Storage> bits)
641 { return BitMask<Storage>(BitMask<Storage>::fromValues, bits); }
644 //------------------------------------------------------------------------------
645 template <typename Storage>
646 constexpr util::flags::BitMask<Storage> util::flags::operator|
647 (BitMask<Storage> left, BitMask<Storage> right)
648 { return BitMask<Storage>::combineWithMask(left, right); }
650 template <typename Storage>
651 constexpr util::flags::BitMask<Storage> util::flags::operator|
652 (BitMask<Storage> left, typename BitMask<Storage>::Bits_t right)
653 { return BitMask<Storage>::combineWithMask(left, right); }
655 template <typename Storage>
656 constexpr util::flags::BitMask<Storage> util::flags::operator|
657 (typename BitMask<Storage>::Bits_t left, BitMask<Storage> right)
658 { return BitMask<Storage>::combineWithMask(right, left); }
661 //------------------------------------------------------------------------------
662 template <typename Storage>
663 constexpr util::flags::BitMask<Storage> util::flags::operator&
664 (BitMask<Storage> left, BitMask<Storage> right)
665 { return BitMask<Storage>::intersectWithMask(left, right); }
667 template <typename Storage>
668 constexpr util::flags::BitMask<Storage> util::flags::operator&
669 (BitMask<Storage> left, typename BitMask<Storage>::Bits_t right)
670 { return BitMask<Storage>::intersectWithMask(left, right); }
672 template <typename Storage>
673 constexpr util::flags::BitMask<Storage> util::flags::operator&
674 (typename BitMask<Storage>::Bits_t left, BitMask<Storage> right)
675 { return makeMask(left) & right; }
678 template <typename Storage>
679 constexpr util::flags::BitMask<Storage> util::flags::operator&
680 (Bits_t<Storage> left, Bits_t<Storage> right)
681 { return BitMask<Storage>(left) & right; }
683 //------------------------------------------------------------------------------
684 template <typename Storage>
685 constexpr util::flags::BitMask<Storage> util::flags::operator+
686 (BitMask<Storage> baseMask, BitMask<Storage> mask)
687 { return BitMask<Storage>::mergeIntoMask(baseMask, mask); }
689 template <typename Storage>
690 constexpr util::flags::BitMask<Storage> util::flags::operator+
691 (BitMask<Storage> baseMask, typename BitMask<Storage>::Bits_t bits)
692 { return BitMask<Storage>::mergeIntoMask(baseMask, bits); }
694 template <typename Storage>
695 constexpr util::flags::BitMask<Storage> util::flags::operator+
696 (typename BitMask<Storage>::Bits_t baseBits, BitMask<Storage> mask)
697 { return makeMask(baseBits) + mask; }
699 //------------------------------------------------------------------------------
700 template <typename Storage>
701 constexpr util::flags::BitMask<Storage> util::flags::operator-
702 (BitMask<Storage> baseMask, BitMask<Storage> mask)
703 { return BitMask<Storage>::unsetMask(baseMask, mask); }
705 template <typename Storage>
706 constexpr util::flags::BitMask<Storage> util::flags::operator-
707 (BitMask<Storage> baseMask, typename BitMask<Storage>::Bits_t bits)
708 { return BitMask<Storage>::unsetMask(baseMask, bits); }
710 template <typename Storage>
711 constexpr util::flags::BitMask<Storage> util::flags::operator-
712 (typename BitMask<Storage>::Bits_t baseBits, BitMask<Storage> mask)
713 { return makeMask(baseBits) - mask; }
715 template <typename Storage>
716 constexpr util::flags::BitMask<Storage> util::flags::operator-
717 (Bits_t<Storage> baseBits, Bits_t<Storage> bits)
718 { return makeMask(baseBits) - bits; }
720 //------------------------------------------------------------------------------
721 template <typename Storage>
722 constexpr util::flags::BitMask<Storage> util::flags::operator+
723 (BitMask<Storage> mask)
726 template <typename Storage>
727 constexpr util::flags::BitMask<Storage> util::flags::operator+
728 (Bits_t<Storage> bits)
729 { return makeMask(bits); }
731 //------------------------------------------------------------------------------
732 template <typename Storage>
733 constexpr util::flags::BitMask<Storage> util::flags::operator-
734 (Bits_t<Storage> bits)
735 { return BitMask<Storage>::negateMask(makeMask(bits)); }
737 template <typename Storage>
738 constexpr util::flags::BitMask<Storage> util::flags::operator-
739 (Flag_t<Storage> flag)
740 { return -(Bits_t<Storage>(flag)); }
742 //------------------------------------------------------------------------------
743 template <typename Storage>
744 constexpr util::flags::BitMask<Storage> util::flags::operator~
745 (BitMask<Storage> mask)
746 { return BitMask<Storage>::negateMask(mask); }
749 template <typename Storage>
750 constexpr BitMask<Storage> operator~ (typename Bits_t<Storage> bits)
751 { return ~BitMask<Storage>(bits); }
754 //------------------------------------------------------------------------------
755 template <typename Storage>
756 constexpr util::flags::BitMask<Storage> util::flags::Set(Flag_t<Storage> flag)
757 { return BitMask<Storage>(BitMask<Storage>::fromValues, flag, flag); }
759 template <typename Storage>
760 constexpr util::flags::BitMask<Storage> util::flags::Unset(Flag_t<Storage> flag)
762 return BitMask<Storage>
763 (BitMask<Storage>::fromValues, flag, Bits_t<Storage>(0));
766 //------------------------------------------------------------------------------
770 #endif // LARDATAOBJ_UTILITIES_BITMASK_TCC