1 ////////////////////////////////////////////////////////////////////////////////
3 // Copyright (c) 2009 by Fedor Pikus & Rich Sposato
4 // The copyright on this file is protected under the terms of the MIT license.
6 // Permission to use, copy, modify, distribute and sell this software for any
7 // purpose is hereby granted without fee, provided that the above copyright
8 // notice appear in all copies and that both that copyright notice and this
9 // permission notice appear in supporting documentation.
11 // The author makes no claims about the suitability of this software for any
12 // purpose. It is provided "as is" without express or implied warranty.
13 ////////////////////////////////////////////////////////////////////////////////
18 #ifndef LOKI_INCLUDED_SAFE_BIT_FIELDS_H
19 #define LOKI_INCLUDED_SAFE_BIT_FIELDS_H
23 #include <loki/static_check.h>
30 ==========================================================================================================================================
31 SafeBitField - type-safe class for bit fields.
32 SafeBitConst - type-safe class for bit constants.
33 SafeBitField is designed to be a [almost] drop-in replacement for integer flags and bit fields where individual bits are set and checked
34 using symbolic names for flags:
36 typedef unsigned long Labels_t;
38 const Labels_t Label_A = 0x00000001;
39 const Labels_t Label_B = 0x00000002;
42 if ( labels & Label_A ) { ... }
44 Such code offers no protection against mismatching bit constants and bit fields:
46 typedef unsigned long Kinds_t;
48 const Kinds_t Kind_A = 0x00000004;
50 if ( kinds & Label_A ) { ... } // Error but compiles
52 SafeBitField is a drop-in replacement which generates a unique type for each bit field. Bit fields of different types cannot be applied
55 LOKI_BIT_FIELD( unsigned long ) Labels_t;
57 LOKI_BIT_CONST( Labels_t, Label_A, 1 ); // 0x0001 - 1st bit is set
58 LOKI_BIT_CONST( Labels_t, Label_B, 2 ); // 0x0002 - 1st bit is set
60 LOKI_BIT_FIELD( unsigned long ) Kinds_t;
62 LOKI_BIT_CONST( Kinds_t, Kind_A, 3 ); // 0x0004 - 1st bit is set
64 if ( kinds & Label_A ) { ... } // Does not compile
66 Several other kinds of bit field misuse are caught by safe bit fields:
68 if ( kinds & Kind_A == 0 ) { ... }
69 if ( kinds && Kind_A ) { ... }
71 There are few cases where drop-in replacement does not work:
73 1. Operations involving bit fields and unnamed integers. Usually the integer in question is 0:
75 Labels_t labels = 0; // No longer compiles
76 if ( ( labels & Label_A ) == 0 ) { ... } // Also does not compile
78 The solution is to use named bit constants, including the one for 0:
80 LOKI_BIT_CONST( Labels_t, Label_None, 0 ); // 0x0000 - No bit is set
81 Labels_t labels = Label_None; // Or just Labels_t labels; - constructor initializes to 0
82 if ( ( labels & Label_A ) == Label_None ) { ... } // // Or just if ( labels & Label_A ) { ... }
84 2. I/O and other operations which require integer variables and cannot be modified:
86 void write_to_db( unsigned int word );
88 write_to_db( labels ); // No longer compiles
90 This problem is solved by reinterpreting the bit fields as an integer, the user is responsible for using the right
93 write_to_db( *((Labels_t::bit_word_t*)(&labels)) );
95 ==========================================================================================================================================
98 /// @par Non-Templated Initialization.
99 /// Not all compilers support template member functions where the template
100 /// arguments are not deduced but explicitly specified. For these broken
101 /// compilers, a non-template make_bit_const() function is provided instead of
102 /// the template one. The only downside is that instead of compile-time checking
103 /// of the index argument, it does runtime checking.
104 #if defined(__SUNPRO_CC) || ( defined(__GNUC__) && (__GNUC__ < 3) )
105 #define LOKI_BIT_FIELD_NONTEMPLATE_INIT
108 /// @par Forbidding Conversions.
109 /// This incomplete type prevents compilers from instantiating templates for
110 /// type conversions which should not happen. This incomplete type must be a
111 /// template: if the type is incomplete at the point of template definition,
112 /// the template is illegal (although the standard allows compilers to accept
113 /// or reject such code, ยง14.6/, so some compilers will not issue diagnostics
114 /// unless template is instantiated). The standard-compliant way is to defer
115 /// binding to the point of instantiation by making the incomplete type itself
117 template < typename > struct Forbidden_conversion; // This struct must not be defined!
119 /// Forward declaration of the field type.
121 unsigned int unique_index,
122 typename word_t = unsigned long
123 > class SafeBitField;
125 ////////////////////////////////////////////////////////////////////////////////
126 /// \class SafeBitConst Bit constants.
127 /// This class defines a bit-field constant - a collection of unchanging bits
128 /// used to compare to bit-fields. Instances of this class are intended to act
129 /// as labels for bit-fields.
132 /// - This class provides operations used for comparisons and conversions, but
133 /// no operations which may modify the value.
134 /// - As a templated class, it provides type-safety so bit values and constants
135 /// used for different reasons may not be unknowingly compared to each other.
136 /// - The unique_index template parameter insures the unique type of each bit
137 /// bit-field. It shares the unique_index with a similar SafeBitField.
138 /// - Its operations only allow comparisons to other bit-constants and
139 /// bit-fields of the same type.
140 ////////////////////////////////////////////////////////////////////////////////
144 unsigned int unique_index,
145 typename word_t = unsigned long
151 /// Type of the bit field is available if needed.
152 typedef word_t bit_word_t;
153 /// Corresponding field type.
154 typedef SafeBitField< unique_index, word_t > field_t;
155 /// Typedef is not allowed in friendship declaration.
156 friend class SafeBitField< unique_index, word_t >;
158 // Static factory constructor, creates a bit constant with one bit set. The position of the bit is given by the template parameter,
159 // bit 1 is the junior bit, i.e. make_bit_const<1>() returns 1. Bit index 0 is a special case and returns 0.
160 // This function should be used only to initialize the static bit constant objects.
161 // This function will not compile if the bit index is outside the vaild range.
162 // There is also a compile-time assert to make sure the size of the class is the same as the size of the underlaying integer type.
163 // This assert could go into the constructor, but aCC does not seem to understand sizeof(SafeBitConst) in the constructor.
165 #ifndef LOKI_BIT_FIELD_NONTEMPLATE_INIT
166 template < unsigned int i > static SafeBitConst make_bit_const()
168 LOKI_STATIC_CHECK( i <= ( 8 * sizeof(word_t) ), Index_is_beyond_size_of_data );
169 LOKI_STATIC_CHECK( sizeof(SafeBitConst) == sizeof(word_t), Object_size_does_not_match_data_size );
170 // Why check for ( i > 0 ) again inside the shift if the shift
171 // can never be evaluated for i == 0? Some compilers see shift by ( i - 1 )
172 // and complain that for i == 0 the number is invalid, without
173 // checking that shift needs evaluating.
174 return SafeBitConst( ( i > 0 ) ? ( word_t(1) << ( ( i > 0 ) ? ( i - 1 ) : 0 ) ) : 0 );
177 static SafeBitConst make_bit_const( unsigned int i )
179 LOKI_STATIC_CHECK( sizeof(SafeBitConst) == sizeof(word_t), Object_size_does_not_match_data_size );
180 assert( i <= ( 8 * sizeof(word_t) ) ); // Index is beyond size of data.
181 // Why check for ( i > 0 ) again inside the shift if the shift
182 // can never be evaluated for i == 0? Some compilers see shift by ( i - 1 )
183 // and complain that for i == 0 the number is invalid, without
184 // checking that shift needs evaluating.
185 return SafeBitConst( ( i > 0 ) ? ( word_t(1) << ( ( i > 0 ) ? ( i - 1 ) : 0 ) ) : 0 );
189 /// Default constructor allows client code to construct bit fields on the stack.
190 SafeBitConst() : word( 0 ) {}
192 /// Copy constructor.
193 SafeBitConst( const SafeBitConst &rhs ) : word( rhs.word ) {}
195 /// Comparison operators which take a constant bit value.
196 bool operator == ( const SafeBitConst &rhs ) const
198 return word == rhs.word;
200 bool operator != ( const SafeBitConst &rhs ) const
202 return word != rhs.word;
204 bool operator < ( const SafeBitConst &rhs ) const
206 return word < rhs.word;
208 bool operator > ( const SafeBitConst &rhs ) const
210 return word > rhs.word;
212 bool operator <= ( const SafeBitConst &rhs ) const
214 return word <= rhs.word;
216 bool operator >= ( const SafeBitConst &rhs ) const
218 return word >= rhs.word;
221 /// Comparision operators for mutable bit fields.
222 bool operator == ( const field_t &rhs ) const
224 return word == rhs.word;
226 bool operator != ( const field_t &rhs ) const
228 return word != rhs.word;
230 bool operator < ( const field_t &rhs ) const
232 return word < rhs.word;
234 bool operator > ( const field_t &rhs ) const
236 return word > rhs.word;
238 bool operator <= ( const field_t &rhs ) const
240 return word <= rhs.word;
242 bool operator >= ( const field_t &rhs ) const
244 return word >= rhs.word;
247 /// Bitwise operations. Operation-assignment operators are not needed,
248 /// since bit constants cannot be changed after they are initialized.
249 const SafeBitConst operator | ( const SafeBitConst &rhs ) const
251 return SafeBitConst( word | rhs.word );
253 const SafeBitConst operator & ( const SafeBitConst &rhs ) const
255 return SafeBitConst( word & rhs.word );
257 const SafeBitConst operator ^ ( const SafeBitConst &rhs ) const
259 return SafeBitConst( word ^ rhs.word );
261 const SafeBitConst operator ~ ( void ) const
263 return SafeBitConst( ~word );
266 /// These bitwise operators return a bit-field instead of a bit-const.
267 field_t operator | ( const field_t &rhs ) const
269 return field_t( word | rhs.word );
271 field_t operator & ( const field_t &rhs ) const
273 return field_t( word & rhs.word );
275 field_t operator ^ ( const field_t &rhs ) const
277 return field_t( word ^ rhs.word );
280 /// The shift operators move bits inside the bit field. These are useful in
281 /// loops which act over bit fields and increment them.
282 const SafeBitConst operator << ( unsigned int s ) const
284 return SafeBitConst( word << s );
286 const SafeBitConst operator >> ( unsigned int s ) const
288 return SafeBitConst( word >> s );
291 /// Word size is also the maximum number of different bit fields for a given word type.
294 return ( 8 * sizeof( word_t ) );
299 /// Copy-assignment operator is not implemented since it does not make sense
300 /// for a constant object.
301 SafeBitConst operator = ( const SafeBitConst &rhs );
303 // Private constructor from an integer type.
304 explicit SafeBitConst( word_t init ) : word( init ) {}
306 /// This data stores a single bit value. It is declared const to enforce
307 // constness for all functions of this class.
310 // Here comes the interesting stuff: all the operators designed to
311 // trap unintended conversions and make them not compile.
312 // Operators below handle code like this:
313 // SafeBitField<1> label1;
314 // SafeBitField<2> label2;
315 // if ( label1 & label2 ) { ... }
317 // These operators are private, and will not instantiate in any
318 // event because of the incomplete Forbidden_conversion struct.
319 template < typename T > SafeBitConst operator|( T ) const
321 Forbidden_conversion< T > wrong;
324 template < typename T > SafeBitConst operator&( T ) const
326 Forbidden_conversion< T > wrong;
329 template < typename T > SafeBitConst operator^( T ) const
331 Forbidden_conversion< T > wrong;
334 template < typename T > SafeBitConst operator|=( T ) const
336 Forbidden_conversion< T > wrong;
339 template < typename T > SafeBitConst operator&=( T ) const
341 Forbidden_conversion< T > wrong;
344 template < typename T > SafeBitConst operator^=( T ) const
346 Forbidden_conversion< T > wrong;
350 // And the same thing for comparisons: private and unusable.
351 // if ( label1 == label2 ) { ... }
352 template < typename T > bool operator==( const T ) const
354 Forbidden_conversion< T > wrong;
357 template < typename T > bool operator!=( const T ) const
359 Forbidden_conversion< T > wrong;
362 template < typename T > bool operator<( const T ) const
364 Forbidden_conversion< T > wrong;
367 template < typename T > bool operator>( const T ) const
369 Forbidden_conversion< T > wrong;
372 template < typename T > bool operator<=( const T ) const
374 Forbidden_conversion< T > wrong;
377 template < typename T > bool operator>=( const T ) const
379 Forbidden_conversion< T > wrong;
385 ////////////////////////////////////////////////////////////////////////////////
386 /// \class SafeBitConst Bit constants.
387 /// This class defines a bit-field constant - a collection of unchanging bits
388 /// used to compare to bit-fields. Instances of this class are intended to
389 /// store bit values.
392 /// - This class provides operations used for comparisons and conversions, and
393 /// also operations which may safely modify the value.
394 /// - As a templated class, it provides type-safety so bit values and constants
395 /// used for different reasons may not be unknowingly compared to each other.
396 /// - The unique_index template parameter insures the unique type of each bit
397 /// bit-field. It shares the unique_index with a similar SafeBitConst.
398 /// - Its operations only allow comparisons to other bit-constants and
399 /// bit-fields of the same type.
400 ////////////////////////////////////////////////////////////////////////////////
404 unsigned int unique_index,
411 /// Type of the bit field is available if needed.
412 typedef word_t bit_word_t;
413 /// Corresponding field type.
414 typedef SafeBitConst< unique_index, word_t > const_t;
415 /// Typedef is not allowed in friendship declaration.
416 friend class SafeBitConst<unique_index, word_t>;
418 /// Default constructor allows client code to construct bit fields on the stack.
419 SafeBitField() : word( 0 ) {}
421 /// Copy constructor and assignment operators.
422 SafeBitField( const SafeBitField &rhs ) : word( rhs.word ) {}
423 SafeBitField &operator = ( const SafeBitField &rhs )
429 /// Copy constructor and assignment operators from constant bit fields.
430 SafeBitField( const const_t &rhs ) : word( rhs.word ) {}
431 SafeBitField &operator = ( const const_t &rhs )
437 /// These comparison operators act on bit-fields of the same type.
438 bool operator == ( const SafeBitField &rhs ) const
440 return word == rhs.word;
442 bool operator != ( const SafeBitField &rhs ) const
444 return word != rhs.word;
446 bool operator < ( const SafeBitField &rhs ) const
448 return word < rhs.word;
450 bool operator > ( const SafeBitField &rhs ) const
452 return word > rhs.word;
454 bool operator <= ( const SafeBitField &rhs ) const
456 return word <= rhs.word;
458 bool operator >= ( const SafeBitField &rhs ) const
460 return word >= rhs.word;
463 /// These comparison operators act on bit-constants of a similar type.
464 bool operator == ( const const_t &rhs ) const
466 return word == rhs.word;
468 bool operator != ( const const_t &rhs ) const
470 return word != rhs.word;
472 bool operator < ( const const_t &rhs ) const
474 return word < rhs.word;
476 bool operator > ( const const_t &rhs ) const
478 return word > rhs.word;
480 bool operator <= ( const const_t &rhs ) const
482 return word <= rhs.word;
484 bool operator >= ( const const_t &rhs ) const
486 return word >= rhs.word;
489 /// Bitwise operations that use bit-fields.
490 SafeBitField operator | ( const SafeBitField &rhs ) const
492 return SafeBitField( word | rhs.word );
494 SafeBitField operator & ( const SafeBitField &rhs ) const
496 return SafeBitField( word & rhs.word );
498 SafeBitField operator ^ ( const SafeBitField &rhs ) const
500 return SafeBitField( word ^ rhs.word );
502 SafeBitField operator ~ ( void ) const
504 return SafeBitField( ~word );
506 SafeBitField operator |= ( const SafeBitField &rhs )
509 return SafeBitField( *this );
511 SafeBitField operator &= ( const SafeBitField &rhs )
514 return SafeBitField( *this );
516 SafeBitField operator ^= ( const SafeBitField &rhs )
519 return SafeBitField( *this );
522 /// Bitwise operators that use bit-constants.
523 SafeBitField operator | ( const_t rhs ) const
525 return SafeBitField( word | rhs.word );
527 SafeBitField operator & ( const_t rhs ) const
529 return SafeBitField( word & rhs.word );
531 SafeBitField operator ^ ( const_t rhs ) const
533 return SafeBitField( word ^ rhs.word );
535 SafeBitField operator |= ( const_t rhs )
538 return SafeBitField( *this );
540 SafeBitField operator &= ( const_t rhs )
543 return SafeBitField( *this );
545 SafeBitField operator ^= ( const_t rhs )
548 return SafeBitField( *this );
551 // Conversion to bool.
552 // This is a major source of headaches, but it's required to support code like this:
553 // const static SafeBitConst<1> Label_value = SafeBitConst<1>::make_bit_const<1>();
554 // SafeBitField<1> label;
555 // if ( label & Label_value ) { ... } // Nice...
557 // The downside is that this allows all sorts of nasty conversions. Without additional precautions, bit fields of different types
558 // can be converted to bool and then compared or operated on:
559 // SafeBitField<1> label1;
560 // SafeBitField<2> label2;
561 // if ( label1 == label2 ) { ... } // Yuck!
562 // if ( label1 & label2 ) { ... } // Blech!
564 // It is somewhat safer to convert to a pointer, at least pointers to different types cannot be readilly compared, and there are no
565 // bitwise operations on pointers, but the conversion from word_t to a pointer can have run-time cost if they are of different size.
567 operator const bool() const
569 return ( 0 != word );
572 // Shift operators shift bits inside the bit field. Does not make
573 // sense, most of the time, except perhaps to loop over labels and
575 SafeBitField operator << ( unsigned int s )
577 return SafeBitField( word << s );
579 SafeBitField operator >> ( unsigned int s )
581 return SafeBitField( word >> s );
583 SafeBitField operator <<= ( unsigned int s )
588 SafeBitField operator >>= ( unsigned int s )
594 // Word size is also the maximum number of different bit fields for
595 // a given word type.
596 static size_t size( void )
598 return ( 8 * sizeof( word_t ) );
603 /// Private constructor from an integer type. Don't put too much stock into
604 /// explicit declaration, it's better than nothing but does not solve all
605 /// problems with undesired conversions because SafeBitField coverts to bool.
606 explicit SafeBitField( word_t init ) : word( init ) {}
608 /// This stores the bits.
611 // Here comes the interesting stuff: all the operators designed to
612 // trap unintended conversions and make them not compile.
613 // Operators below handle code like this:
614 // SafeBitField<1> label1;
615 // SafeBitField<2> label2;
616 // if ( label1 & label2 ) { ... }
618 // These operators are private, and will not instantiate in any
619 // event because of the incomplete Forbidden_conversion struct.
620 template < typename T > SafeBitField operator | ( T ) const
622 Forbidden_conversion< T > wrong;
625 template < typename T > SafeBitField operator & ( T ) const
627 Forbidden_conversion< T > wrong;
630 template < typename T > SafeBitField operator ^ ( T ) const
632 Forbidden_conversion< T > wrong;
635 template < typename T > SafeBitField operator |= ( T ) const
637 Forbidden_conversion< T > wrong;
640 template < typename T > SafeBitField operator &= ( T ) const
642 Forbidden_conversion< T > wrong;
645 template < typename T > SafeBitField operator ^= ( T ) const
647 Forbidden_conversion< T > wrong;
651 // And the same thing for comparisons:
652 // if ( label1 == label2 ) { ... }
653 template < typename T > bool operator == ( const T ) const
655 Forbidden_conversion< T > wrong;
658 template < typename T > bool operator != ( const T ) const
660 Forbidden_conversion< T > wrong;
663 template < typename T > bool operator < ( const T ) const
665 Forbidden_conversion< T > wrong;
668 template < typename T > bool operator > ( const T ) const
670 Forbidden_conversion< T > wrong;
673 template < typename T > bool operator <= ( const T ) const
675 Forbidden_conversion< T > wrong;
678 template < typename T > bool operator >= ( const T ) const
680 Forbidden_conversion< T > wrong;
685 // The above template member operators catch errors when the first
686 // argument to a binary operator is a label, but they don't work when
687 // the first argument is an integer and the second one is a label: the
688 // label converts to bool and the operator is performed on two integers.
689 // These operators catch errors like this:
690 // SafeBitField<1> label1;
691 // SafeBitField<2> label2;
692 // if ( !label1 & label2 ) { ... }
693 // where the first label is converted to bool (these errors cannot be
694 // caught by member operators of SafeBitField class because the first
695 // argument is not SafeBitField but bool.
697 // If used, these operators will not instantiate because of the
698 // incomplete Forbidden_conversion struct.
700 template < unsigned int unique_index, typename word_t >
701 inline SafeBitField< unique_index, word_t > operator & ( bool, SafeBitField< unique_index, word_t > rhs )
703 Forbidden_conversion<word_t> wrong;
707 template < unsigned int unique_index, typename word_t >
708 inline SafeBitField< unique_index, word_t > operator | ( bool, SafeBitField< unique_index, word_t > rhs )
710 Forbidden_conversion< word_t > wrong;
714 template < unsigned int unique_index, typename word_t >
715 inline SafeBitField< unique_index, word_t > operator ^ ( bool, SafeBitField< unique_index, word_t > rhs )
717 Forbidden_conversion< word_t > wrong;
721 template < unsigned int unique_index, typename word_t >
722 inline SafeBitField< unique_index, word_t > operator == ( bool, SafeBitField< unique_index, word_t > rhs )
724 Forbidden_conversion< word_t > wrong;
728 template < unsigned int unique_index, typename word_t >
729 inline SafeBitField< unique_index, word_t > operator != ( bool, SafeBitField< unique_index, word_t > rhs )
731 Forbidden_conversion< word_t > wrong;
735 // Finally, few macros. All macros are conditionally defined to use the SafeBitField classes if LOKI_SAFE_BIT_FIELD is defined. Otherwise,
736 // the macros fall back on the use of typedefs and integer constants. This provides no addititonal safety but allows the code to support the
737 // mixture of compilers which are broken to different degrees.
738 #define LOKI_SAFE_BIT_FIELD
740 // The first macro helps to declare new bit field types:
741 // LOKI_BIT_FIELD( ulong ) field_t;
742 // This creates a typedef field_t for SafeBitField<unique_index, ulong> where index is the current line number. Since line numbers __LINE__ are counted
743 // separately for all header files, this ends up being the same type in all files using the header which defines field_t.
744 #ifdef LOKI_SAFE_BIT_FIELD
745 #define LOKI_BIT_FIELD( word_t ) typedef SafeBitField<__LINE__, word_t>
747 #define LOKI_BIT_FIELD( word_t ) typedef word_t
748 #endif // LOKI_SAFE_BIT_FIELD
750 // The second macro helps to declare static bit constants:
751 // LOKI_BIT_CONST( field_t, Label_1, 1 );
752 // creates new bit field object named Label_1 of type field_t which represents the field with the 1st (junior) bit set.
753 #ifdef LOKI_SAFE_BIT_FIELD
754 #ifndef LOKI_BIT_FIELD_NONTEMPLATE_INIT
755 #define LOKI_BIT_CONST( field_t, label, bit_index ) \
756 static const field_t::const_t label = field_t::const_t::make_bit_const<bit_index>()
758 #define LOKI_BIT_CONST( field_t, label, bit_index ) \
759 static const field_t::const_t label = field_t::const_t::make_bit_const( bit_index )
760 #endif // LOKI_BIT_FIELD_NONTEMPLATE_INIT
762 inline size_t make_bit_const( size_t i )
764 return ( i > 0 ) ? ( size_t(1) << ( ( i > 0 ) ? ( i - 1 ) : 0 ) ) : 0;
766 #define LOKI_BIT_CONST( field_t, label, bit_index ) static const field_t label = make_bit_const( bit_index )
767 #endif // LOKI_SAFE_BIT_FIELD
769 // The third macro helps to declare complex bit constants which are combination of several bits:
770 // LOKI_BIT_CONSTS( field_t, Label12 ) = Label_1 | Label_2;
771 #ifdef LOKI_SAFE_BIT_FIELD
772 #define LOKI_BIT_CONSTS( field_t, label ) static const field_t::const_t label
774 #define LOKI_BIT_CONSTS( field_t, label ) static const field_t label
775 #endif // LOKI_SAFE_BIT_FIELD
777 // The fourth macro helps to declare the maximum number of bit constants for a given type:
778 // static const size_t count = LOKI_BIT_FIELD_COUNT( field_t );
779 // declared a variable "count" initialized to field_t::size()
780 #ifdef LOKI_SAFE_BIT_FIELD
781 #define LOKI_BIT_FIELD_COUNT( field_t ) field_t::size()
783 #define LOKI_BIT_FIELD_COUNT( field_t ) ( 8 * sizeof(field_t) )
784 #endif // LOKI_SAFE_BIT_FIELD
788 #endif // LOKI_INCLUDED_SAFE_BIT_FIELDS_H