代码之家  ›  专栏  ›  技术社区  ›  Swiss Frank

如何通过引用传入位字段

  •  2
  • Swiss Frank  · 技术社区  · 4 年前

    请注意,已经存在一个标题几乎完全相同的问题,但问的是一个非常不同的问题。

    假设我想要一个接受位字段引用或指针作为参数的方法。这是不合法的,但也许举个例子可以澄清:

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

    我可以把Bar写成宏:

    #define BAR( pfoo, field ) ( ( (pfoo)->field = (pfoo)->a ), true )
    
    Foo foo;
    if ( BAR( &foo, b ) )
        exit( EXIT_SUCCESS );
    

    在许多地方,你可以用C编写这样的宏,现在你可以用函数模板来处理。在C++11或更高版本中,是否有合法编写上述Bar()方法的模板解决方案?

    0 回复  |  直到 4 年前
        1
  •  2
  •   n. m. could be an AI    4 年前

    有可能以一种相当低效和迂回的方式拼凑出一些充当比特场参考的东西。

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

    它可以这样使用

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

    还有可能摆脱 get set 通过定义转换运算符和赋值运算符(以及与之相关的所有复合赋值),为了简洁起见,省略了这一点。