一般来说,除非明确允许,否则C程序获取标准库函数指针的行为是未指定的。这意味着在将它们作为 * Callable * 传递之前要格外小心。通常最好将它们 Package 在lambda中。
更多关于该主题的信息:Can I take the address of a function defined in standard library?
然而,C20基于Range-v3 library引入了Constrained algorithms或范围算法;其中类似于函数的实体,例如std::ranges::sort
和std::ranges::transform
,被引入作为Niebloid。
而原始库为算法库中的每个函数创建了一个函子类,每个niebloid,如ranges::sort
,只是对应函子类的一个命名对象;该标准没有具体说明应如何实施这些措施。
因此问题是,是否指定/显式允许将Niebloid作为 Callable(如std::invoke(std::ranges::sort, my_vec)
)传递的行为?
1条答案
按热度按时间zujrkrfu1#
所有的规范说,在[算法.要求]是:
本条款中
std::ranges
命名空间中定义的实体未通过参数相关名称查找([basic. lookup. argdep])找到。当通过函数调用([www.example.com])中后缀表达式的非限定([basic. lookup. unqual])名称查找找到时,它们将禁止参数相关名称查找。expr.call]), they inhibit argument-dependent name lookup.现在,实现这一点的唯一方法是使它们成为对象,但是,我们不指定这些对象的任何进一步的行为。
所以这个:
将起作用,因为在引用它之后,它的计算结果将是
std::ranges::sort(my_vec)
,而且没有办法真正阻止它起作用。但是其他的用法可能就不行了,例如,
std::views::transform(r, std::ranges::distance)
没有被指定工作,因为我们没有说std::ranges::distance
是否是可复制的--std::ranges::size
是一个定制点对象,因此是可复制的,但是std::ranges::distance
只是一个算法。MSVC实现试图积极地遵守有限的规范,并且它的
std::ranges::distance
实现是 * 不可 * 复制的。另一方面,libstdc ++只是使它们成为空对象,因此views::transform(ranges::distance)
只是通过不被主动拒绝的方式工作。所有这些都是:一旦不再直接编写
std::ranges::meow(r)
(或者在using
或using namespace
之后编写meow(r)
),您就只能靠自己了。