在C ++ 20中,std::swap
成为constexpr
函数。
[我知道标准库在标记constexpr
方面确实落后于该语言,但是到2017年,<algorithm>
就像其他很多东西一样,已经成为constexpr了。但是-std::swap
不是。我隐约记得有一些奇怪的语言缺陷阻止了这种标记,但是我忘记了细节。
有人可以简洁明了地解释吗?
动机:需要了解为什么在C ++ 11 / C ++ 14代码中标记类似std::swap()
的函数constexpr
可能不是一个好主意。
奇怪的语言是CWG 1581:
第15条[special]非常清楚,特殊成员函数仅在使用过时才隐式定义。这为在未评估的上下文中的常量表达式带来了问题:
struct duration { constexpr duration() {} constexpr operator int() const { return 0; } }; // duration d = duration(); // #1 int n = sizeof(short{duration(duration())});
这里的问题是我们不允许在此程序中隐式定义
constexpr duration::duration(duration&&)
,因此初始化列表中的表达式不是常量表达式(因为它调用了尚未定义的constexpr函数),因此花括号初始化程序包含缩小的转换,因此该程序格式不正确。如果取消注释第1行,则将隐式定义move构造函数,并且该程序有效。远距离的这种怪异的动作是非常不幸的。在这一点上,实现方式有所不同。
您可以阅读其余的问题描述。
[2017年,在Albuquerque的P0859中通过了此问题的解决方案(在C ++ 17发行后)。这个问题是对于C ++ 20都可以同时具有constexpr std::swap
(在P0879中解决)和constexpr std::invoke
(在P1065中也具有CWG1581示例)的阻碍。
(由于@NathanOliver)
为了允许constexpr
交换功能,必须在实例化此函数的模板之前检查交换类型是否可移动构造和可分配移动。不幸的是,由于仅在C ++ 20中解决了语言缺陷,您无法对此进行了检查,因为相关的成员函数可能尚未生成/实例化。
<algorithm>
功能标记为constexpr
。constexpr std::swap
和constexpr std::invoke
成为问题-请参阅上面的说明。std::swap
和其他一些构造,并且这被C ++ 17接受。std::invoke
修复也是如此。如果您不要检查移动可构造性和移动可分配性,则可以使用constexpr
交换,而是直接检查类型的某些其他功能,以确保尤其如此。例如仅原始类型,没有类或结构。或者,从理论上讲,您可以放弃检查,而仅处理可能遇到的任何编译错误,以及在编译器之间进行不稳定的行为切换。无论如何,不要用这种东西代替std::swap()
。