首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >在纯__is_constexpr中实现Linux的ICE_P宏

在纯__is_constexpr中实现Linux的ICE_P宏
EN

Stack Overflow用户
提问于 2019-04-21 06:24:46
回答 1查看 424关注 0票数 6

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

代码语言:javascript
代码运行次数:0
运行
复制
#define ICE_P(x) _Generic((1? (void *) ((x)*0) : (int *) 0), int*: 1, void*: 0)

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

代码语言:javascript
代码运行次数:0
运行
复制
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)

然而,它失败了最简单测试。为什么它不能检测整数常量表达式?

EN

Stack Overflow用户

回答已采纳

发布于 2019-04-21 06:24:46

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

(N4659) expr.cond 在第二和第三个操作数上执行7值到rvalue、数组到指针以及函数到指针的标准转换.在这些转换之后,应持有下列一项规定:

  • ..。
  • 第二和第三个操作数中的一个或两个操作数都具有指针类型;执行指针转换、函数指针转换和限定转换,将它们转换为它们的复合指针类型(Clause expr)。结果是复合指针类型。
  • ..。

组合指针类型的简化如下所示:

(N4659) expr 5两个操作数p1和p2的复合指针类型分别具有T1和T2类型,其中至少有一个是指向成员类型或std​::​nullptr_­t的指针或指针,为:

  • 如果p1和p2都是空指针常量,则为std​::​nullptr_­t
  • 如果p1或p2是空指针常量,则分别为T2或T1;
  • 如果T1或T2是“指向cv1 void的指针”,而另一种类型是“指向cv2 T的指针”,其中T是对象类型或cv2,则为“cv12 void”,其中cv12是cv1和cv2的结合;
  • ..。

因此,我们的ICE_P宏的结果是由我们上面的哪一个子弹决定的,在检查每个子弹的顺序后,我们就会着陆一个。考虑到我们如何定义is_ice_helper,我们知道复合类型不是nullptr_t,否则我们就会命中第一个项目,并且会因为缺少模板专门化而得到一个错误。因此,我们必须命中3号符号,使谓词报告为假。这一切似乎都取决于空指针常量的定义。

(N4659) conv.ptr (重点雷) 1空指针常量是值为零的整数文本std​::​nullptr_­t类型的prvalue。可以将空指针常量转换为指针类型;结果是该类型的空指针值,并且与对象指针或函数指针类型的每个其他值都有区别。这种转换称为空指针转换。相同类型的两个空指针值应比较相等。将空指针常量转换为指针到cv限定类型的转换是一次转换,而不是指针转换的顺序,然后是限定转换。整数类型的空指针常量可以转换为std​::​nullptr_­t类型的prvalue。

由于根据上面的定义,(int*)0不是空指针常量,所以我们不限定expr/5的第一个符号,复合类型不是std::nullptr_t(void *) ((x)*0)既不是空指针常量,也不能转化为空指针常量。删除强制转换(定义不允许的内容)将留给我们(x)*0。这是一个值为零的整数常量表达式。但它不是值为零的整数字面值!C++中空指针常数的定义与C中的定义不同!

(N1570) 6.3.2.3指针 3.值为0的整数常量表达式或转换为void *类型的此类表达式称为空指针常量。如果将空指针常量转换为指针类型,则保证结果指针(称为空指针)与指向任何对象或函数的指针不相等。

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

票数 4
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55780426

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档