std::clamp - 检测函数返回值是否绑定到 const T&



如果minmax的参数之一是右值,则最好不要将std::clamp返回值绑定到const-ref。

std::clamp的典型实现(非常简化):

template <class T>
constexpr const T& clamp(const T& value, const T& min, const T& max)
{
return value < min ? min : max < value ? max : value;
}

正如在std::clamp的cppreference中已经指出的,当有人写:时,会出现危险的情况

int n = -1;
const int& r = std::clamp(n, 0, 255);
// r is dangling

有什么方法可以在编译时检测这些情况吗?

如果你愿意编写自己的clamp函数,你可以检测到这一点并采取措施。

例如,假设您希望clamp函数按值返回,如果这是确保我们不会得到悬挂引用的唯一方法:

#include <type_traits>
template<class A, class B, class C>
constexpr std::conditional_t<
std::is_lvalue_reference<A &&>::value && std::is_lvalue_reference<B &&>::value && std::is_lvalue_reference<C &&>::value,
std::add_lvalue_reference_t<std::common_type_t<A, B, C>>,
std::common_type_t<A, B, C>
> clamp(A && value, B && min, C && max)
{            
return value < min ? min : max < value ? max : value;
}

这将使得CCD_ 5有效地具有签名CCD_;只有当所有3个输入都是左值引用时,才会得到int & clamp(int&, int&, int&)。如果您愿意的话,生成返回的引用const是很简单的。

如果不是所有的左值引用,也可能导致函数编译失败:

#include <type_traits>
template<class A, class B, class C>
constexpr std::add_lvalue_reference_t<std::common_type_t<A, B, C>>
clamp(A && value, B && min, C && max)
{
static_assert(std::is_lvalue_reference<A &&>::value && std::is_lvalue_reference<B &&>::value && std::is_lvalue_reference<C &&>::value, "");
return value < min ? min : max < value ? max : value;
}

相关内容

最新更新