-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.cpp
114 lines (94 loc) · 3.56 KB
/
main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include <QFlags>
#include <QVarLengthArray>
#include <QDebug>
#include "boost/concept_check.hpp"
#include "boost/concept/assert.hpp"
enum Option {
NoOptions = 0x0,
ShowTabs = 0x1,
ShowAll = 0x2,
SqueezeBlank = 0x4,
PreLast = 1 << 30,
Last = 1 << 31
};
Q_DECLARE_FLAGS(Options, Option)
//Q_DECLARE_OPERATORS_FOR_FLAGS(Options)
enum MyEnum {bla=1 << 31};
//Q_DECLARE_FLAGS(MyEnums, MyEnum)
void shift(/*unsigned */int f = -1) {
do qDebug() << f;
while (f <<= 1);
}
template <typename T>
class qtvFlags : public QFlags<T>
{
public:
qtvFlags(const QFlags<T> & other) : QFlags<T>(other) {qDebug("*this: %d", 1u > *this);}
qtvFlags(T e) : QFlags<T>(e) {}
qtvFlags(QFlag value) : QFlags<T>(value) {}
qtvFlags() /*: QFlags() */{}
const T next(unsigned int m) const {
if (!m) m = 1;
else {
qDebug() << " mask:" << (m << 1);
// if ( (m <<= 1) > *this || !m ) return (T)0;
m <<= 1;
}
if (m > *this || !m) return (T)0; // check !m in case max enum flag set or *this==0
// is it better to move !m check here also? done..
// consider: 'm > *this | !m' to eliminate branching
while ( !( *this & m ) ) m <<= 1;
return (T)m;
}
class const_iterator : public std::iterator<std::forward_iterator_tag, const T> {
const qtvFlags<T>* /*const */i; // const avoiding gives us copy assignable class by default
unsigned int m;
public:
inline const_iterator(const qtvFlags<T>* const p) : i(p), m(0) {}
// inline const_iterator(/*const */const_iterator&) : i() {} // is_copy_constructible: false
// why only one of these always called?
inline const T& operator*() const { /*qDebug("rvalue");*/ return static_cast<const T>(m); }
// inline T& operator*() { qDebug("lvalue"); return reinterpret_cast<T&>(m); } // needed?
inline bool operator==(const const_iterator &o) const { return m == o.m /*&& i == o.i*/; }
inline bool operator!=(const const_iterator &o) const { return m != o.m /*|| i != o.i*/; }
inline const_iterator& operator++() { m = i->next(m); return *this;}
inline const_iterator operator++(int) { const const_iterator n(*this); m = i->next(m); return n; }
};
const_iterator begin() const { return ++const_iterator(this);}
const_iterator end() const { return const_iterator(this); }
};
Q_DECLARE_OPERATORS_FOR_FLAGS(qtvFlags<Option>)
Options myOpt(bla);
qtvFlags<Option> flags
(ShowTabs
// |SqueezeBlank
|PreLast
// |Last
)
;
int main()
{
myOpt|=NoOptions|ShowTabs;
qDebug() << flags << myOpt << '\n'
<< "is_copy_constructible:" << std::is_copy_constructible<qtvFlags<Option>::const_iterator>::value << '\n'
<< "is_copy_assignable:" << std::is_copy_assignable<qtvFlags<Option>::const_iterator>::value << '\n'
<< "is_destructible:" << std::is_destructible<qtvFlags<Option>::const_iterator>::value << '\n'
;
for ( Option n = flags.next(0); n; n = flags.next(n) )
qDebug() << n << '\n';
qDebug("\nforeach");
foreach (Option flag, flags) qDebug() << "value:" << flag << '\n';
/* Tests
*/
qtvFlags<Option>::const_iterator i(&flags), i1(i);
i1 = i;
i1 == i;
i1 != i;
// both of these call non-const '*' operator (lvalue) if provided
*i;
// *i = (Option)5;
++i;
++(i++);
// empty() test
BOOST_CONCEPT_ASSERT((boost::ForwardIterator<qtvFlags<Option>::const_iterator>));
}