Swiss Frank
Swiss Frank

Reputation: 2422

how to pass a bitfield in by reference

Note a question with nearly the exact same title already exists, but is asking a very different question.

Say I want a method that takes a bitfield reference or pointer as an argument. This isn't legal, but perhaps an example would clarify:

class Foo {

  unsigned a:2, b:2, c:2;

  bool Bar( unsigned* px:2 ) { *px = a; return true; };
}

Foo foo;
if ( foo.Bar( &foo.b ) )
    exit( EXIT_SUCCESS );

I could write Bar as a macro:

#define BAR( pfoo, field ) ( ( (pfoo)->field = (pfoo)->a ), true )

Foo foo;
if ( BAR( &foo, b ) )
    exit( EXIT_SUCCESS );

Many place where you'd write some such macro in C you can now handle with function templates. Is there a template solution to writing the above Bar() method legally in C++11 or later?

Upvotes: 2

Views: 744

Answers (1)

n. m. could be an AI
n. m. could be an AI

Reputation: 120041

It is possible to cobble up something that acts as a bitfield reference in a rather inefficient and roundabout way.

template<typename underlying>
struct bitfield_ref
{
    virtual underlying get() { return getter(); }
    virtual void set(underlying val) { setter(val); }
    bitfield_ref(std::function<underlying()> getter, std::function<void(underlying)> setter) :
      getter(getter), setter(setter) {}
    std::function<underlying()> getter;
    std::function<void(underlying)> setter;
};

#define BITFIELD_REF(s,m) bitfield_ref<decltype(s.m)>( \
      [&s]() { return s.m; }, \
      [&s](decltype(s.m) v) { s.m = v; })

It can be used this way

  struct moo
  {
      unsigned int a : 2;
      unsigned int b : 3;
  };

  unsigned int test(bitfield_ref<unsigned int> x)
  {
      x.set(3);
      return x.get() + 1;
  }

  int main()
  {
      moo m;
      std::cout << test(BITFIELD_REF(m, a)) << "\n";
  }

It is further possible to get rid of get and set by defining a conversion operator and an assignment operator (and all of the compound assignments to go with it), this is omitted for brevity.

Upvotes: 2

Related Questions