检测Sfinae POD类型的第一成员
Detecting first member of POD types for SFINAE
给定一些与此类似的POD结构:
struct StandardHeader
{
uint32_t field1;
uint32_t field2;
};
struct TypeA
{
StandardHeader Header;
uint8_t field3;
};
struct TypeB
{
StandardHeader Header;
uint16_t field4;
};
我想编写一种类型特征(或最终可以在static_assert
和std::enable_if
中使用的类似特征或以其他方式禁用模板方法(,该方法可以检测到StandardHeader
字段的存在为标准布局类型的第一个成员 - IE。因此reinterpret_cast<StandardHeader*>(&instance)
是安全的。
(从本质上讲, is-a 基本类型检查,除了类型必须是Pods,如果我使用实际的C 继承,那将是正确的。(
我能够写一些使用检测成语来验证该类型是标准布局的东西,并且具有正确类型的Header
成员:
template<typename, typename = std::void_t<>>
struct HasStandardHeader : std::false_type {};
template<typename T>
struct HasStandardHeader<T,
std::void_t<decltype(std::declval<T>().Header)>>
: std::conditional_t<
std::is_standard_layout_v<T> &&
std::is_same_v<decltype(std::declval<T>().Header), StandardHeader>
, std::true_type, std::false_type> {};
以上部分有效,但没有验证该字段是第一个。
我试图沿此表达式添加一些东西以检测到这一点,但它不起作用:
static_cast<uint8_t*>(&static_cast<T*>(0)->Header) - static_cast<uint8_t*>(0)) == 0
(涉及调用constexpr bool
方法的其他失败尝试,但可悲的是,这些尝试在conditional_t
中似乎无效。或者至少在使用&
或其他情况下不有效。(
理想情况下,我更喜欢只能检测到正确类型的字段的东西,甚至不需要将其命名为Header
。那可能吗?并且有更好的改写上述方法吗?
如前所述,最终目标是制作此方法:
template<typename T>
bool Process(T& data, size_t len);
如果T
不是具有正确的第一个成员的POD类型,则消失或static_assert
。
edit :看起来我可能已经过度复杂了一点。添加此表达式使其正常工作:
offsetof(T, Header) == 0
但是现在:
- 有更好的写作方法吗?
- 是否可以写这篇文章,以使我们不需要该字段被称为
Header
?
只需检查成员的偏移。
template<typename, typename = std::void_t<>>
struct HasStandardHeader : std::false_type {};
template<typename T>
struct HasStandardHeader<T,
std::void_t<decltype(std::declval<T>().Header)>>
: std::conditional_t<
std::is_standard_layout<T>::value &&
std::is_same<decltype(std::declval<T>().Header), StandardHeader>::value &&
offsetof(T, Header) == 0
, std::true_type, std::false_type> {};
在Godbolt上进行了一些测试。
相关文章:
- 根据模板类型选择类模板的成员类型?
- 函数模板签名中忽略的成员类型def 的访问说明符
- 在C++如何从数组中提取成员并返回成员类型的数组?
- C++从成员类型中扣除类型的功能模板?
- 无法初始化以 std::byte 作为成员类型的位字段
- 构造函数可以更改默认成员类型吗?
- 使用相同方法但不同成员类型构建类的最佳方法
- 允许通过指向方法的成员参数的指针来推断模板参数所指向的成员类型
- 使用 std::条件根据模板参数选择成员类型
- CRTP:如何推断要用作返回类型的成员类型?
- 对成员类型的成员方法使用 std::result_of<>
- C :可以从类及其受保护的成员类型继承可以继承吗?
- 如何在不指定不必要的模板参数的情况下使用模板类的成员类型
- 基类数据成员类型取决于派生类
- C 多态性:允许模棱两可的成员类型
- 使用使用成员类型别名的构造函数来推论类模板参数
- 获取与在模板参数中传递的函数成员类型相同的类
- 如果静态成员未初始化并且成员类型是类本身,该怎么办?
- boost::bind 无法绑定到纯虚拟基类中定义的非静态函数模板成员类型
- 将联合强制转换为其成员类型之一