Ich habe diese Pseudo bitfield Umsetzung:Wie macht man dieses "template/constexpr" Konstrukt eleganter/weniger wortreich?
class Field {
public:
constexpr Field(int i, int s) : index(i), size(s) {}
constexpr Field(const Field & prev, int s) : index(prev.index + prev.size), size(s) {}
int index, size;
};
#define FIELD(name, i, s) constexpr static const Field name = {i, s};
template<typename T = quint32>
class Flags {
public:
Flags(T d = 0) : data(d) {}
inline T readField(const Field & f) {
return (data & getMask(f.index, f.size)) >> f.index;
}
inline void writeField(const Field & f, T val) {
data = (data & setMask(f.index, f.size)) | (val << f.index);
}
private:
static constexpr T getMask(int i, int size) {
return ((1 << size) - 1) << i;
}
static constexpr T setMask(int pos, int size) {
return ~getMask(pos, size);
}
T data;
};
Allerdings ist es ziemlich ausführliches in seiner jetzigen Form zu verwenden:
struct Test {
Flags<> flags;
FIELD(one, 0, 1)
FIELD(two, one, 2)
};
Test t;
t.flags.readField(t.one);
t.flags.writeField(t.one, 1);
Ich mag wäre es eleganter zu machen, so dass anstelle der Syntax oben ich dies einfach tun:
t.one.read();
t.one.write(1);
Die Art und Weise habe ich versucht, für jeden Field
eine Flags &
zu tun haben, ist dies und implementieren read()
und write()
Methoden, die intern die Flags
Ziele verwenden.
Dies erfordert jedoch, dass die Field
auch eine Vorlage gemacht wird, die die Ausführlichkeit weiter erhöht, jetzt muss auch ein T
für die Felder angegeben werden.
Ich versuchte T
angegeben implizit ein Flags<T>::makeField()
verwendet wird, hat aber es wurde bald ein Chaos der Inkompatibilität zwischen constexprt
, static
und ordentlichen Mitgliedern und Methoden, auto
und so weiter, so dass nach im Kreis endlich eine Beratung von Menschen zu suchen, entschied mit mehr Erfahrung.
Natürlich gibt es die Anforderung, dass Fields
Laufzeitspeicher nicht aufnehmen und so viele mögliche Ausdrücke während der Kompilierung aufgelöst werden.
Ich denke nicht, die Syntax Sie wollen Nutzung ist möglich. Da die Felder statisch sind, können sie ihren Kontext nicht kennen. Es gibt also keine Möglichkeit, eine Funktion auf dem Feld zu haben, die mit einer Flags-Instanz funktioniert, ohne dass es ihnen mitgeteilt wird. In ähnlicher Weise zeigt die Art, wie Sie es in der ersten Instanz hatten, die Kehrseite - die Flags müssten angegeben werden, welches Feld verwendet werden soll. – qeadz
@qeadz - seien Sie mein Gast, ich interessiere mich nicht für die tatsächlichen Implementierungsdetails, alles was mich interessiert ist, dass es keine zusätzlichen Laufzeitkosten hat und ordentlich in seiner Syntax ist. Es muss während des Kompilierens gelöst werden, und außen hübsch aussehen, drinnen ist es mir egal, auch wenn es ein Durcheinander ist :) –
Ja Entschuldigung, ich habe meinen Kommentar zurückgezogen, weil ich bei weiterer Überlegung nicht sicher bin, ob der Compiler in der Lage sein wird um eine Menge von Lese-/Schreibvorgängen zur Kompilierzeit zu reduzieren, wenn das Endergebnis bekannt sein könnte, und dies ist ein notwendiges Merkmal. – qeadz