2 * @file lardataobj/Utilities/BitMask.tcc
3 * @brief Class holding flags: template implementation file.
4 * @author Gianluca Petrillo (petrillo@fnal.gov)
5 * @date January 25, 2017
6 * @see lardataobj/Utilities/BitMask.h
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
17 // C/C++ standard library
18 #include <algorithm> // std::for_each()
19 #include <type_traits> // std::integral_constant, std::make_unsigned_t, ...
27 //------------------------------------------------------------------------
28 template <typename First, typename... Others>
29 struct GrowingSizeTypes;
31 template <typename First, typename Next, typename... Others>
32 struct GrowingSizeTypes<First, Next, Others...>
33 : public std::integral_constant<bool,
34 (sizeof(First) <= sizeof(Next)) &&
35 GrowingSizeTypes<Next, Others...>::value> {};
37 template <typename First>
38 struct GrowingSizeTypes<First> : public std::true_type {};
40 //------------------------------------------------------------------------
41 template <unsigned int NBits, typename... TestTypes>
42 struct FirstUnsignedTypeNoSmallerThanImpl;
44 template <unsigned int NBits, typename TestType, typename... Others>
45 struct FirstUnsignedTypeNoSmallerThanImpl<NBits, TestType, Others...> {
46 static_assert(sizeof...(Others) > 0, "Wrong specialisation!");
47 static_assert(GrowingSizeTypes<TestType, Others...>(),
48 "Types are not in increasing size order!");
50 using unsigned_test_type = std::make_unsigned_t<TestType>;
51 static_assert(sizeof(TestType) == sizeof(unsigned_test_type),
52 "Strange: signed and unsigned type sizes differ.");
55 std::conditional_t<(sizeof(unsigned_test_type) * 8 >= NBits),
57 typename FirstUnsignedTypeNoSmallerThanImpl<NBits, Others...>::type>;
59 }; // FirstUnsignedTypeNoSmallerThanImpl<>
61 template <unsigned int NBits, typename TestType>
62 struct FirstUnsignedTypeNoSmallerThanImpl<NBits, TestType> {
63 using type = TestType;
66 template <unsigned int NBits, typename... TestTypes>
67 struct FirstUnsignedTypeNoSmallerThan {
69 using type = typename FirstUnsignedTypeNoSmallerThanImpl<NBits, TestTypes...>::type;
71 static_assert(sizeof(type) * 8 >= NBits, "No type is large enough!");
72 }; // FirstUnsignedTypeNoSmallerThan
74 /// Trait containing the smallest integral type accommodating `NBits`
76 template <unsigned int NBits>
77 struct SmallestUIntType {
79 using type = typename FirstUnsignedTypeNoSmallerThan<NBits,
86 }; // struct SmallestUIntType
88 /// Returns the number of Storage variables needed to hold that many bits
89 template <typename Storage>
90 constexpr unsigned int computePages(unsigned int bits)
92 return 1 + ((sizeof(Storage) * 8 >= bits) ? 0 : computePages<Storage>(bits - 8));
95 //------------------------------------------------------------------------
98 constexpr Index_t firstBitIndexImpl(T bits, Index_t carry)
100 return (bits & 1) ? carry : firstBitIndexImpl(bits >> 1, carry + 1);
103 /// Returns the index of the least significant set bit, or max() if none.
104 template <typename T>
105 constexpr Index_t firstBitIndex(T bits)
107 return bits ? firstBitIndexImpl(bits, 0) : sizeof(T) * 8;
110 //------------------------------------------------------------------------
111 template <typename Storage>
112 char flagChar(BitMask<Storage> const& flags,
113 typename BitMask<Storage>::Flag_t flag,
114 char const unset = '0',
115 char const set = '1',
116 char const undefined = '-',
117 char const unexpected = '?')
119 if (flags.isUndefined(flag)) return undefined;
120 if (flags.isSet(flag)) return set;
121 if (flags.isUnset(flag)) return unset;
125 //------------------------------------------------------------------------
126 template <typename Storage>
127 constexpr typename util::flags::BitMask<Storage>::Mask_t createMaskImpl(
128 util::flags::BitMask<Storage> const baseMask)
133 template <typename Storage, typename First, typename... Others>
134 constexpr typename util::flags::BitMask<Storage>::Mask_t
135 createMaskImpl(util::flags::BitMask<Storage> const baseMask, First first, Others... others)
137 return createMaskImpl(util::flags::BitMask<Storage>::mergeIntoMask(baseMask, first),
141 //------------------------------------------------------------------------
143 } // namespace details
149 //------------------------------------------------------------------------------
152 template <typename Storage>
153 constexpr util::flags::Index_t util::flags::Flag_t<Storage>::index() const
155 return details::firstBitIndex(bits);
158 //------------------------------------------------------------------------------
161 template <typename Storage>
162 constexpr bool util::flags::Bits_t<Storage>::all(This_t bits) const
164 return select(bits) == bits;
167 template <typename Storage>
168 constexpr bool util::flags::Bits_t<Storage>::any(This_t bits) const
170 return bool(select(bits)) || !bits;
173 template <typename Storage>
174 constexpr bool util::flags::Bits_t<Storage>::none(This_t bits) const
176 return !any(bits) || !bits;
179 template <typename Storage>
180 constexpr bool util::flags::Bits_t<Storage>::only(This_t bits) const
182 return !exclude(bits);
185 //------------------------------------------------------------------------------
186 template <typename Storage>
187 constexpr util::flags::Bits_t<Storage> util::flags::Bits_t<Storage>::combine(This_t bits) const
189 return This_t(Storage_t(data | bits.data));
192 template <typename Storage>
193 constexpr util::flags::Bits_t<Storage> util::flags::Bits_t<Storage>::select(This_t bits) const
195 return This_t(Storage_t(data & bits.data));
198 template <typename Storage>
199 constexpr util::flags::Bits_t<Storage> util::flags::Bits_t<Storage>::exclude(This_t bits) const
201 return select(bits.invert());
204 template <typename Storage>
205 constexpr util::flags::Bits_t<Storage> util::flags::Bits_t<Storage>::invert() const
207 return This_t(Storage_t(~data));
210 //------------------------------------------------------------------------------
211 template <typename Storage>
212 void util::flags::Bits_t<Storage>::set(This_t bits)
214 setBits(data, bits.data);
217 template <typename Storage>
218 void util::flags::Bits_t<Storage>::unset(This_t bits)
220 unsetBits(data, bits.data);
223 template <typename Storage>
224 void util::flags::Bits_t<Storage>::keepOnly(This_t bits)
226 unsetBits(data, bits.negate().data);
229 //------------------------------------------------------------------------------
230 template <typename Storage>
231 constexpr util::flags::Bits_t<Storage> util::flags::operator|(util::flags::Bits_t<Storage> left,
232 util::flags::Bits_t<Storage> right)
234 return left.combine(right);
237 template <typename Storage>
238 constexpr util::flags::Bits_t<Storage> util::flags::operator|(
239 util::flags::Bits_t<Storage> left,
240 typename util::flags::Bits_t<Storage>::Flag_t right)
242 return left | util::flags::Bits_t<Storage>(right);
245 template <typename Storage>
246 constexpr util::flags::Bits_t<Storage> util::flags::operator|(
247 typename util::flags::Bits_t<Storage>::Flag_t left,
248 util::flags::Bits_t<Storage> right)
253 template <typename Storage>
254 constexpr util::flags::Bits_t<Storage> util::flags::operator|(util::flags::Flag_t<Storage> left,
255 util::flags::Flag_t<Storage> right)
257 return util::flags::Bits_t<Storage>(left) | right;
260 template <typename Storage>
261 constexpr util::flags::Bits_t<Storage> util::flags::operator+(util::flags::Bits_t<Storage> left,
262 util::flags::Bits_t<Storage> right)
267 template <typename Storage>
268 constexpr util::flags::Bits_t<Storage> util::flags::operator+(
269 util::flags::Bits_t<Storage> left,
270 typename util::flags::Bits_t<Storage>::Flag_t right)
275 template <typename Storage>
276 constexpr util::flags::Bits_t<Storage> util::flags::operator+(
277 typename util::flags::Bits_t<Storage>::Flag_t left,
278 util::flags::Bits_t<Storage> right)
283 template <typename Storage>
284 constexpr util::flags::Bits_t<Storage> util::flags::operator+(util::flags::Flag_t<Storage> left,
285 util::flags::Flag_t<Storage> right)
290 //------------------------------------------------------------------------------
293 template <typename Storage>
294 constexpr util::flags::BitMask<Storage>::BitMask(BitMaskFromValuesTag,
297 : values(values), presence(defined.combine(values))
300 template <typename Storage>
301 constexpr util::flags::BitMask<Storage>::BitMask(BitMaskFromValuesTag tag, Bits_t bits)
302 : BitMask(tag, bits, bits)
305 template <typename Storage>
306 constexpr util::flags::BitMask<Storage>::BitMask(BitMaskFromValuesTag tag,
309 : BitMask(tag, Bits_t(defined), Bits_t(values))
312 template <typename Storage>
313 constexpr util::flags::BitMask<Storage>::BitMask(BitMaskFromValuesTag tag, Storage_t values)
314 : BitMask(tag, Bits_t(values))
317 //------------------------------------------------------------------------------
318 template <typename Storage>
319 constexpr typename util::flags::BitMask<Storage>::Bits_t
320 util::flags::BitMask<Storage>::definedOnly() const
322 return values.select(presence);
325 //------------------------------------------------------------------------------
326 template <typename Storage>
327 constexpr size_t util::flags::BitMask<Storage>::capacity()
329 return sizeof(Storage) * 8;
332 //------------------------------------------------------------------------------
333 template <typename Storage>
334 constexpr bool util::flags::BitMask<Storage>::isDefined(Flag_t flag) const
336 return presence.any(flag);
339 template <typename Storage>
340 constexpr bool util::flags::BitMask<Storage>::isDefined(Bits_t bits) const
342 return presence.all(bits);
345 //------------------------------------------------------------------------------
346 template <typename Storage>
347 constexpr bool util::flags::BitMask<Storage>::isUndefined(Flag_t flag) const
349 return !isDefined(flag);
352 template <typename Storage>
353 constexpr bool util::flags::BitMask<Storage>::isUndefined(Bits_t bits) const
355 return !isDefined(bits);
358 //------------------------------------------------------------------------------
359 template <typename Storage>
360 constexpr bool util::flags::BitMask<Storage>::get(Flag_t flag) const
362 return values.any(flag);
365 //------------------------------------------------------------------------------
366 template <typename Storage>
367 constexpr bool util::flags::BitMask<Storage>::isSet(Flag_t flag) const
369 return get(flag) && isDefined(flag);
372 //------------------------------------------------------------------------------
373 template <typename Storage>
374 constexpr bool util::flags::BitMask<Storage>::isUnset(Flag_t flag) const
376 return !get(flag) && isDefined(flag);
379 //------------------------------------------------------------------------------
380 template <typename Storage>
381 constexpr bool util::flags::BitMask<Storage>::all(Bits_t bits) const
383 return isDefined(bits) && values.all(bits);
386 //------------------------------------------------------------------------------
387 template <typename Storage>
388 constexpr bool util::flags::BitMask<Storage>::any(Bits_t bits) const
390 // check values only for the flags in bits that are actually defined;
391 // values.any() will return true if no bit is specified,
392 // which is semantically correct but does not serve the scope here;
393 // if no bits are defined, this method should return false instead.
394 return values.any(presence.select(bits)) && !(presence.select(bits).empty());
397 //------------------------------------------------------------------------------
398 template <typename Storage>
399 constexpr bool util::flags::BitMask<Storage>::none(Bits_t bits) const
401 return isDefined(bits) && values.none(bits);
404 //------------------------------------------------------------------------------
405 template <typename Storage>
406 constexpr bool util::flags::BitMask<Storage>::anySet(Mask_t const& mask) const
408 return !definedOnly().select(mask.definedOnly()).empty() ||
409 mask.values.select(mask.presence).empty();
412 //------------------------------------------------------------------------------
413 template <typename Storage>
414 constexpr bool util::flags::BitMask<Storage>::noneSet(Mask_t const& mask) const
416 return !anySet(mask);
419 //------------------------------------------------------------------------------
420 template <typename Storage>
421 constexpr bool util::flags::BitMask<Storage>::match(Mask_t const& mask) const
423 // 1) no undefined flags that are defined in mask
424 // 2) all our flags defined also in mask must have the same values as in mask
425 return mask.presence.exclude(presence).empty() &&
426 values.select(mask.presence) == mask.definedOnly();
429 //------------------------------------------------------------------------------
430 template <typename Storage>
431 template <typename Stream>
432 void util::flags::BitMask<Storage>::dump(Stream&& out, unsigned int nBits) const
438 typename BitMask<Storage>::FlagIndex_t i = nBits;
439 out << details::flagChar(*this, --i);
442 if ((i % 4) == 3) out << ':';
443 out << details::flagChar(*this, i);
449 } // util::flags::BitMask<>::dump()
451 //------------------------------------------------------------------------------
452 template <typename Storage>
453 template <typename... Args>
454 constexpr typename util::flags::BitMask<Storage>::Mask_t util::flags::BitMask<Storage>::create(
457 return details::createMaskImpl(Mask_t(), args...);
460 //------------------------------------------------------------------------------
461 template <typename Storage>
462 void util::flags::BitMask<Storage>::defineSingle(Flag_t flag)
467 //------------------------------------------------------------------------------
468 template <typename Storage>
469 template <typename... Flags>
470 void util::flags::BitMask<Storage>::undefineImpl(Flag_t flag, Flags... others)
472 undefineSingle(flag);
473 undefineImpl(others...);
476 //------------------------------------------------------------------------------
477 template <typename Storage>
478 void util::flags::BitMask<Storage>::undefineSingle(Flag_t flag)
480 presence.unset(flag);
483 //------------------------------------------------------------------------------
484 template <typename Storage>
485 template <typename... Flags>
486 void util::flags::BitMask<Storage>::setImpl(Flag_t flag, Flags... others)
492 //------------------------------------------------------------------------------
493 template <typename Storage>
494 void util::flags::BitMask<Storage>::setSingle(Flag_t flag)
500 //------------------------------------------------------------------------------
501 template <typename Storage>
502 template <typename... Flags>
503 void util::flags::BitMask<Storage>::unsetImpl(Flag_t flag, Flags... others)
506 unsetImpl(others...);
509 //------------------------------------------------------------------------------
510 template <typename Storage>
511 void util::flags::BitMask<Storage>::unsetSingle(Flag_t flag)
517 //------------------------------------------------------------------------------
518 template <typename Storage>
519 template <typename BeginIter, typename EndIter>
520 void util::flags::BitMask<Storage>::rangeSet(BeginIter begin, EndIter end)
522 std::for_each(begin, end, [this](auto&& flag) { this->set(flag); });
525 //------------------------------------------------------------------------------
526 template <typename Storage>
527 template <typename BeginIter, typename EndIter>
528 void util::flags::BitMask<Storage>::rangeUnset(BeginIter begin, EndIter end)
530 std::for_each(begin, end, [this](auto&& flag) { this->unset(flag); });
533 //------------------------------------------------------------------------------
534 template <typename Storage>
535 constexpr typename util::flags::BitMask<Storage>::Mask_t
536 util::flags::BitMask<Storage>::mergeIntoMask(Mask_t baseMask, Mask_t mask)
538 return Mask_t(fromValues,
539 baseMask.presence.combine(mask.presence),
540 (baseMask.values.exclude(mask.presence)) | mask.values);
541 } // util::flags::BitMask<>::mergeIntoMask(Mask_t)
543 //------------------------------------------------------------------------------
544 template <typename Storage>
545 constexpr typename util::flags::BitMask<Storage>::Mask_t
546 util::flags::BitMask<Storage>::mergeIntoMask(Mask_t baseMask, Bits_t bits)
548 return Mask_t(fromValues, baseMask.presence.combine(bits), baseMask.values.combine(bits));
549 } // util::flags::BitMask<>::mergeIntoMask(Mask_t)
551 //------------------------------------------------------------------------------
552 template <typename Storage>
553 constexpr typename util::flags::BitMask<Storage>::Mask_t
554 util::flags::BitMask<Storage>::mergeIntoMask(Mask_t baseMask, Flag_t flags)
556 return mergeIntoMask(baseMask, Bits_t(flags));
559 //------------------------------------------------------------------------------
560 template <typename Storage>
561 constexpr typename util::flags::BitMask<Storage>::Mask_t
562 util::flags::BitMask<Storage>::combineWithMask(Mask_t A, Mask_t B)
564 return Mask_t(fromValues,
565 A.presence.combine(B.presence),
566 A.presence.combine(B.presence).select(A.values.combine(B.values)));
567 } // util::flags::BitMask<>::combineWithMask(Mask_t)
569 //------------------------------------------------------------------------------
570 template <typename Storage>
571 constexpr typename util::flags::BitMask<Storage>::Mask_t
572 util::flags::BitMask<Storage>::combineWithMask(Mask_t baseMask, Bits_t bits)
574 return mergeIntoMask(baseMask, bits);
577 //------------------------------------------------------------------------------
578 template <typename Storage>
579 constexpr typename util::flags::BitMask<Storage>::Mask_t
580 util::flags::BitMask<Storage>::combineWithMask(Mask_t baseMask, Flag_t flags)
582 return combineWithMask(baseMask, Bits_t(flags));
585 //------------------------------------------------------------------------------
586 template <typename Storage>
587 constexpr typename util::flags::BitMask<Storage>::Mask_t
588 util::flags::BitMask<Storage>::intersectWithMask(Mask_t A, Mask_t B)
591 // flags undefined in B are copied from A; for the others, B wins.
593 return Mask_t(fromValues,
594 A.presence.combine(B.presence),
595 // the bits that are defined in both get AND'ed:
596 A.presence.select(B.presence)
599 // the bits that are not, are copied:
600 .combine(A.values.combine(B.values).exclude(A.presence.select(B.presence))));
603 //------------------------------------------------------------------------------
604 template <typename Storage>
605 constexpr typename util::flags::BitMask<Storage>::Mask_t
606 util::flags::BitMask<Storage>::intersectWithMask(Mask_t baseMask, Bits_t bits)
608 // defined: (presentInA | B)
609 // values: (presentInA & B) & (valuesA & B) : if in both terms, use AND
610 // | (!(presentInA & B) & (valuesA | B) : otherwise, set from either
611 return Mask_t(fromValues,
612 baseMask.presence.combine(bits),
613 // the bits that are defined in both get AND'ed:
614 baseMask.presence.select(bits)
615 .select(baseMask.values)
616 // the bits that are not, are copied:
617 .combine(baseMask.values.combine(bits).exclude(baseMask.presence.select(bits))));
618 } // util::flags::BitMask<>::intersectWithMask(Mask_t)
620 //------------------------------------------------------------------------------
621 template <typename Storage>
622 constexpr typename util::flags::BitMask<Storage>::Mask_t
623 util::flags::BitMask<Storage>::intersectWithMask(Mask_t baseMask, Flag_t flags)
625 return intersectWithMask(baseMask, Bits_t(flags));
628 //------------------------------------------------------------------------------
629 template <typename Storage>
630 constexpr typename util::flags::BitMask<Storage>::Mask_t util::flags::BitMask<Storage>::unsetMask(
636 baseMask.presence.combine(mask.presence),
637 baseMask.presence.combine(mask.presence).select(baseMask.values.exclude(mask.values)));
640 //------------------------------------------------------------------------------
641 template <typename Storage>
642 constexpr typename util::flags::BitMask<Storage>::Mask_t util::flags::BitMask<Storage>::unsetMask(
646 return Mask_t(fromValues, baseMask.presence.combine(bits), baseMask.values.exclude(bits));
647 } // util::flags::BitMask<>::unsetMask(Mask_t)
649 //------------------------------------------------------------------------------
650 template <typename Storage>
651 constexpr typename util::flags::BitMask<Storage>::Mask_t util::flags::BitMask<Storage>::unsetMask(
655 return unsetMask(baseMask, Bits_t(flags));
658 //------------------------------------------------------------------------------
659 template <typename Storage>
660 constexpr typename util::flags::BitMask<Storage>::Mask_t util::flags::BitMask<Storage>::negateMask(
663 return Mask_t(fromValues, mask.presence, mask.presence.select(mask.values.invert()));
666 //------------------------------------------------------------------------------
667 template <typename Storage>
668 constexpr typename util::flags::BitMask<Storage>::Mask_t util::flags::BitMask<Storage>::negateMask(
671 return Mask_t(fromValues, bits, Bits_t(0));
674 template <typename Storage>
675 constexpr typename util::flags::BitMask<Storage>::Mask_t util::flags::BitMask<Storage>::negateMask(
678 return negateMask(Bits_t(flags));
681 //------------------------------------------------------------------------------
682 //--- free functions and operators
684 template <typename Storage>
685 constexpr util::flags::BitMask<Storage> util::flags::makeMask(Bits_t<Storage> bits)
687 return BitMask<Storage>(BitMask<Storage>::fromValues, bits);
690 //------------------------------------------------------------------------------
691 template <typename Storage>
692 constexpr util::flags::BitMask<Storage> util::flags::operator|(BitMask<Storage> left,
693 BitMask<Storage> right)
695 return BitMask<Storage>::combineWithMask(left, right);
698 template <typename Storage>
699 constexpr util::flags::BitMask<Storage> util::flags::operator|(
700 BitMask<Storage> left,
701 typename BitMask<Storage>::Bits_t right)
703 return BitMask<Storage>::combineWithMask(left, right);
706 template <typename Storage>
707 constexpr util::flags::BitMask<Storage> util::flags::operator|(
708 typename BitMask<Storage>::Bits_t left,
709 BitMask<Storage> right)
711 return BitMask<Storage>::combineWithMask(right, left);
714 //------------------------------------------------------------------------------
715 template <typename Storage>
716 constexpr util::flags::BitMask<Storage> util::flags::operator&(BitMask<Storage> left,
717 BitMask<Storage> right)
719 return BitMask<Storage>::intersectWithMask(left, right);
722 template <typename Storage>
723 constexpr util::flags::BitMask<Storage> util::flags::operator&(
724 BitMask<Storage> left,
725 typename BitMask<Storage>::Bits_t right)
727 return BitMask<Storage>::intersectWithMask(left, right);
730 template <typename Storage>
731 constexpr util::flags::BitMask<Storage> util::flags::operator&(
732 typename BitMask<Storage>::Bits_t left,
733 BitMask<Storage> right)
735 return makeMask(left) & right;
738 template <typename Storage>
739 constexpr util::flags::BitMask<Storage> util::flags::operator&(Bits_t<Storage> left,
740 Bits_t<Storage> right)
742 return BitMask<Storage>(left) & right;
745 //------------------------------------------------------------------------------
746 template <typename Storage>
747 constexpr util::flags::BitMask<Storage> util::flags::operator+(BitMask<Storage> baseMask,
748 BitMask<Storage> mask)
750 return BitMask<Storage>::mergeIntoMask(baseMask, mask);
753 template <typename Storage>
754 constexpr util::flags::BitMask<Storage> util::flags::operator+(
755 BitMask<Storage> baseMask,
756 typename BitMask<Storage>::Bits_t bits)
758 return BitMask<Storage>::mergeIntoMask(baseMask, bits);
761 template <typename Storage>
762 constexpr util::flags::BitMask<Storage> util::flags::operator+(
763 typename BitMask<Storage>::Bits_t baseBits,
764 BitMask<Storage> mask)
766 return makeMask(baseBits) + mask;
769 //------------------------------------------------------------------------------
770 template <typename Storage>
771 constexpr util::flags::BitMask<Storage> util::flags::operator-(BitMask<Storage> baseMask,
772 BitMask<Storage> mask)
774 return BitMask<Storage>::unsetMask(baseMask, mask);
777 template <typename Storage>
778 constexpr util::flags::BitMask<Storage> util::flags::operator-(
779 BitMask<Storage> baseMask,
780 typename BitMask<Storage>::Bits_t bits)
782 return BitMask<Storage>::unsetMask(baseMask, bits);
785 template <typename Storage>
786 constexpr util::flags::BitMask<Storage> util::flags::operator-(
787 typename BitMask<Storage>::Bits_t baseBits,
788 BitMask<Storage> mask)
790 return makeMask(baseBits) - mask;
793 template <typename Storage>
794 constexpr util::flags::BitMask<Storage> util::flags::operator-(Bits_t<Storage> baseBits,
795 Bits_t<Storage> bits)
797 return makeMask(baseBits) - bits;
800 //------------------------------------------------------------------------------
801 template <typename Storage>
802 constexpr util::flags::BitMask<Storage> util::flags::operator+(BitMask<Storage> mask)
807 template <typename Storage>
808 constexpr util::flags::BitMask<Storage> util::flags::operator+(Bits_t<Storage> bits)
810 return makeMask(bits);
813 //------------------------------------------------------------------------------
814 template <typename Storage>
815 constexpr util::flags::BitMask<Storage> util::flags::operator-(Bits_t<Storage> bits)
817 return BitMask<Storage>::negateMask(makeMask(bits));
820 template <typename Storage>
821 constexpr util::flags::BitMask<Storage> util::flags::operator-(Flag_t<Storage> flag)
823 return -(Bits_t<Storage>(flag));
826 //------------------------------------------------------------------------------
827 template <typename Storage>
828 constexpr util::flags::BitMask<Storage> util::flags::operator~(BitMask<Storage> mask)
830 return BitMask<Storage>::negateMask(mask);
834 template <typename Storage>
835 constexpr BitMask<Storage> operator~ (typename Bits_t<Storage> bits)
836 { return ~BitMask<Storage>(bits); }
839 //------------------------------------------------------------------------------
840 template <typename Storage>
841 constexpr util::flags::BitMask<Storage> util::flags::Set(Flag_t<Storage> flag)
843 return BitMask<Storage>(BitMask<Storage>::fromValues, flag, flag);
846 template <typename Storage>
847 constexpr util::flags::BitMask<Storage> util::flags::Unset(Flag_t<Storage> flag)
849 return BitMask<Storage>(BitMask<Storage>::fromValues, flag, Bits_t<Storage>(0));
852 //------------------------------------------------------------------------------
854 #endif // LARDATAOBJ_UTILITIES_BITMASK_TCC