Newsgroup: it.comp.lang.c++
Titolo: ancora sui bitfield

Saluti. Qualche giorno fa Griffini mi ha mostrato come
si puo' evitare l'uso dei bitfield per estrarre campi da 
posizioni precise e assegnate:
template<int address,    // Indirizzo del campo
           int bit,      // Bit di partenza
           int size>     // Dimensione
  struct BitField
  {
    operator int ()
    {
      return ((*(int *)address)>>bit)&((1<<size)-1);
    }
    void operator=(int x)
    {
      const int mask=~(((1<<size)-1)<<bit);
      int& v=*(int *)address;
      v = (v&mask)|(x<<bit);
    }
  };
Quello che mi chiedevo era se e' possibile estrarre
un campo formato a sua volta da due campi non adiacenti.
Per spiegarmi meglio usando i bitfield:
struct
{
    unsigned char low : 4;
    unsigned char foo1 : 3;
    unsigned char foo2: 7;
    unsigned char high: 4;
};
quello che vorrei e' accedere al campo formato
da low e high come se fossero consecutivi.
Esiste un modo generale per affrontare il problema?
Saluti e grazie  Manlio Perillo

da low e high come se fossero consecutivi.
Questo lo considero un esperimento sui template...
onestamente non metterei mai roba del genere in un
programma.
La tua semplice obiezione sui campi suddivisi in
piu' parti mi ha fatto capire che queste soluzioni
sono comunque piu' contorte e meno flessibili di una
bella e semplice coppia di routine inline get/set.
Intendo dire... se un campo e' rappresentato "negato" ?
Se lo e' una sua parte ? Se esiste un bit che dice
quale parte prendere ?
Sono tutti casi assolutamente banali da affrontare
(e da manutenere!) se si usa un paio di routine
inline esplicite e che invece aumentano la
complicazione nel voler usare template.
Anyway... questa e' una possibile soluzione template...
  #include <iostream>
  template<int pos,int sz>
  struct bitfield
  {
    enum { size = sz, 
           mask = (1<<sz)-1 };
    int& v;
    bitfield(int& v) : v(v) { }
 
    operator int()
    {
      return (v >> pos) & mask;
    }
    void operator=(int x)
    {
      v = v & ~(mask<<pos) | (x<<pos);
    }
  };
  template< class U,class V >
  struct cbitfield
  {
    U u;
    V v;
 
    enum { size = U::size+V::size, 
           mask = (1<<(U::size+V::size))-1 };
    cbitfield(const U& u,const V& v) : u(u),v(v) { }
 
    operator int()
    {
      return (int(u) << V::size) | int(v);
    }
 
    void operator=(int x)
    {
      u = (x >> V::size);
      v = (x & V::mask);
    }
  };
  // Helper
  template<class U,class V>
  inline cbitfield<U,V> cbitf(const U& u,const V& v)
  { return cbitfield<U,V>(u,v); }
  // Esempio d'uso
 
  struct X
  {
    int rep[2];
    // bit 0-3 dir rep[0] + bit 4-15 di rep[1]
    cbitfield< bitfield<0,4>, bitfield<4,12> >
      color()
      {
        return cbitf( bitfield<0,4>(rep[0]),
                      bitfield<4,12>(rep[1]) );
      }
    // bit 8-11 di rep[0] 
    //  + bit 12-19 di rep[1] 
    //  + bit 20-27 di rep[0]
    cbitfield< bitfield<8,4>,
               cbitfield< bitfield<12,8>,
                          bitfield<20,8> > >
      style()
      {
        return cbitf( bitfield<8,4>(rep[0]),
                      cbitf( bitfield<12,8>(rep[1]),
                             bitfield<20,8>(rep[0]) )
                    );
      }
  };
  int main()
  {
    X x; 
    x.rep[0] = 0x01234567;
    x.rep[1] = 0x09abcdef;
    std::cout << std::hex;
    std::cout << x.color() << std::endl; // 7cde
    std::cout << x.style() << std::endl; // 5bc12
    x.rep[0] = x.rep[1] = 0;
    x.style() = 0x0e2d3c;
    std::cout << x.rep[0] << "/" 
              << x.rep[1] << std::endl; // 3c00e00/2d000
  }
HTH
Andrea