gpt4 book ai didi

c++ - 在纯 C++ 中实现 Linux 内核的 __is_constexpr (ICE_P) 宏

转载 作者:太空狗 更新时间:2023-10-29 21:32:13 33 4
gpt4 key购买 nike

reading about 之后Martin Uecker 的 ICE_P 谓词的标准 C11 版本,我尝试用纯 C++ 实现它。 C11版本,使用_Generic选择如下:

#define ICE_P(x) _Generic((1? (void *) ((x)*0) : (int *) 0), int*: 1, void*: 0)

C++ 的明显做法是用模板和decltype 替换_Generic,例如:

template<typename T> struct is_ice_helper;
template<> struct is_ice_helper<void*> { enum { value = false }; };
template<> struct is_ice_helper<int*> { enum { value = true }; };

#define ICE_P(x) (is_ice_helper<decltype(1? (void *) ((x)*0) : (int *) 0)>::value)

但是,它失败了 simplest test .为什么它不能检测整型常量表达式?

最佳答案

这个问题很微妙。确定条件表达式的指针操作数的复合类型的规范在 C++ 中与 C 中的类似,所以它开始看起来很有希望:

(N4659) [expr.cond]

7 Lvalue-to-rvalue, array-to-pointer, and function-to-pointerstandard conversions are performed on the second and third operands.After those conversions, one of the following shall hold:

  • [...]

  • One or both of the second and third operands have pointer type; pointer conversions, function pointer conversions, and qualificationconversions are performed to bring them to their composite pointertype (Clause [expr]). The result is of the composite pointer type.

  • [...]

复合指针类型的缩减指定如下:

(N4659) [expr]

5 The composite pointer type of two operands p1 and p2 havingtypes T1 and T2, respectively, where at least one is a pointer orpointer to member type or std​::​nullptr_­t, is:

  • if both p1 and p2 are null pointer constants, std​::​nullptr_­t;
  • if either p1 or p2 is a null pointer constant, T2 or T1, respectively;
  • if T1 or T2 is “pointer to cv1 void” and the other type is “pointer to cv2 T”, where T is an object type or void, “pointer to cv12 void”,where cv12 is the union of cv1 and cv2;
  • [...]

因此,我们的 ICE_P 宏的结果取决于我们按顺序检查上面的哪一颗子弹。鉴于我们如何定义 is_ice_helper,我们知道复合类型不是 nullptr_t,否则我们会命中第一颗子弹,并且会由于缺少模板特化而出错.所以我们必须击中第 3 个项目符号,使谓词报告为假。这一切似乎都取决于空指针常量的定义。

(N4659) [conv.ptr] (emphasis mine)

1 A null pointer constant is an integer literal with valuezero or a prvalue of type std​::​nullptr_­t. A null pointerconstant can be converted to a pointer type; the result is the nullpointer value of that type and is distinguishable from every othervalue of object pointer or function pointer type. Such a conversion iscalled a null pointer conversion. Two null pointer values of the sametype shall compare equal. The conversion of a null pointer constant toa pointer to cv-qualified type is a single conversion, and not thesequence of a pointer conversion followed by a qualificationconversion. A null pointer constant of integral type can be convertedto a prvalue of type std​::​nullptr_­t.

由于 (int*)0 不是上面定义的空指针常量,我们不符合 [expr]/5 的第一个项目符号。复合类型不是std::nullptr_t(void *) ((x)*0) 既不是空指针常量,也不能变成空指针常量。删除转换(定义不允许的东西)给我们留下 (x)*0。这是一个值为零的整数常量表达式。但它不是一个值为零的整数文字! C++中空指针常量的定义与C中的有所不同!

(N1570) 6.3.2.3 Pointers

3 An integer constant expression with the value 0, or such anexpression cast to type void *, is called a null pointer constant. Ifa null pointer constant is converted to a pointer type, the resultingpointer, called a null pointer, is guaranteed to compare unequal to apointer to any object or function.

C 允许任意 值为零的常量表达式形成空指针常量,而 C++ 需要整数文字。鉴于 C++ 对计算各种文字类型的常量表达式的丰富支持,这似乎是一个不必要的限制。并且使上述 ICE_P 方法成为 C++ 中的非入门者。

关于c++ - 在纯 C++ 中实现 Linux 内核的 __is_constexpr (ICE_P) 宏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55780426/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com