了解gsl :: narrow实现 [英] Understanding gsl::narrow implementation

查看:485
本文介绍了了解gsl :: narrow实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

C ++核心指南具有抛出的narrow强制转换如果强制转换更改了值.查看该库的 Microsoft实现:

The C++ Core Guidelines has a narrow cast that throws if the cast changes the value. Looking at the microsoft implementation of the library:

// narrow() : a checked version of narrow_cast() that throws if the cast changed the value
template <class T, class U>
T narrow(U u) noexcept(false)
{
    T t = narrow_cast<T>(u);
    if (static_cast<U>(t) != u)
        gsl::details::throw_exception(narrowing_error());
    if (!details::is_same_signedness<T, U>::value && ((t < T{}) != (u < U{})))  // <-- ???
        gsl::details::throw_exception(narrowing_error());
    return t;
}

我不理解第二个if.它会检查什么特殊情况?为什么static_cast<U>(t) != u还不够?

I don't understand the second if. What special case does it check for and why isn't static_cast<U>(t) != u enough?

出于完整性考虑:

narrow_cast只是一个static_cast:

// narrow_cast(): a searchable way to do narrowing casts of values
template <class T, class U>
constexpr T narrow_cast(U&& u) noexcept
{
    return static_cast<T>(std::forward<U>(u));
}

details::is_same_signdess是其广告:

template <class T, class U>
struct is_same_signedness
    : public std::integral_constant<bool,
        std::is_signed<T>::value == std::is_signed<U>::value>
{
};

推荐答案

这正在检查溢出.让我们看看

This is checking for overflow. Lets look at

auto foo = narrow<int>(std::numeric_limits<unsigned int>::max())

T将是intU将是unsigned int.所以

T t = narrow_cast<T>(u);

将在t中提供存储-1.当您将其投射回去

will give store -1 in t. When you cast that back in

if (static_cast<U>(t) != u)

-1将转换回std::numeric_limits<unsigned int>::max(),因此支票将通过.尽管std::numeric_limits<unsigned int>::max()溢出int并且是未定义的行为,但这不是有效的强制转换.因此,我们继续

the -1 will convert back to std::numeric_limits<unsigned int>::max() so the check will pass. This isn't a valid cast though as std::numeric_limits<unsigned int>::max() overflows an int and is undefined behavior. So then we move on to

if (!details::is_same_signedness<T, U>::value && ((t < T{}) != (u < U{})))

由于符号不同,我们评估

and since the signs aren't the same we evaluate

(t < T{}) != (u < U{})

这是

(-1 < 0) != (really_big_number < 0)
==  true != false
==  true

所以我们抛出一个异常.如果我们走得更远并回绕使用,以使t变为正数,则第二个检查将通过,但第一个检查将失败,因为t将为正,并且强制转换回源类型的方法仍然相同正值,不等于其原始值.

So we throw an exception. If we go even farther and wrap back around using so that t becomes a positive number then the second check will pass but the first one will fail since t would be positive and that cast back to the source type is still the same positive value which isn't equal to its original value.

这篇关于了解gsl :: narrow实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆