C++20的“寻址限制”有什么好处?

cuxqih21  于 2023-04-13  发布在  其他
关注(0)|答案(1)|浏览(149)

根据cppreference.com,C++20为标准库函数引入了“寻址限制”:

寻址限制

如果一个C程序试图显式或隐式地形成一个指向标准库函数或标准库函数模板的示例化的指针、引用(对于自由函数和静态成员函数)或成员指针(对于非静态成员函数),则该程序的行为是未指定的(可能是病态的),除非它被指定为一个可寻址函数(见下文)。
以下代码在C
17中定义良好,但导致未指定的行为,并且可能无法从C++20编译:

#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
}

为什么要引入这个?
特别是在语言的向后兼容性方面,这似乎是一个破坏了许多现有代码的变化。这提供了什么好处,使这样一个破坏性的变化值得?

monwx1rj

monwx1rj1#

它从来都不是“定义良好的”,它只是碰巧在你的/一些/大多数实现上工作。
在标准的库部分的介绍中,有一个关于实现者必须提供什么的描述。对于(比如)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)

但是,您不能获取riemann_zetaf的地址,因为不存在这样的beast。
请注意,即使没有宏,也不能保证addressof(riemann_zetal)会返回一个只接受一个参数的函数,唯一能保证的是可以使用一个参数调用它。
如果你需要一个可以获取地址的东西,你可以自己定义它:

float riemann_zetal (float x) { return std::riemann_zetal(x); }

然后取 that 的地址。

相关问题