c++ - How to make this "template / constexpr" construct more elegant / less verbose? -


i have pseudo bitfield implementation:

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; }; 

however, quite verbose use in present form:

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); 

i make more elegant, instead of syntax above can this:

t.one.read(); t.one.write(1); 

the way tried have flags & each field , implement read() , write() methods use flags targets internally.

this requires field made template well, increased verbosity further, t has specified fields well.

i tried having t specified implicitly using flags<t>::makefield() became mess of incompatibility between constexprt, static , regular members , methods, auto , whatnot, after going in circles decided seek advice people more experience.

naturally, there requirement fields not take runtime storage , many possible expressions resolved during compile.

having absolutely no idea intent is, first suggestion use bitfield. it's thousand times simpler/faster/etc.

struct test {      unsigned long long 1 : 1;      unsigned long long 1 : 2; }; 

however, if want class, made fieldreference class appears vaguely match you're doing.

class:

#include <cassert> #include <type_traits> #include <cstddef>  template<class t, size_t offset_, size_t size_> struct fieldreference {     static const size_t offset = offset_;     static const size_t size = size_;     static const size_t mask = ~t(((~0)<<offset<<size)|((1<<offset)-1));      explicit fieldreference(t& f) :flags(&f) {}     operator t() const {return (flags[0]&mask)>>offset;}     fieldreference& operator=(t v) {         assert((v&~(mask>>offset))==0);         flags[0] &= ~mask;         flags[0] |= (v<<offset);         return *this;     } private:     t* flags; }; #define firstfield(flags,name,size) \     auto name() -> fieldreference<decltype(flags),0,size> {return fieldreference<decltype(flags),0,size>(flags);} \     fieldreference<std::add_const<decltype(flags)>::type,0,size> name() const {return fieldreference<std::add_const<decltype(flags)>::type,0,size>(flags);} #define field(flags,name,previous,size) \     auto name() -> fieldreference<decltype(flags),decltype(previous())::offset,size> {return fieldreference<decltype(flags),decltype(previous())::offset,size>(flags);} \     auto name() const -> fieldreference<std::add_const<decltype(flags)>::type,decltype(this->previous())::offset,size> {return fieldreference<std::add_const<decltype(flags)>::type,decltype(previous())::offset,size>(flags);} 

usage:

struct test {     unsigned long long flags = 0;     firstfield(flags,one,1);     field(flags,two,one,2); };  #include <iostream>  int main() {     test t;     t.one() = 1; //that seems less verbose     t.two() = 3;     std::cout << t.two();     return 0; } 

http://coliru.stacked-crooked.com/a/c027d9829ce05119

the fields don't take space whatsoever except while you're working on them, , take space of single pointer. offsets , sizes , masks calculated @ compile time, should faster code too.


Comments

Popular posts from this blog

node.js - Mongoose: Cast to ObjectId failed for value on newly created object after setting the value -

[C++][SFML 2.2] Strange Performance Issues - Moving Mouse Lowers CPU Usage -

ios - Possible to get UIButton sizeThatFits to work? -