<i id='L90Gk'><tr id='L90Gk'><dt id='L90Gk'><q id='L90Gk'><span id='L90Gk'><b id='L90Gk'><form id='L90Gk'><ins id='L90Gk'></ins><ul id='L90Gk'></ul><sub id='L90Gk'></sub></form><legend id='L90Gk'></legend><bdo id='L90Gk'><pre id='L90Gk'><center id='L90Gk'></center></pre></bdo></b><th id='L90Gk'></th></span></q></dt></tr></i><div id='L90Gk'><tfoot id='L90Gk'></tfoot><dl id='L90Gk'><fieldset id='L90Gk'></fieldset></dl></div>
  1. <tfoot id='L90Gk'></tfoot>

  2. <small id='L90Gk'></small><noframes id='L90Gk'>

    • <bdo id='L90Gk'></bdo><ul id='L90Gk'></ul>
    <legend id='L90Gk'><style id='L90Gk'><dir id='L90Gk'><q id='L90Gk'></q></dir></style></legend>
    1. 理解 gsl::narrow 实现

      Understanding gsl::narrow implementation(理解 gsl::narrow 实现)
      <i id='2NcMX'><tr id='2NcMX'><dt id='2NcMX'><q id='2NcMX'><span id='2NcMX'><b id='2NcMX'><form id='2NcMX'><ins id='2NcMX'></ins><ul id='2NcMX'></ul><sub id='2NcMX'></sub></form><legend id='2NcMX'></legend><bdo id='2NcMX'><pre id='2NcMX'><center id='2NcMX'></center></pre></bdo></b><th id='2NcMX'></th></span></q></dt></tr></i><div id='2NcMX'><tfoot id='2NcMX'></tfoot><dl id='2NcMX'><fieldset id='2NcMX'></fieldset></dl></div>
      • <tfoot id='2NcMX'></tfoot>
      • <small id='2NcMX'></small><noframes id='2NcMX'>

              <tbody id='2NcMX'></tbody>
          1. <legend id='2NcMX'><style id='2NcMX'><dir id='2NcMX'><q id='2NcMX'></q></dir></style></legend>

                <bdo id='2NcMX'></bdo><ul id='2NcMX'></ul>

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

                问题描述

                C++ 核心指南有一个narrow cast 如果转换改变了值就会抛出.查看库的微软实现:

                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(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>
                {
                };
                

                推荐答案

                这是检查溢出.来看看

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

                T 将是 intU 将是 unsigned int.所以

                T will be int and U will be unsigned int. So

                T t = narrow_cast<T>(u);
                

                将在 t 中给 store -1.当你把它放回去

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

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

                -1 将转换回 std::numeric_limits::max() 以便检查通过.这不是有效的转换,因为 std::numeric_limits::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 实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

                相关文档推荐

                Constructor initialization Vs assignment(构造函数初始化 Vs 赋值)
                Is a `=default` move constructor equivalent to a member-wise move constructor?(`=default` 移动构造函数是否等同于成员移动构造函数?)
                Has the new C++11 member initialization feature at declaration made initialization lists obsolete?(声明时新的 C++11 成员初始化功能是否使初始化列表过时了?)
                Order of constructor call in virtual inheritance(虚继承中构造函数调用的顺序)
                How to use sfinae for selecting constructors?(如何使用 sfinae 选择构造函数?)
                Initializing a union with a non-trivial constructor(使用非平凡的构造函数初始化联合)

                <small id='SVDGw'></small><noframes id='SVDGw'>

                  <tfoot id='SVDGw'></tfoot>

                  <legend id='SVDGw'><style id='SVDGw'><dir id='SVDGw'><q id='SVDGw'></q></dir></style></legend>

                    <tbody id='SVDGw'></tbody>
                  <i id='SVDGw'><tr id='SVDGw'><dt id='SVDGw'><q id='SVDGw'><span id='SVDGw'><b id='SVDGw'><form id='SVDGw'><ins id='SVDGw'></ins><ul id='SVDGw'></ul><sub id='SVDGw'></sub></form><legend id='SVDGw'></legend><bdo id='SVDGw'><pre id='SVDGw'><center id='SVDGw'></center></pre></bdo></b><th id='SVDGw'></th></span></q></dt></tr></i><div id='SVDGw'><tfoot id='SVDGw'></tfoot><dl id='SVDGw'><fieldset id='SVDGw'></fieldset></dl></div>

                        <bdo id='SVDGw'></bdo><ul id='SVDGw'></ul>