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

7
根据cppreference.com的说法,C++20为标准库函数引入了"寻址限制"

Addressing restriction

The behavior of a C++ program is unspecified (possibly ill-formed) if it explicitly or implicitly attempts to form a pointer, reference (for free functions and static member functions) or pointer-to-member (for non-static member functions) to a standard library function or an instantiation of a standard library function template, unless it is designated an addressable function (see below).

Following code was well-defined in C++17, but leads to unspecified behaviors and possibly fails to compile since 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
}

为什么要引入这个?

特别是考虑到语言的向后兼容性,这似乎是一项破坏了许多现有代码的变化。这提供了什么好处,使得这种破坏性的变化值得实施呢?


以下代码在C++17中被很好地定义。 - 463035818_is_not_a_number
3
https://dev59.com/mXE95IYBdhLWcg3wi-Yc - Hans Passant
4
相关问题:https://dev59.com/5VMI5IYBdhLWcg3wpdK7 - Jerry Coffin
1
可能会有超出语言规范的其他重载。因此,您无法确定确切的函数签名是什么。http://eel.is/c++draft/member.functions - BoP
@BoP 我猜它也允许一些标准库函数被实现为宏,对吗? - Jesper Juhl
1个回答

7

它从来没有被“明确定义”,它只是在你/某些/大多数实现中偶然起作用。(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)

但是,你不能取得riemann_zetaf的地址,因为这个东西根本不存在。
请注意,即使没有宏,你也无法保证addressof(riemann_zetal)会返回一个只接受一个参数的函数。你唯一能确保的是可以用一个参数调用它。
如果你需要一个可以取地址的东西,请自己定义一个:
float riemann_zetal (float x) { return std::riemann_zetal(x); }

然后取代那个的地址。


我怀疑实现允许定义这样的宏,因为它可能会与用户代码冲突。 - HolyBlackCat
你是指像 toupper 这样的吗? - Marshall Clow
1
@MarshallClow,这会产生冲突,因为用户应该能够在其范围内声明自己的riemann_zetal(它不是保留标识符),如果它是宏,则无法正常工作。(具体而言,如果标准库使用宏实现,则您最后的建议也无法编译。) - user17732522
3
@MarshallClow C17 7.1.4 使用库函数 /1 允许将 C 标准库函数定义为宏。但我在 C++ 标准中没有找到同样的措辞来描述 C++ 标准库实体。 - HolyBlackCat
2
我认为宏参数将讨论从主要观点偏离,即:标准库可以具有默认参数、模板或添加其他重载等,使得地址不明确、不匹配函数或根本不可用。没有任何保证这会永远有效,依赖它只是在现实中“可能可以”,但不符合规范。遵循规范可以保护您免受未来库更改的影响。 - Chris Uzdavinis
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接