根据 cppreference.com,C++20 引入了标准库函数的“寻址限制” :
寻址限制
如果 C++ 程序显式或隐式尝试形成指针、引用(对于自由函数和静态成员函数)或指向成员的指针(对于非静态成员函数),则该程序的行为是未指定的(可能是格式错误的)标准库函数或标准库函数模板的实例,除非它被指定为可寻址函数(见下文)。
以下代码在 C++17 中定义良好,但会导致未指定的行为,并且自 C++20 起可能无法编译:
Run Code Online (Sandbox Code Playgroud)#include <cmath> #include <memory> int main() { auto fptr0 = &std::betaf; // by unary operator& auto fptr1 = std::addressof(std::betal); // by std::addressof auto fptr2 = std::riemann_zetaf; // by function-to-pointer implicit conversion auto &fref = std::riemann_zetal; // forming a reference }
为什么要引入这个?
特别是在语言的向后兼容性方面,这似乎是一个破坏了许多现有代码的更改。这带来了什么好处,值得进行如此重大的改变?
它从来都不是“明确定义的”,它只是碰巧适用于您/某些/大多数实现。(这里CppReference是错误的)
标准的库部分的介绍中隐藏着对实现者必须提供的内容的描述。对于(例如)std:: riemann_zetal,需要的是有一个可以使用函数调用语法调用的“事物”,它采用单个float参数,并返回可以转换为float.
所以,这是一个完全合法的实现:
template <typename FP>
FP ZETA(FP f, int flags = 0) { /* code here */ }
#define riemann_zetaf(x) ZETA<float>(x, 23)
Run Code Online (Sandbox Code Playgroud)
但是,你不能获取地址,riemann_zetaf因为不存在这样的野兽。
请注意,即使没有宏,您也不能保证addressof(riemann_zetal)会返回一个只接受一个参数的函数。您拥有的唯一保证是您可以使用一个参数来调用它。
如果您需要可以获取地址的内容,请自行定义:
float riemann_zetal (float x) { return std::riemann_zetal(x); }
Run Code Online (Sandbox Code Playgroud)
然后取它的地址。
| 归档时间: |
|
| 查看次数: |
288 次 |
| 最近记录: |