Ami*_*rsh 5 c++ function-pointers language-lawyer c++20
C++20 增加了可寻址函数 规则16.5.4.2.1 [namespace.std]/6 : -- 重点是我的 --
让F表示标准库函数([global.functions])、标准库静态成员函数或标准库函数模板的实例化。除非F被指定为 可寻址函数,否则C++ 程序的行为是未指定的(可能格式错误),如果它显式或隐式地尝试形成指向 F 的指针。 [注意:形成此类指针的可能方法包括应用一元 &运算符 ([expr.unary.op])、addressof ([specialized.addressof]) 或函数到指针的标准转换 ([conv.func])。— 尾注 ] 此外,如果 C++ 程序试图形成对 F 的引用,或者如果它试图形成一个指向成员的指针来指定标准库非静态成员函数([member .functions]) 或标准库成员函数模板的实例化。
据我所知,数学函数没有被规范标记为可寻址函数。
这是否意味着以下代码自 C++20 以来是非法的(如cppreference和其他标准库函数的示例所指出的):
// unspecified and illegal?
auto func = static_cast<float (*)(float, float)>(std::pow);
std::cout << func(2, 4) << std::endl;
Run Code Online (Sandbox Code Playgroud)
下面的代码呢,它合法吗?
// legal? or unspecified and illegal?
std::function<float(float, float)> f = static_cast<float(*)(float, float)>(std::pow);
std::cout << f(2, 3) << std::endl;
Run Code Online (Sandbox Code Playgroud)
这个规则来自P0551。这里的措辞是“未指定(可能格式错误)”——不是未定义的行为,不是格式错误的 NDR,没有类似的东西。
现在,该库主要围绕直接使用 API 进行设计、指定和实现。库指定了什么x.foo(y, z)意思,实现必须遵循该规范。但是有很多方法可以实现这一点——可能foo需要一些额外的默认参数,或者可以是一个模板,或者是一个重载集。
此外,也许在 C++N 中,只有x.foo(y, z). 但是在 C++N+1 中,也增加x.foo(y)了一个新提案。例如,在 C++03 中只有一个,vector::push_back但现在有两个。
C++20 中这个新限制的原因是什么?
限制的原因(它在概念上并不是新的,更多的是它最终被阐明)是为了允许更改标准库。这些类型的更改只有在您获取这些函数之一的地址时才能观察到 - 基本上是图书馆说它不在乎这些更改是否破坏了您的代码,因为这是您的错,而不是委员会/图书馆的错。
另请参阅标准库兼容性。
这样的限制不是打破遗留代码吗?
并不真地。它更不喜欢这样做的代码,然后不担心将来是否有任何更改可能会破坏它。
自 C++20 以来,保存或传递不可寻址函数的正确方法是什么?
将它们包裹在 lambda 中。该 lambda 甚至可以是无状态的,这允许您仍然将其转换为函数指针。它仍然是一个函数指针,但它不受任何未来标准库更改的影响。
| 归档时间: |
|
| 查看次数: |
172 次 |
| 最近记录: |