c++-如何在C++编译时检测结构的成员是否为位域?

给定一个结构 S:

struct S {
  bool a : 1;
  bool b : 1;
};

如何确定S::aS::b是在编译时位字段?

我试图提出一个类似的宏,IsBitField(S, a)但很难将 SFINAE 应用到offsetof()addressof()(众所周知,每个位域的操作都是无效的)。

回答

首先,对于 SFINAE 解决方案,省略号重​​载技巧(使用表达式 SFINAE)仍然有效,我们只需要找到一个构造,它在应用于位域时格式错误,而在应用于普通成员时格式良好。

例如,如果成员是位域,则不能形成指向成员的指针。

所以我们可以这样写:

template <typename T>
struct is_bit_field_t {
    template <typename U>
    static constexpr bool helper(...) {
        return true;
    }
    template <typename U>
    static constexpr bool helper(decltype(&U::a) arg) {
        return false;
    }
    static constexpr bool value = helper<T>(nullptr); 
};

这将考验公众成员是否aU是位字段类型。解释:

  • 如果T::a是位域,则表达式decltype(&U::a)将是格式错误的,然后 SFINAE 会输出第二个重载。

现场演示:https : //godbolt.org/z/TTn8YPKW3


使用 C++20,这可以通过概念来完成,利用您无法获取位域地址的事实。

核心实现看起来像:

template <typename T>
concept A_IsBitField = !requires (T t) {
     { &t.a };
};

现场演示:https : //godbolt.org/z/W3jbosY93

如果你不想定义一个独立的概念,你可以使用requires表达式代替(使用 SFINAE 方法你别无选择,只能创建该结构)


当然,以上仅适用于名为 的成员a。如果您想与其他成员一起使用它,那么您需要重写 SFINAE 特征或概念,替换a为您想要的任何成员。如果您需要大量这些结构,您可以编写一个宏来帮助您生成这些结构。


以上是c++-如何在C++编译时检测结构的成员是否为位域?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>