每周贴士 #231: 两点之间:一些稍被忽视的算法

(原文链接:https://abseil.io/tips/231 译者:clangpp@gmail.com)

每周贴士 #231: 少用Flags,尤其是在库代码中

概述

最近的一些C++版本中,标准库加入了一些函数,他们的唯一任务就是提供两点(xy)之间的一些(特定的)点:std::clamp (来自C++17)std::midpointstd::lerp(来自C++20)。

把这些函数模板加入标准库有两个目的。第一,统一这些操作的术语——这点很容易被认识到;第二,特别是std::midpointstd::lerp的情况,它提供了高质量的实现以避免常见的错误

所有这些操作都是constexpr,意味着既能用在运行期又能用在编译期。支持的输入数据类型取决于特定的操作,而且std::midpointstd::clamp还提供了额外的灵活性。详情如下。

std::clamp

std::clamp(x, min, max)x“夹”在区间[min, max]以内。更直白地说,如果x已经在minmax之间(含两点),那么std::clamp(x, min, max)返回x;对于落在此区间之外的xstd::clamp返回minmax中距x最近的那个值。这个操作等价于std::max(std::min(x, max), min),只是更直接地表达目的(也少了很多给读者的谜语代码)。

警告:虽然std::clamp返回引用,但是依赖此行为的代码是隐晦和不常见的,而且需要给读者一个注释作为警报。传给std::clamp一个临时变量并且绑定返回值到一个临时变量,很容易不小心创建一个悬挂引用:

// `std::clamp(1, 3, 4)`返回一个指向临时变量的引用,该临时变量初始化自`3`,不应该超越该临时变量的生命周期使用。
// 参阅 See [Tip #101](https://abseil.io/tips/101).
const int& dangling = std::clamp(1, 3, 4);

std::clamp适用于任何可以用<比较大小的类型(或传一个用户提供的比较器std::clamp(x, min, max, cmp))。
Warning: While std::clamp returns a reference, code depending on that is subtle and unusual, and would warrant a comment to alert readers. It is easy to accidentally create a dangling reference by passing a temporary to std::clamp and binding the result to a temporary:

std::midpoint

std::midpoint干的事儿没什么惊喜:std::midpoint(x, y)返回xy的中点(xy是整数的话,向x方向取整)。

std::midpoint(x, y)适用于任何浮点型或整型(不含bool)。买一送一,std::midpoint(p, q)还适用于指向数组元素的指针p, q

std::lerp

std::lerp中的“lerp”是“linear interpolation”(线性插值)的缩写。std::lerp(x, y, t)返回从xy之间t分数距离的值。例如,std::lerp(x, y, 0)返回xstd::lerp(x, y, 1)返回ystd::lerp(x, y, 0.5)可以被简化为std::midpoint(x, y)

注:别看它的起名(译者注:叫内插(interpolation)),当输入t超过[0, 1]区间的时候,std::lerp还可以用作外插(extrapolation)。例如,std::lerp(100, 101, -2)取值是98, std::lerp(100, 101, +2)是102。

std::lerp适用于浮点型。

建议

  1. 这些库函数的主要好处之一是提供共同的术语。跟以往一样,推荐使用这些标准的工具,而不是从头发明轮子。
  2. 任何合适的时候,使用std::midpoint(x, y)而不是std::lerp(x, y, 0.5)
  3. 避免声明引用指向std::clamp的返回值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值