1 /////////////////////////////////////////////////////////////////////////////
2 // Name: wx/private/flagscheck.h
3 // Purpose: helpers for checking that (bit)flags don't overlap
4 // Author: Vaclav Slavik
7 // Copyright: (c) 2008 Vaclav Slavik
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 #ifndef _WX_PRIVATE_FLAGSCHECK_H_
12 #define _WX_PRIVATE_FLAGSCHECK_H_
16 // IBM xlC 8 can't parse the template syntax
17 #if !defined(__IBMCPP__)
19 #include "wx/meta/if.h"
24 // These templates are used to implement wxADD_FLAG macro below.
26 // The idea is that we want to trigger *compilation* error if the flags
27 // overlap, not just runtime assert failure. We can't implement the check
28 // using just a simple logical operation, we need checks equivalent to this
32 // assert( (mask & wxFLAG_2) == 0 ); // no overlap
34 // assert( (mask & wxFLAG_3) == 0 ); // no overlap
38 // This can be done at compilation time by using templates metaprogramming
39 // technique that makes the compiler carry on the computation.
41 // NB: If any of this doesn't compile with your compiler and would be too
42 // hard to make work, it's probably best to disable this code and replace
43 // the macros below with empty stubs, this isn't anything critical.
45 template<int val
> struct FlagsHaveConflictingValues
47 // no value here - triggers compilation error
50 template<int val
> struct FlagValue
55 // This template adds its template parameter integer 'add' to another integer
56 // 'all' and produces their OR-combination (all | add). The result is "stored"
57 // as constant SafelyAddToMask<>::value. Combination of many flags is achieved
58 // by chaining parameter lists: the 'add' parameter is value member of
59 // another (different) SafelyAddToMask<> instantiation.
60 template<int all
, int add
> struct SafelyAddToMask
62 // This typedefs ensures that no flags in the list conflict. If there's
63 // any overlap between the already constructed part of the mask ('all')
64 // and the value being added to it ('add'), the test that is wxIf<>'s
65 // first parameter will be non-zero and so Added value will be
66 // FlagsHaveConflictingValues<add>. The next statement will try to use
67 // AddedValue::value, but there's no such thing in
68 // FlagsHaveConflictingValues<> and so compilation will fail.
69 typedef typename wxIf
<(all
& add
) == 0,
71 FlagsHaveConflictingValues
<add
> >::value
74 enum { value
= all
| AddedValue::value
};
77 } // wxPrivate namespace
81 // This macro is used to ensure that no two flags that can be combined in
82 // the same integer value have overlapping bits. This is sometimes not entirely
83 // trivial to ensure, for example in wxWindow styles or flags for wxSizerItem
84 // that span several enums, some of them used for multiple purposes.
86 // By constructing allowed flags mask using wxADD_FLAG macro and then using
87 // this mask to check flags passed as arguments, you can ensure that
89 // a) if any of the allowed flags overlap, you will get compilation error
90 // b) if invalid flag is used, there will be an assert at runtime
94 // static const int SIZER_FLAGS_MASK =
95 // wxADD_FLAG(wxCENTRE,
96 // wxADD_FLAG(wxHORIZONTAL,
97 // wxADD_FLAG(wxVERTICAL,
101 // And wherever flags are used:
103 // wxASSERT_VALID_FLAG( m_flag, SIZER_FLAGS_MASK );
105 #define wxADD_FLAG(f, others) \
106 ::wxPrivate::SafelyAddToMask<f, others>::value
109 #define wxADD_FLAG(f, others) (f | others)
112 // Checks if flags value 'f' is within the mask of allowed values
113 #define wxASSERT_VALID_FLAGS(f, mask) \
114 wxASSERT_MSG( (f & mask) == f, \
115 "invalid flag: not within " #mask )
117 #endif // _WX_PRIVATE_FLAGSCHECK_H_