自C ++ 20起,保留或传递不可寻址的函数

问题描述 投票:4回答:1

C ++ 20添加了可寻址函数 16.5.4.2.1 [namespace.std]/6的规则:-重点是我的-

F表示标准库函数([global.functions]), 标准库静态成员函数或a的实例化 标准库功能模板。 除非F被指定为 可寻址函数,未指定C ++程序的行为 (可能是格式错误的),如果它明确地隐式试图形成 指向F的指针。 [注意:形成此类指针的可能方法 包括一元&运算符([expr.unary.op])的应用, addressof([specialized.addressof])或函数指针标准 转换([conv.func])。 —尾注]而且,C ++的行为 如果程序试图形成一个未指定的程序(可能是格式错误) 对F的引用,或者它试图形成一个指向成员的指针 指定标准库的非静态成员函数 ([member.functions])或标准库成员的实例化 功能模板。

据我所知,数学函数没有被规范标记为可寻址函数

这是否意味着从C ++ 20起以下代码是非法的(如noted by cppreference以及其他标准库函数的示例:

// unspecified and illegal?
auto func = static_cast<float (*)(float, float)>(std::pow);
std::cout << func(2, 4) << std::endl;

下面的代码又合法吗?

// 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;

  • C ++ 20中此新限制的原因是什么?
  • 这样的限制不是破坏旧代码吗?
  • 自C ++ 20起,保持或传递non-addressable-functions的正确方法是什么?
c++ language-lawyer function-pointers c++20
1个回答
1
投票

此规则来自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中此新限制的原因是什么?

限制的原因(实际上并不是真正的新概念,更多的是最终阐明的原因是允许更改标准库。只有当您使用这些功能之一的地址时,这些类型的更改才可以观察到-基本上是库说不关心这些更改是否破坏了您的代码,因为这是您的错,而不是委员会/图书馆的错。

另请参见Standard Library Compatibility

这样的限制不是破坏旧代码吗?

不是。它对执行此操作的代码不满意,然后不担心将来是否有任何更改可能会破坏它。

自C ++ 20起,持有或传递不可寻址函数的正确方法是什么?

将它们包装在lambda中。该lambda甚至可以是无状态的,这使您仍然可以将其转换为函数指针。它仍然是一个函数指针,但是与将来的任何标准库更改都隔离。

© www.soinside.com 2019 - 2024. All rights reserved.