]> git.cworth.org Git - vogl/blob - src/extlib/loki/include/loki/SafeBits.h
Initial vogl checkin
[vogl] / src / extlib / loki / include / loki / SafeBits.h
1 ////////////////////////////////////////////////////////////////////////////////
2 // The Loki Library
3 // Copyright (c) 2009 by Fedor Pikus & Rich Sposato
4 // The copyright on this file is protected under the terms of the MIT license.
5 //
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.
10 //
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 ////////////////////////////////////////////////////////////////////////////////
14
15 // $Id$
16
17
18 #ifndef LOKI_INCLUDED_SAFE_BIT_FIELDS_H
19 #define LOKI_INCLUDED_SAFE_BIT_FIELDS_H
20
21 #include <cstdlib>
22 #include <assert.h>
23 #include <loki/static_check.h>
24
25
26 namespace Loki
27 {
28
29 /*
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:
35
36       typedef unsigned long Labels_t;
37       Labels_t labels;
38       const Labels_t Label_A = 0x00000001;
39       const Labels_t Label_B = 0x00000002;
40       ...
41       labels |= Label_B;
42       if ( labels & Label_A ) { ... }
43
44    Such code offers no protection against mismatching bit constants and bit fields:
45
46       typedef unsigned long Kinds_t;
47       Kinds_t kinds;
48       const Kinds_t Kind_A = 0x00000004;
49       ...
50       if ( kinds & Label_A ) { ... } // Error but compiles
51
52    SafeBitField is a drop-in replacement which generates a unique type for each bit field. Bit fields of different types cannot be applied
53    to each other:
54
55       LOKI_BIT_FIELD( unsigned long ) Labels_t;
56       Labels_t labels;
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
59       ...
60       LOKI_BIT_FIELD( unsigned long ) Kinds_t;
61       Kinds_t kinds;
62       LOKI_BIT_CONST( Kinds_t, Kind_A, 3 );                                  // 0x0004 - 1st bit is set
63       ...
64       if ( kinds & Label_A ) { ... } // Does not compile
65
66    Several other kinds of bit field misuse are caught by safe bit fields:
67
68       if ( kinds & Kind_A == 0 ) { ... }
69       if ( kinds && Kind_A ) { ... }
70
71    There are few cases where drop-in replacement does not work:
72
73    1. Operations involving bit fields and unnamed integers. Usually the integer in question is 0:
74
75          Labels_t labels = 0;  // No longer compiles
76          if ( ( labels & Label_A ) == 0 ) { ... } // Also does not compile
77
78       The solution is to use named bit constants, including the one for 0:
79
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 ) { ... }
83
84    2. I/O and other operations which require integer variables and cannot be modified:
85
86          void write_to_db( unsigned int word );
87          Labels_t labels;
88          write_to_db( labels ); // No longer compiles
89
90       This problem is solved by reinterpreting the bit fields as an integer, the user is responsible for using the right
91       type of integer:
92
93          write_to_db( *((Labels_t::bit_word_t*)(&labels)) );
94
95    ==========================================================================================================================================
96 */
97
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
106 #endif
107
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
116 /// a template.
117 template < typename > struct Forbidden_conversion;  // This struct must not be defined!
118
119 /// Forward declaration of the field type.
120 template <
121 unsigned int unique_index,
122          typename word_t = unsigned long
123          > class SafeBitField;
124
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.
130 ///
131 /// \par Safety
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 ////////////////////////////////////////////////////////////////////////////////
141
142 template
143 <
144 unsigned int unique_index,
145          typename word_t = unsigned long
146          >
147 class SafeBitConst
148 {
149 public:
150
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 >;
157
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.
164         //
165 #ifndef LOKI_BIT_FIELD_NONTEMPLATE_INIT
166         template < unsigned int i > static SafeBitConst make_bit_const()
167         {
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 );
175         }
176 #else
177         static SafeBitConst make_bit_const( unsigned int i )
178         {
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 );
186         }
187 #endif
188
189         /// Default constructor allows client code to construct bit fields on the stack.
190         SafeBitConst() : word( 0 ) {}
191
192         /// Copy constructor.
193         SafeBitConst( const SafeBitConst &rhs ) : word( rhs.word ) {}
194
195         /// Comparison operators which take a constant bit value.
196         bool operator == ( const SafeBitConst &rhs ) const
197         {
198                 return word == rhs.word;
199         }
200         bool operator != ( const SafeBitConst &rhs ) const
201         {
202                 return word != rhs.word;
203         }
204         bool operator <  ( const SafeBitConst &rhs ) const
205         {
206                 return word <  rhs.word;
207         }
208         bool operator >  ( const SafeBitConst &rhs ) const
209         {
210                 return word >  rhs.word;
211         }
212         bool operator <= ( const SafeBitConst &rhs ) const
213         {
214                 return word <= rhs.word;
215         }
216         bool operator >= ( const SafeBitConst &rhs ) const
217         {
218                 return word >= rhs.word;
219         }
220
221         /// Comparision operators for mutable bit fields.
222         bool operator == ( const field_t &rhs ) const
223         {
224                 return word == rhs.word;
225         }
226         bool operator != ( const field_t &rhs ) const
227         {
228                 return word != rhs.word;
229         }
230         bool operator <  ( const field_t &rhs ) const
231         {
232                 return word <  rhs.word;
233         }
234         bool operator >  ( const field_t &rhs ) const
235         {
236                 return word >  rhs.word;
237         }
238         bool operator <= ( const field_t &rhs ) const
239         {
240                 return word <= rhs.word;
241         }
242         bool operator >= ( const field_t &rhs ) const
243         {
244                 return word >= rhs.word;
245         }
246
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
250         {
251                 return SafeBitConst( word | rhs.word );
252         }
253         const SafeBitConst operator & ( const SafeBitConst &rhs ) const
254         {
255                 return SafeBitConst( word & rhs.word );
256         }
257         const SafeBitConst operator ^ ( const SafeBitConst &rhs ) const
258         {
259                 return SafeBitConst( word ^ rhs.word );
260         }
261         const SafeBitConst operator ~ ( void ) const
262         {
263                 return SafeBitConst( ~word );
264         }
265
266         /// These bitwise operators return a bit-field instead of a bit-const.
267         field_t operator | ( const field_t &rhs ) const
268         {
269                 return field_t( word | rhs.word );
270         }
271         field_t operator & ( const field_t &rhs ) const
272         {
273                 return field_t( word & rhs.word );
274         }
275         field_t operator ^ ( const field_t &rhs ) const
276         {
277                 return field_t( word ^ rhs.word );
278         }
279
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
283         {
284                 return SafeBitConst( word << s );
285         }
286         const SafeBitConst operator >> ( unsigned int s ) const
287         {
288                 return SafeBitConst( word >> s );
289         }
290
291         /// Word size is also the maximum number of different bit fields for a given word type.
292         static size_t size()
293         {
294                 return ( 8 * sizeof( word_t ) );
295         }
296
297 private:
298
299         /// Copy-assignment operator is not implemented since it does not make sense
300         /// for a constant object.
301         SafeBitConst operator = ( const SafeBitConst &rhs );
302
303         // Private constructor from an integer type.
304         explicit SafeBitConst( word_t init ) : word( init ) {}
305
306         /// This data stores a single bit value.  It is declared const to enforce
307         // constness for all functions of this class.
308         const word_t word;
309
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 ) { ... }
316
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
320         {
321                 Forbidden_conversion< T > wrong;
322                 return *this;
323         }
324         template < typename T > SafeBitConst operator&( T ) const
325         {
326                 Forbidden_conversion< T > wrong;
327                 return *this;
328         }
329         template < typename T > SafeBitConst operator^( T ) const
330         {
331                 Forbidden_conversion< T > wrong;
332                 return *this;
333         }
334         template < typename T > SafeBitConst operator|=( T ) const
335         {
336                 Forbidden_conversion< T > wrong;
337                 return *this;
338         }
339         template < typename T > SafeBitConst operator&=( T ) const
340         {
341                 Forbidden_conversion< T > wrong;
342                 return *this;
343         }
344         template < typename T > SafeBitConst operator^=( T ) const
345         {
346                 Forbidden_conversion< T > wrong;
347                 return *this;
348         }
349
350         // And the same thing for comparisons: private and unusable.
351         //    if ( label1 == label2 ) { ... }
352         template < typename T > bool operator==( const T ) const
353         {
354                 Forbidden_conversion< T > wrong;
355                 return true;
356         }
357         template < typename T > bool operator!=( const T ) const
358         {
359                 Forbidden_conversion< T > wrong;
360                 return true;
361         }
362         template < typename T > bool operator<( const T ) const
363         {
364                 Forbidden_conversion< T > wrong;
365                 return true;
366         }
367         template < typename T > bool operator>( const T ) const
368         {
369                 Forbidden_conversion< T > wrong;
370                 return true;
371         }
372         template < typename T > bool operator<=( const T ) const
373         {
374                 Forbidden_conversion< T > wrong;
375                 return true;
376         }
377         template < typename T > bool operator>=( const T ) const
378         {
379                 Forbidden_conversion< T > wrong;
380                 return true;
381         }
382 };
383
384
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.
390 ///
391 /// \par Safety
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 ////////////////////////////////////////////////////////////////////////////////
401
402 template
403 <
404 unsigned int unique_index,
405          typename word_t
406          >
407 class SafeBitField
408 {
409 public:
410
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>;
417
418         /// Default constructor allows client code to construct bit fields on the stack.
419         SafeBitField() : word( 0 ) {}
420
421         /// Copy constructor and assignment operators.
422         SafeBitField( const SafeBitField &rhs ) : word( rhs.word ) {}
423         SafeBitField &operator = ( const SafeBitField &rhs )
424         {
425                 word = rhs.word;
426                 return *this;
427         }
428
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 )
432         {
433                 word = rhs.word;
434                 return *this;
435         }
436
437         /// These comparison operators act on bit-fields of the same type.
438         bool operator == ( const SafeBitField &rhs ) const
439         {
440                 return word == rhs.word;
441         }
442         bool operator != ( const SafeBitField &rhs ) const
443         {
444                 return word != rhs.word;
445         }
446         bool operator <  ( const SafeBitField &rhs ) const
447         {
448                 return word <  rhs.word;
449         }
450         bool operator >  ( const SafeBitField &rhs ) const
451         {
452                 return word >  rhs.word;
453         }
454         bool operator <= ( const SafeBitField &rhs ) const
455         {
456                 return word <= rhs.word;
457         }
458         bool operator >= ( const SafeBitField &rhs ) const
459         {
460                 return word >= rhs.word;
461         }
462
463         /// These comparison operators act on bit-constants of a similar type.
464         bool operator == ( const const_t &rhs ) const
465         {
466                 return word == rhs.word;
467         }
468         bool operator != ( const const_t &rhs ) const
469         {
470                 return word != rhs.word;
471         }
472         bool operator <  ( const const_t &rhs ) const
473         {
474                 return word <  rhs.word;
475         }
476         bool operator >  ( const const_t &rhs ) const
477         {
478                 return word >  rhs.word;
479         }
480         bool operator <= ( const const_t &rhs ) const
481         {
482                 return word <= rhs.word;
483         }
484         bool operator >= ( const const_t &rhs ) const
485         {
486                 return word >= rhs.word;
487         }
488
489         /// Bitwise operations that use bit-fields.
490         SafeBitField operator |  ( const SafeBitField &rhs ) const
491         {
492                 return SafeBitField( word | rhs.word );
493         }
494         SafeBitField operator &  ( const SafeBitField &rhs ) const
495         {
496                 return SafeBitField( word & rhs.word );
497         }
498         SafeBitField operator ^  ( const SafeBitField &rhs ) const
499         {
500                 return SafeBitField( word ^ rhs.word );
501         }
502         SafeBitField operator ~  ( void ) const
503         {
504                 return SafeBitField( ~word );
505         }
506         SafeBitField operator |= ( const SafeBitField &rhs )
507         {
508                 word |= rhs.word;
509                 return SafeBitField( *this );
510         }
511         SafeBitField operator &= ( const SafeBitField &rhs )
512         {
513                 word &= rhs.word;
514                 return SafeBitField( *this );
515         }
516         SafeBitField operator ^= ( const SafeBitField &rhs )
517         {
518                 word ^= rhs.word;
519                 return SafeBitField( *this );
520         }
521
522         /// Bitwise operators that use bit-constants.
523         SafeBitField operator |  ( const_t rhs ) const
524         {
525                 return SafeBitField( word | rhs.word );
526         }
527         SafeBitField operator &  ( const_t rhs ) const
528         {
529                 return SafeBitField( word & rhs.word );
530         }
531         SafeBitField operator ^  ( const_t rhs ) const
532         {
533                 return SafeBitField( word ^ rhs.word );
534         }
535         SafeBitField operator |= ( const_t rhs )
536         {
537                 word |= rhs.word;
538                 return SafeBitField( *this );
539         }
540         SafeBitField operator &= ( const_t rhs )
541         {
542                 word &= rhs.word;
543                 return SafeBitField( *this );
544         }
545         SafeBitField operator ^= ( const_t rhs )
546         {
547                 word ^= rhs.word;
548                 return SafeBitField( *this );
549         }
550
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...
556         //
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!
563         //
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.
566         //
567         operator const bool() const
568         {
569                 return ( 0 != word );
570         }
571
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
574         // increment them.
575         SafeBitField operator <<  ( unsigned int s )
576         {
577                 return SafeBitField( word << s );
578         }
579         SafeBitField operator >>  ( unsigned int s )
580         {
581                 return SafeBitField( word >> s );
582         }
583         SafeBitField operator <<= ( unsigned int s )
584         {
585                 word <<= s;
586                 return *this;
587         }
588         SafeBitField operator >>= ( unsigned int s )
589         {
590                 word >>= s;
591                 return *this;
592         }
593
594         // Word size is also the maximum number of different bit fields for
595         // a given word type.
596         static size_t size( void )
597         {
598                 return ( 8 * sizeof( word_t ) );
599         }
600
601 private:
602
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 ) {}
607
608         /// This stores the bits.
609         word_t word;
610
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 ) { ... }
617
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
621         {
622                 Forbidden_conversion< T > wrong;
623                 return *this;
624         }
625         template < typename T > SafeBitField operator &  ( T ) const
626         {
627                 Forbidden_conversion< T > wrong;
628                 return *this;
629         }
630         template < typename T > SafeBitField operator ^  ( T ) const
631         {
632                 Forbidden_conversion< T > wrong;
633                 return *this;
634         }
635         template < typename T > SafeBitField operator |= ( T ) const
636         {
637                 Forbidden_conversion< T > wrong;
638                 return *this;
639         }
640         template < typename T > SafeBitField operator &= ( T ) const
641         {
642                 Forbidden_conversion< T > wrong;
643                 return *this;
644         }
645         template < typename T > SafeBitField operator ^= ( T ) const
646         {
647                 Forbidden_conversion< T > wrong;
648                 return *this;
649         }
650
651         // And the same thing for comparisons:
652         //    if ( label1 == label2 ) { ... }
653         template < typename T > bool operator == ( const T ) const
654         {
655                 Forbidden_conversion< T > wrong;
656                 return true;
657         }
658         template < typename T > bool operator != ( const T ) const
659         {
660                 Forbidden_conversion< T > wrong;
661                 return true;
662         }
663         template < typename T > bool operator <  ( const T ) const
664         {
665                 Forbidden_conversion< T > wrong;
666                 return true;
667         }
668         template < typename T > bool operator >  ( const T ) const
669         {
670                 Forbidden_conversion< T > wrong;
671                 return true;
672         }
673         template < typename T > bool operator <= ( const T ) const
674         {
675                 Forbidden_conversion< T > wrong;
676                 return true;
677         }
678         template < typename T > bool operator >= ( const T ) const
679         {
680                 Forbidden_conversion< T > wrong;
681                 return true;
682         }
683 };
684
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.
696 //
697 // If used, these operators will not instantiate because of the
698 // incomplete Forbidden_conversion struct.
699
700 template < unsigned int unique_index, typename word_t >
701 inline SafeBitField< unique_index, word_t > operator & ( bool, SafeBitField< unique_index, word_t > rhs )
702 {
703         Forbidden_conversion<word_t> wrong;
704         return rhs;
705 }
706
707 template < unsigned int unique_index, typename word_t >
708 inline SafeBitField< unique_index, word_t > operator | ( bool, SafeBitField< unique_index, word_t > rhs )
709 {
710         Forbidden_conversion< word_t > wrong;
711         return rhs;
712 }
713
714 template < unsigned int unique_index, typename word_t >
715 inline SafeBitField< unique_index, word_t > operator ^ ( bool, SafeBitField< unique_index, word_t > rhs )
716 {
717         Forbidden_conversion< word_t > wrong;
718         return rhs;
719 }
720
721 template < unsigned int unique_index, typename word_t >
722 inline SafeBitField< unique_index, word_t > operator == ( bool, SafeBitField< unique_index, word_t > rhs )
723 {
724         Forbidden_conversion< word_t > wrong;
725         return rhs;
726 }
727
728 template < unsigned int unique_index, typename word_t >
729 inline SafeBitField< unique_index, word_t > operator != ( bool, SafeBitField< unique_index, word_t > rhs )
730 {
731         Forbidden_conversion< word_t > wrong;
732         return rhs;
733 }
734
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
739
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>
746 #else
747 #define LOKI_BIT_FIELD( word_t ) typedef word_t
748 #endif // LOKI_SAFE_BIT_FIELD
749
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>()
757 #else
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
761 #else
762 inline size_t make_bit_const( size_t i )
763 {
764         return ( i > 0 ) ? ( size_t(1) << ( ( i > 0 ) ? ( i - 1 ) : 0 ) ) : 0;
765 }
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
768
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
773 #else
774 #define LOKI_BIT_CONSTS( field_t, label ) static const field_t label
775 #endif // LOKI_SAFE_BIT_FIELD
776
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()
782 #else
783 #define LOKI_BIT_FIELD_COUNT( field_t ) ( 8 * sizeof(field_t) )
784 #endif // LOKI_SAFE_BIT_FIELD
785
786 } // namespace Loki
787
788 #endif // LOKI_INCLUDED_SAFE_BIT_FIELDS_H