Author: federico.kircheis@gmail.com

Date: Fri, 20 Jan 2017 08:31:37 -0800 (PST)

------=_Part_619_708454977.1484929897975 Content-Type: multipart/alternative; boundary="----=_Part_620_2018933233.1484929897976" ------=_Part_620_2018933233.1484929897976 Content-Type: text/plain; charset=UTF-8 Hello to everyone, this is my first proposal, I hope you'll find it interesting, give me some feedback and help to improve my idea/implementation/proposal. I found myself many times to compare different numeric types together, for example int and std::size_t. This happens because the c++ standard library uses unsigned types when dealing with sizes and positions, whereas other libraries do not always, as for example CArray of the MFC framework. I noticed, that most of the time, I needed one of the following three operations: 1) convert one type to another (verify if a number is in a valid range), 2) verify if two numbers of different types are equivalent (equality), 3) verify how two numbers of different types relates (less than). In order to do one of the above listed operations, we might do different things. For example, verifying if both numbers are unsigned or not. If only one is unsigned, check if it is less than zero. If not, determine which of the two types has a greater precision, cast both of them to the bigger type (may be unnecessary in some cases), and finally do the desired operation. You also need to pay attention to implicit conversions. You can see, that for doing a pretty trivial operation (is 5ul equal to 2?, can I convert -3 to an unsigned short?) you need to do a lot of repetitive work, and the worst part is, that some relations between the types might change based on the platform. Usually types are related to your architecture, that means that a comparison valid where you are developing, might be invalid on some other architecture; One type might be bigger than the other one, or the signeddes may have changed. Of course this does not happen if you are working with the same type, but it may happen that you are working with two different types that are typedeffed, for example, to the same type on a 32 bit platform, whereas on 64 bit they are not. For this reason it is essential to have some utility function to write correct code in a simpler way, which gives you the possibility to verify if a value of one type is in the range of a second type, if two values are equivalent, or if one is less (greater, and so on) than the other. My proposal would be to add four templated functions which work only for integral types (bool excluded). The first function would be: template <typename R, typename T> constexpr bool in_range(const T t) noexcept; Usage size_t i == ... if(in_range<DWORD>(i)){ // safe to convert i to a DWORD value, parameter... } else { // not possible to represent i as a DWORD } The second function would be: template <typename T, typename U> constexpr bool cmp_equal(const T t, const U u) noexcept; Usage size_t i == ... DWORD j == ... if(cmp_equal(i,j)){ // i and j represent the same quantity } else { // i and j represents different quantities } And the third function would be: template <typename T, typename U> constexpr bool cmp_less(const T t, const U u) noexcept Usage: size_t i == ... DWORD j == ... if(cmp_less(i,j)){ // i < j } else { // i >= j } We could (and maybe should) also provide cmp_greater, cmp_less_or_equal, cmp_unequal and etc., but we can implement this functions using cmp_equal and cmp_less. The fourth function I would like to add is: template <typename T> constexpr std::size_t precision() noexcept; The reasons are described here: https://www.securecoding.cert.org/confluence/display/c/INT35-C.+Use+correct+integer+precisions Quote: "Integer types in C have both a size and a precision. The size indicates the number of bytes used by an object and can be retrieved for any object or type using the sizeof operator. The precision of an integer type is the number of bits it uses to represent values, excluding any sign and padding bits. Padding bits contribute to the integer's size, but not to its precision. Consequently, inferring the precision of an integer type from its size may result in too large a value, which can then lead to incorrect assumptions about the numeric range of these types. Programmers should use correct integer precisions in their code, and in particular, should not use the sizeof operator to compute the precision of an integer type on architectures that use padding bits or in strictly conforming (that is, portable) programs." The function precision is used internally (by cmp_equal, cmp_less and in_range) for verifying which type is bigger, in order to safely cast before comparing the types. I also think, that this function should be part of the API, since it is very handy. I've already provided and tested an implementation of those functions, you can find them at https://github.com/fekir/safeintegral The file containing the implementation is: https://github.com/fekir/safeintegral/blob/master/safeintegral/safeintegralop.hpp As you can see the implementation is not particularly complex and should work on any conformant compiler (tested with gcc and msvc), those functions can be easily added in the standard library, maybe in <limits>. My implementation is composed by more than four functions, the others are probably not necessary, but I'm not a template master, and I was not able to reduce the number of functions and maintain a good readability. There are also other unrelated functions apart from the four I have mentioned, but my goal was to keep my proposal small. I also think, that the others are not yet complete, since they do not handle different types. Let me know what you think. Federico -- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/66f9bab2-7220-4bf1-afb7-77c5efa1bac3%40isocpp.org. ------=_Part_620_2018933233.1484929897976 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">Hello to everyone, this is my first proposal, I hope you&#= 39;ll find it interesting, give me some feedback and help to improve my ide= a/implementation/proposal.<br><br><br>I found myself many times to compare = different numeric types together, for example int and std::size_t.<br>This = happens because the c++ standard library uses unsigned types when dealing = with sizes and positions, whereas other libraries do not always, as for exa= mple CArray of the MFC framework.<br><br>I noticed, that most of the time, = I needed one of the following three operations:<br>=C2=A0=C2=A0=C2=A0 1) co= nvert one type to another (verify if a number is in a valid range),<br>=C2= =A0=C2=A0=C2=A0 2) verify if two numbers of different types are equivalent = (equality),<br>=C2=A0=C2=A0=C2=A0 3) verify how two numbers of different ty= pes relates (less than).<br><br>In order to do one of the above listed=C2= =A0 operations, we might do different things. For example, verifying if bot= h numbers are unsigned or not. If only one is unsigned, check if it is less= than zero. If not, determine which of the two types has a greater precisio= n, cast both of them to the bigger type (may be unnecessary in some cases),= and finally do the desired operation. You also need to pay attention to im= plicit conversions.<br><br>You can see, that for doing a pretty trivial ope= ration (is 5ul equal to 2?, can I convert -3 to an unsigned short?) you nee= d to do a lot of repetitive work, and the worst part is, that some relation= s between the types might change based on the platform.<br>Usually types ar= e related to your architecture, that means that a comparison valid where yo= u are developing, might be invalid on some other architecture; One type mig= ht be bigger than the other one, or the signeddes may have changed. Of cour= se this does not happen if you are working with the same type, but it may h= appen that you are working with two different types that are typedeffed, fo= r example, to the same type on a 32 bit platform, whereas on 64 bit they ar= e not.<br><br>For this reason it is essential to have some utility function= to write correct code in a simpler way, which gives you the possibility to= verify if a value of one type is in the range of a second type, if two val= ues are equivalent, or if one is less (greater, and so on) than the other.<= br><br><br>My proposal would be to add four templated functions which work = only for integral types (bool excluded).<br><br>The first function would be= :<br><br>template <typename R, typename T> constexpr bool in_range(co= nst T t) noexcept;<br><br>Usage<br>size_t i =3D=3D ...<br>if(in_range<DW= ORD>(i)){<br>=C2=A0=C2=A0=C2=A0 // safe to convert i to a DWORD value, p= arameter...<br>} else {<br>=C2=A0=C2=A0=C2=A0 // not possible to represent = i as a DWORD<br>}<br><br>The second function would be:<br><br>template <= typename T, typename U> constexpr bool cmp_equal(const T t, const U u) n= oexcept;<br><br>Usage<br>size_t i =3D=3D ...<br>DWORD j =3D=3D ...<br>if(cm= p_equal(i,j)){<br>=C2=A0=C2=A0=C2=A0 // i and j represent the same quantity= <br>} else {<br>=C2=A0=C2=A0=C2=A0 // i and j represents different quantiti= es<br>}<br><br><br>And the third function would be:<br><br>template <typ= ename T, typename U> constexpr bool cmp_less(const T t, const U u) noexc= ept<br><br>Usage:<br>size_t i =3D=3D ...<br>DWORD j =3D=3D ...<br>if(cmp_le= ss(i,j)){<br>=C2=A0=C2=A0=C2=A0 //=C2=A0 i < j<br>} else {<br>=C2=A0=C2= =A0=C2=A0 //=C2=A0 i >=3D j<br>}<br>=C2=A0=C2=A0=C2=A0 <br><br>We could = (and maybe should) also provide cmp_greater, cmp_less_or_equal, cmp_unequal= and etc., but we can implement this functions using cmp_equal and cmp_less= ..<br><br>The fourth function I would like to add is: <br><br>template <t= ypename T> constexpr std::size_t precision() noexcept;<br><br><br>The re= asons are described here:<br><br>https://www.securecoding.cert.org/confluen= ce/display/c/INT35-C.+Use+correct+integer+precisions<br><br>Quote:<br>"= ;Integer types in C have both a size and a precision. The size indicates th= e number of bytes used by an object and can be retrieved for any object or = type using the sizeof operator.=C2=A0 The precision of an integer type is t= he number of bits it uses to represent values, excluding any sign and paddi= ng bits.<br><br>Padding bits contribute to the integer's size, but not = to its precision. Consequently, inferring the precision of an integer type = from its size may result in too large a value, which can then lead to incor= rect assumptions about the numeric range of these types.=C2=A0 Programmers = should use correct integer precisions in their code, and in particular, sho= uld not use the sizeof operator to compute the precision of an integer type= on architectures that use padding bits or in strictly conforming (that is,= portable) programs."<br><br><br>The function precision is used intern= ally (by cmp_equal, cmp_less and in_range) for verifying which type is bigg= er, in order to safely cast before comparing the types. I also think, that = this function should be part of the API, since it is very handy.<br><br><br= >I've already provided and tested an implementation of those functions,= you can find them at <br><br>https://github.com/fekir/safeintegral<br><br>= The file containing the implementation is:<br><br>https://github.com/fekir/= safeintegral/blob/master/safeintegral/safeintegralop.hpp<br><br>As you can = see the implementation is not particularly complex and should work on any c= onformant compiler (tested with gcc and msvc), those functions can be easil= y added in the standard library, maybe in <limits>.<br>My implementat= ion is composed by more than four functions, the others are probably=20 not necessary, but I'm not a template master, and I was not able to=20 reduce the number of functions and maintain a good readability.<br><br>Ther= e are also other unrelated functions apart from the four I have mentioned, = but my goal was to keep my proposal small. I also think, that the others ar= e not yet complete, since they do not handle different types.<br><br><br>Le= t me know what you think.<br><br>Federico<br><br></div> <p></p> -- <br /> You received this message because you are subscribed to the Google Groups &= quot;ISO C++ Standard - Future Proposals" group.<br /> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa= ls+unsubscribe@isocpp.org</a>.<br /> To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp= ..org">std-proposals@isocpp.org</a>.<br /> To view this discussion on the web visit <a href=3D"https://groups.google.c= om/a/isocpp.org/d/msgid/std-proposals/66f9bab2-7220-4bf1-afb7-77c5efa1bac3%= 40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.= com/a/isocpp.org/d/msgid/std-proposals/66f9bab2-7220-4bf1-afb7-77c5efa1bac3= %40isocpp.org</a>.<br /> ------=_Part_620_2018933233.1484929897976-- ------=_Part_619_708454977.1484929897975-- .

Author: federico.kircheis@gmail.com

Date: Sat, 4 Feb 2017 09:27:38 -0800 (PST)

------=_Part_893_515332329.1486229258407 Content-Type: multipart/alternative; boundary="----=_Part_894_198252994.1486229258407" ------=_Part_894_198252994.1486229258407 Content-Type: text/plain; charset=UTF-8 I've created a proposal draft (see attachment). -- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/845d8ffe-13e2-4597-882c-0404ad582cef%40isocpp.org. ------=_Part_894_198252994.1486229258407 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">I've created a proposal draft (see attachment).<br></d= iv> <p></p> -- <br /> You received this message because you are subscribed to the Google Groups &= quot;ISO C++ Standard - Future Proposals" group.<br /> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa= ls+unsubscribe@isocpp.org</a>.<br /> To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp= ..org">std-proposals@isocpp.org</a>.<br /> To view this discussion on the web visit <a href=3D"https://groups.google.c= om/a/isocpp.org/d/msgid/std-proposals/845d8ffe-13e2-4597-882c-0404ad582cef%= 40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.= com/a/isocpp.org/d/msgid/std-proposals/845d8ffe-13e2-4597-882c-0404ad582cef= %40isocpp.org</a>.<br /> ------=_Part_894_198252994.1486229258407-- ------=_Part_893_515332329.1486229258407 Content-Type: text/html; charset=US-ASCII; name=safe_comparison_proposal.html Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=safe_comparison_proposal.html X-Attachment-Id: f35ef8a6-6476-471b-9f53-cdaaf7f6376e Content-ID: <f35ef8a6-6476-471b-9f53-cdaaf7f6376e> <html> <head> <title>safe integral comparisons</title> </head> <body> <address> Document number: Dnnnn=yy-nnnn</br> Date: 2017-02-04</br> Project: safe integral comparisons</br> Reply-to: <a href="mailto:federico.kircheis@gmail.com">Federico Kircheis</a><br/> </address> <h1>safe integral comparisons</h1> <a name="Table"></a><h2>I. Table of Contents</h2> <ul> <li><a href="#Table">I. Table of Contents</a></li> <li><a href="#Motivation">II. Motivation</a></li> <li><a href="#Proposal">III. Proposal</a></li> <li><a href="#Examples">IV. Examples</a></li> <li><a href="#Sample">V. Sample implementation</a></li> <li><a href="#Effects">VI. Effects on Existing Code</a></li> <li><a href="#Design">VII. Design Decisions</a></li> </ul> <a name="Motivation"></a><h2>II. Motivation</h2> <p> Comparing integrals of different types may be a more complex task than expected. Most of the time we expect that a simple <blockquote><pre> if(a < b){ // ... } else { // ... } </pre></blockquote> should work in all cases, but if a and b are of different types, things are more complicated.</br> If <code>a</code> is an signed type, and <code>b</code> unsigned, then <code>a</code> is converted to the unsigned type. If <code>a</code> held a number less than zero, then the result may be unexpected, since the expression <code>a < b</code> could evaluate to false, even if a strictly negative number is always lower than a positive one.</br> </p> <p> Also converting integrals between different types can be challenging, for simplicity, most of the time we assume that values are in range, and write <blockquote><pre> a = static_cast<decltype(a)>(b); </pre></blockquote> If we want to write a safe conversion, we need to check if <code>b</code> has a value between <code>std::numeric_limits<decltype(a)>::min()</code> and <code>std::numeric_limits<decltype(a)>::max()</code>. We also need to pay attention that no implicit conversion (for example between unsigned and signed types) invalidates our comparison. </p> <p> Comparing and converting numbers, even of different numeric types, should be a trivial task. Unfortunately it is not, and because of implicit conversions we may write, without noticing it, unsafe code. </p> <a name="Proposal"></a><h2>III. Proposal</h2> <p> This paper proposes to add a set of <code>constexpr</code> and <code>noexcept</code> functions for converting and comparing integrals of different signeddes and precision (except for <code>bool</code>): <ul> <li> Two functions to compare if two variables rappresent the same value or not <blockquote><pre> template <typename T, typename U> constexpr bool std::cmp_equal(T t, U u) noexcept; template <typename T, typename U> constexpr bool std::cmp_unequal(T t, U u) noexcept; </pre></blockquote> <li> A set of functions that can be used to determine the relative order of two values <blockquote><pre> template <typename T, typename U> constexpr bool std::cmp_less(T t, U u) noexcept; template <typename T, typename U> constexpr bool std::cmp_greater(T t, U u) noexcept; template <typename T, typename U> constexpr bool std::cmp_less_or_equal(T t, U u) noexcept; template <typename T, typename U> constexpr bool std::cmp_greater_or_equal(T t, U u) noexcept; </pre></blockquote> <li> One function to determine if a specific value is inside the range of possible values of another type (i.e. if we can convert the value to the other type safely) <blockquote><pre> template <typename R, typename T> constexpr bool in_range(T t) noexcept; </pre></blockquote> <li> One function for retrieving the precision of a given numeric type <blockquote><pre> template <typename T> constexpr std::size_t std::precision() noexcept; </pre></blockquote> </ul> The function <code>precision</code> is part of the proposal because we cannot use the operator <code>sizeof</code> to determine between two types which one has a wider range (quote from <a href="https://www.securecoding.cert.org/confluence/display/c/INT35-C.+Use+correct+integer+precisions">SecureCoding</a>):</br> <q>Integer types in C have both a size and a precision. The size indicates the number of bytes used by an object and can be retrieved for any object or type using the sizeof operator. The precision of an integer type is the number of bits it uses to represent values, excluding any sign and padding bits. Padding bits contribute to the integer's size, but not to its precision. Consequently, inferring the precision of an integer type from its size may result in too large a value, which can then lead to incorrect assumptions about the numeric range of these types. Programmers should use correct integer precisions in their code, and in particular, should not use the sizeof operator to compute the precision of an integer type on architectures that use padding bits or in strictly conforming (that is, portable) programs.</q> </p> <a name="Examples"></a><h2>IV. Examples</h2> <h3>Examples without current proposal</h3> <p> Comparing an unsigned int with an int: <blockquote><pre> int a = ... unsigned int b = ... // added static_cast to avoid compiler warnings since we are doing a "safe" comparison if(a < 0 || static_cast<unsigned int>(a) < b){ // do X } else { // do Y } </pre></blockquote> Comparing an uint32_t with an int16_t: <blockquote><pre> int32_t a = ... uint16_t b = ... // added static_cast to avoid compiler warnings since we are doing a "safe" comparison if(a < static_cast<int32_t>(b)){ // do X } else { // do Y } </pre></blockquote> Comparing an int with an intptr_t: <blockquote><pre> int a = ... intptr_t b = ... if(???){ // no idea how to do it in one readable line without some assumption about int and intptr_t // do X } else { // do Y } </pre></blockquote> <h3>Example with current proposal</h3> Comparing one integral type <code>A</code> with another integral type <code>B</code> (both non <code>bool</code>): <blockquote><pre> A a = ... B b = ... // no need for any cast since std::cmp_less is taking care of everything if( std::cmp_less(a,b)){ // do X } else { // do Y } </pre></blockquote> </p> <a name="Sample"></a><h2>V. Sample implementation</h2> <p> This section shows an example of how <code>precision</code>, <code>cmp_equal</code>, <code>cmp_less</code> and <code>in_range</code> can be implemented with any standard conforming C++11 compiler, without any language extension. The only dependencies are the <code>std::numeric_limits</code> function from the <code>limits</code> header and some traits from the <code>type_traits</code> header. <blockquote><pre> #include <limits> #include <type_traits> template <typename T> constexpr std::size_t precision() noexcept; namespace details{ #if defined(ERR_MSG_xxx_NEEDS_INTEGRAL_NOT_BOOL) || defined(ASSERT_INTEGRAL_NOT_BOOL_TYPE) #error "ERR_MSG_xxx_NEEDS_INTEGRAL_NOT_BOOL or ASSERT_INTEGRAL_NOT_BOOL_TYPE already defined" #endif #define ERR_MSG_xxx_NEEDS_INTEGRAL_NOT_BOOL " needs to be an integral (not bool) value type" #define ASSERT_INTEGRAL_NOT_BOOL_TYPE(T) static_assert(is_integral_not_bool<T>(), #T ERR_MSG_xxx_NEEDS_INTEGRAL_NOT_BOOL); template <typename T> constexpr bool is_integral_not_bool(){ using value_type = typename std::remove_cv<T>::type; return !std::is_same<value_type,bool>::value && std::is_integral<T>::value; } template <class T> constexpr std::size_t pop(const std::size_t precision, const T num) { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); return (num == T{0}) ? precision : pop(((num % 2 != 0) ? precision+1 : precision), num >> 1); } // could use the same implementation of in_range_signed_signed, but compiler may generate warning that t is always bigger than 0 template <typename R, typename T> constexpr bool in_range_unsigned_unsigned(const T t) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(R); return (precision<T>() > precision<R>()) ? (t < static_cast<T>(std::numeric_limits<R>::max())) : (static_cast<R>(t) <std::numeric_limits<R>::max()); } template <typename R, typename T> constexpr bool in_range_signed_signed(const T t) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(R); return (precision<T>() > precision<R>()) ? (t <= static_cast<T>(std::numeric_limits<R>::max()) && t >= static_cast<T>(std::numeric_limits<R>::min())) : (static_cast<R>(t) <= std::numeric_limits<R>::max() && static_cast<R>(t) >= std::numeric_limits<R>::max()); } template <typename R, typename T> constexpr bool in_range_signed_unsigned(const T t) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(R); return (t < T{ 0 }) ? false : (precision<T>() / 2 <= precision<R>()) ? true : (t <= static_cast<T>(std::numeric_limits<R>::max())); } template <typename R, typename T> constexpr bool in_range_unsigned_signed(const T t) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(R); return (precision<T>() >= precision<R>() / 2) ? (t <= static_cast<T>(std::numeric_limits<R>::max())) : true; } template <typename R, typename T> constexpr bool in_range_unsigned(const T t) noexcept { return std::is_unsigned<R>::value ? in_range_unsigned_unsigned<R>(t) : in_range_unsigned_signed<R>(t); } template <typename R, typename T> constexpr bool in_range_signed(const T t) noexcept { return std::is_signed<R>::value ? in_range_signed_signed<R>(t) : in_range_signed_unsigned<R>(t); } template <typename T, typename U> constexpr bool cmp_equal_same_sign(const T t, const U u) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(U); return (precision<T>()>precision<U>()) ? (t == static_cast<T>(u)) : (static_cast<U>(t) == u); } template <typename T, typename U> constexpr bool cmp_equal_signed_unsigned(const T t, const U u) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(U); return (t<T{ 0 }) ? false : (precision<T>() / 2>precision<U>()) ? (t == static_cast<T>(u)) : (static_cast<U>(t) == u); } template <typename T, typename U> constexpr bool cmp_less_same_sign(const T t, const U u) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(U); return (precision<T>()>precision<U>()) ? (t < static_cast<T>(u)) : (static_cast<U>(t) < u); } template <typename T, typename U> constexpr bool cmp_less_signed_unsigned(const T t, const U u) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(U); return (t<T{ 0 }) ? true : (precision<T>() / 2>precision<U>()) ? (t < static_cast<T>(u)) : (static_cast<U>(t) < u); } template <typename T, typename U> constexpr bool cmp_less_unsigned_signed(const T t, const U u) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(U); return (u<U{ 0 }) ? false : (precision<U>() / 2>precision<T>()) ? (static_cast<U>(t) < u) : (t < static_cast<T>(u)); } #undef ERR_MSG_xxx_NEEDS_INTEGRAL_NOT_BOOL #undef ASSERT_INTEGRAL_NOT_BOOL_TYPE } // end details template <typename T> constexpr std::size_t precision() noexcept { return details::pop(0, std::numeric_limits<T>::max()); } /// Usage: /// size_t i = ... /// if(in_range<DWORD>(i)){ /// // safe to use i as a DWORD value, parameter... /// } else { /// // not possible to rappresent i as a DWORD /// } template <typename R, typename T> constexpr bool in_range(const T t) noexcept { return std::is_unsigned<T>::value ? details::in_range_unsigned<R>(t) : details::in_range_signed<R>(t); } // equivalent of operator== for different types /// Usage: /// size_t i = ... /// DWORD j = ... /// if(cmp_equal(i,j)){ /// // i and j rappresent the same quantity /// } else { /// // i and j rappresents different quantities /// } template <typename T, typename U> constexpr bool cmp_equal(const T t, const U u) noexcept { return (std::is_signed<T>::value == std::is_signed<U>::value) ? details::cmp_equal_same_sign(t, u) : (std::is_signed<T>::value) ? details::cmp_equal_signed_unsigned(t, u) : details::cmp_equal_signed_unsigned(u,t); } // equivalent of operator< for different integral types /// Usage: /// size_t i = ... /// DWORD j = ... /// if(cmp_less(i,j)){ /// // i < j /// } else { /// // i >= j /// } template <typename T, typename U> constexpr bool cmp_less(const T t, const U u) noexcept { return (std::is_signed<T>::value == std::is_signed<U>::value) ? details::cmp_less_same_sign(t,u) : (std::is_signed<T>::value) ? details::cmp_less_signed_unsigned(t, u) : details::cmp_less_unsigned_signed(t, u); } </pre></blockquote> </p> <a name="Effects"></a><h2>VI. Effects on Existing Code</h2> <p>Since the proposed functions are not defined in any standard header, no currently existing code behavior will be changed.</p> <a name="Design"></a><h2>VII. Design Decisions</h2> <p> Since there is no reason to compare <code>true</code> and <code>false</code> with other integral types, there isn't one to provide an overload for the <code>bool</code> integral type either.</br> The name of the functions (<code>cmp_equal</code>, <code>cmp_less</code> and others) are open to discussion, but the function names <code>std::less</code> and <code>std::greater</code> should not be used, since these do already exist, and have a different meaning.</p> </body> </html> ------=_Part_893_515332329.1486229258407-- .

Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>

Date: Sun, 5 Feb 2017 16:10:15 +0100

Le 20/01/2017 =C3=A0 17:31, federico.kircheis@gmail.com a =C3=A9crit : > Hello to everyone, this is my first proposal, I hope you'll find it=20 > interesting, give me some feedback and help to improve my=20 > idea/implementation/proposal. > > > <snip> > > My proposal would be to add four templated functions which work only=20 > for integral types (bool excluded). > > The first function would be: > > template <typename R, typename T> constexpr bool in_range(const T t)=20 > noexcept; > > Usage > size_t i =3D=3D ... > if(in_range<DWORD>(i)){ > // safe to convert i to a DWORD value, parameter... > } else { > // not possible to represent i as a DWORD > } > There si something related in GSL narrow/narrow_cast. Your function=20 could be named can_be_narrowed<DWORD>(i). There could also be template <class T, class U> bool can_be_narrowed(U); template <class T, class U> optional<T> try_to_narrow(U); > The second function would be: > > template <typename T, typename U> constexpr bool cmp_equal(const T t,=20 > const U u) noexcept; > > Usage > size_t i =3D=3D ... > DWORD j =3D=3D ... > if(cmp_equal(i,j)){ > // i and j represent the same quantity > } else { > // i and j represents different quantities > } > > Currently we are going more towards 3-value comparisons (p0100r2). There=20 will surely be an additional operator <=3D>. It would be better to start=20 by defining some kind of safe_3compare. Have you considered defining a wrapper that has this safe semantic. if( safe(i) =3D=3D safe(j) ){ > <snip> > > The fourth function I would like to add is: > > template <typename T> constexpr std::size_t precision() noexcept; > > > The reasons are described here: > > https://www.securecoding.cert.org/confluence/display/c/INT35-C.+Use+corre= ct+integer+precisions > > Quote: > "Integer types in C have both a size and a precision. The size=20 > indicates the number of bytes used by an object and can be retrieved=20 > for any object or type using the sizeof operator. The precision of an=20 > integer type is the number of bits it uses to represent values,=20 > excluding any sign and padding bits. > > Padding bits contribute to the integer's size, but not to its=20 > precision. Consequently, inferring the precision of an integer type=20 > from its size may result in too large a value, which can then lead to=20 > incorrect assumptions about the numeric range of these types. =20 > Programmers should use correct integer precisions in their code, and=20 > in particular, should not use the sizeof operator to compute the=20 > precision of an integer type on architectures that use padding bits or=20 > in strictly conforming (that is, portable) programs." > > > The function precision is used internally (by cmp_equal, cmp_less and=20 > in_range) for verifying which type is bigger, in order to safely cast=20 > before comparing the types. I also think, that this function should be=20 > part of the API, since it is very handy. Wondering if you shouldn't use std::numeric_limits<T>, and if there is=20 not enough information there to request the addition of a trait? Vicente --=20 You received this message because you are subscribed to the Google Groups "= ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an e= mail to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp= ..org/d/msgid/std-proposals/a734e3fd-d203-1ed6-d605-bf54f6a6e1e9%40wanadoo.f= r. .

Author: federico.kircheis@gmail.com

Date: Mon, 6 Feb 2017 09:23:56 -0800 (PST)

------=_Part_1635_1008569127.1486401836450 Content-Type: multipart/alternative; boundary="----=_Part_1636_1841719393.1486401836450" ------=_Part_1636_1841719393.1486401836450 Content-Type: text/plain; charset=UTF-8 Hi Vicente, thank you for your feedback. I was not aware of narrow/narrow cast. If they do provide the same functionality and it's going to be in the next std release, then I could drop the proposal for "in_range". One possible issue is that you may not know, between two types, which is the bigger one (for example inside a templated function). So a function like "can_be_narrowed" does not seem right because you are not going to narrow, whereas "in_range" does not have that issue -> seems more generic to me. I cannot find any reference to the operator <=> (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0100r2.html), do you have a link? I would gladly drop the function "precision", but if you are comparing an unsigned type with a signed type, and both variables contains a positive value(!), how do you know if you need to cast them both to signed or to unsigned? If you do the comparison with std::numeric_limits without casting, an implicit conversion could give you an unexpected result (thats the whole point of this proposal). If you are comparing an uint_8t with an int_32t, you should cast to int_32t since it can contain all values of uint_8t, but if you are comparing and uint_16t with an int_16 you should cast to uint_16t, since it can contain all positive values of int_16t. So it depends on how big the "range" of the types are, i.e. how precise they are. Normally I would use the sizeof operator to determine which of both types is more precise, but as stated in securecoding, padding bits may be an issue. So why not provide this function to the end user as a bonus? Of course this function is not strictly necessary (it's an implementation detail), and can be removed from the proposal too, even if it seems to me a nice addition. -- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/6a3e0be1-3a7a-4cfd-a4a9-d49cd72bb52b%40isocpp.org. ------=_Part_1636_1841719393.1486401836450 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">Hi Vicente,<br><br>thank you for your feedback.<br><br>I w= as not aware of narrow/narrow cast.<br>If they do provide the same function= ality and it's going to be in the next std release, then I could drop t= he proposal for "in_range".<br><br>One possible issue is that you= may not know, between two types, which is the bigger one (for example insi= de a templated function). So a function like "can_be_narrowed" do= es not seem right because you are not going to narrow, whereas "in_ran= ge" does not have that issue -> seems more generic to me.<br><br>I = cannot find any reference to the operator <=3D> (http://www.open-std.= org/jtc1/sc22/wg21/docs/papers/2016/p0100r2.html), do you have a link?<br><= br>I would gladly drop the function "precision", but if you are c= omparing an unsigned type with a signed type, and both variables contains a= positive value(!), how do you know if you need to cast them both to signed= or to unsigned? If you do the comparison with std::numeric_limits without = casting, an implicit conversion could give you an unexpected result (thats = the whole point of this proposal).<br><br>If you are comparing an uint_8t w= ith an int_32t, you should cast to int_32t since it can contain all values = of uint_8t, but if you are comparing and uint_16t with an int_16 you should= cast to uint_16t, since it can contain all positive values of int_16t.<br>= So it depends on how big the "range" of the types are, i.e. how p= recise they are.<br>Normally I would use the sizeof operator to determine w= hich of both types is more precise, but as stated in securecoding, padding = bits may be an issue. So why not provide this function to the end user as a= bonus? Of course this function is not strictly necessary (it's an impl= ementation detail), and can be removed from the proposal too, even if it se= ems to me a nice addition.<br><br><br></div> <p></p> -- <br /> You received this message because you are subscribed to the Google Groups &= quot;ISO C++ Standard - Future Proposals" group.<br /> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa= ls+unsubscribe@isocpp.org</a>.<br /> To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp= ..org">std-proposals@isocpp.org</a>.<br /> To view this discussion on the web visit <a href=3D"https://groups.google.c= om/a/isocpp.org/d/msgid/std-proposals/6a3e0be1-3a7a-4cfd-a4a9-d49cd72bb52b%= 40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.= com/a/isocpp.org/d/msgid/std-proposals/6a3e0be1-3a7a-4cfd-a4a9-d49cd72bb52b= %40isocpp.org</a>.<br /> ------=_Part_1636_1841719393.1486401836450-- ------=_Part_1635_1008569127.1486401836450-- .

Author: federico.kircheis@gmail.com

Date: Mon, 6 Feb 2017 09:30:20 -0800 (PST)

------=_Part_1493_1946882933.1486402220720 Content-Type: multipart/alternative; boundary="----=_Part_1494_1181049605.1486402220720" ------=_Part_1494_1181049605.1486402220720 Content-Type: text/plain; charset=UTF-8 I've not considered a wrapper, seems like a nice idea, I'll think about it. But before considering it, I think we should provide some basic functions for comparing values, the wrapper can be built on top of that. -- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/3f13d67f-ee5a-4f73-9bae-7f4f448e1027%40isocpp.org. ------=_Part_1494_1181049605.1486402220720 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">I've not considered a wrapper, seems like a nice idea,= I'll think about it.<br><br><br>But before considering it, I think we = should provide some basic functions for comparing values, the wrapper can b= e built on top of that.<br><br></div> <p></p> -- <br /> You received this message because you are subscribed to the Google Groups &= quot;ISO C++ Standard - Future Proposals" group.<br /> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa= ls+unsubscribe@isocpp.org</a>.<br /> To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp= ..org">std-proposals@isocpp.org</a>.<br /> To view this discussion on the web visit <a href=3D"https://groups.google.c= om/a/isocpp.org/d/msgid/std-proposals/3f13d67f-ee5a-4f73-9bae-7f4f448e1027%= 40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.= com/a/isocpp.org/d/msgid/std-proposals/3f13d67f-ee5a-4f73-9bae-7f4f448e1027= %40isocpp.org</a>.<br /> ------=_Part_1494_1181049605.1486402220720-- ------=_Part_1493_1946882933.1486402220720-- .

Author: Robert Ramey <ramey@rrsd.com>

Date: Mon, 6 Feb 2017 09:40:38 -0800

On 2/6/17 9:30 AM, federico.kircheis@gmail.com wrote: > I've not considered a wrapper, seems like a nice idea, I'll think about it. > > > But before considering it, I think we should provide some basic > functions for comparing values, the wrapper can be built on top of that. > > -- > You received this message because you are subscribed to the Google > Groups "ISO C++ Standard - Future Proposals" group. > To unsubscribe from this group and stop receiving emails from it, send > an email to std-proposals+unsubscribe@isocpp.org > <mailto:std-proposals+unsubscribe@isocpp.org>. > To post to this group, send email to std-proposals@isocpp.org > <mailto:std-proposals@isocpp.org>. > To view this discussion on the web visit > https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/3f13d67f-ee5a-4f73-9bae-7f4f448e1027%40isocpp.org > <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/3f13d67f-ee5a-4f73-9bae-7f4f448e1027%40isocpp.org?utm_medium=email&utm_source=footer>. Have you looked at the safe_numerics library. It can be found in the boost library incubator. It is the subject of an article in the forthcoming version of ACCU Overload. A version has been proposed for the C++ standard. And it addresses all known issues related to comparison of integer types. Robert Ramey -- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/5c9e5cc7-584b-8913-78f0-c0f4547dba3e%40rrsd.com. .

Author: federico.kircheis@gmail.com

Date: Mon, 26 Jun 2017 12:45:52 -0700 (PDT)

------=_Part_1924_1373988190.1498506353062 Content-Type: multipart/alternative; boundary="----=_Part_1925_1372842292.1498506353062" ------=_Part_1925_1372842292.1498506353062 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hello, sorry for my absence, I thought I had responded to you. The safe_numerics library offers a lot more functionality than my proposal. I've read some samples, it's not clear to me if you can do simple=20 comparisons like the ones proposed by me, should investigate further, or=20 does someone else have more experience? Il giorno luned=C3=AC 6 febbraio 2017 18:40:49 UTC+1, Robert Ramey ha scrit= to: > > > > Have you looked at the safe_numerics library. It can be found in the=20 > boost library incubator. It is the subject of an article in the=20 > forthcoming version of ACCU Overload. A version has been proposed for=20 > the C++ standard. And it addresses all known issues related to=20 > comparison of integer types.=20 > > Robert Ramey=20 > --=20 You received this message because you are subscribed to the Google Groups "= ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an e= mail to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp= ..org/d/msgid/std-proposals/db7ad582-79fe-4f79-a790-84d10dc5679d%40isocpp.or= g. ------=_Part_1925_1372842292.1498506353062 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr"><br>Hello, sorry for my absence, I thought I had responded= to you.<br><br>The safe_numerics library offers a lot more functionality t= han my proposal.<br><br>I've read some samples, it's not clear to me if you can do simple=20 comparisons like the ones proposed by me, should investigate further, or does someone else have more experience?<br><br><br>Il giorno luned=C3=AC 6= febbraio 2017 18:40:49 UTC+1, Robert Ramey ha scritto:<blockquote class=3D= "gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc s= olid;padding-left: 1ex;"><br> <br>Have you looked at the safe_numerics library. =C2=A0It can be found in = the=20 <br>boost library incubator. =C2=A0It is the subject of an article in the= =20 <br>forthcoming version of ACCU Overload. =C2=A0A version has been proposed= for=20 <br>the C++ standard. =C2=A0And it addresses all known issues related to=20 <br>comparison of integer types. <br> <br>Robert Ramey <br></blockquote></div> <p></p> -- <br /> You received this message because you are subscribed to the Google Groups &= quot;ISO C++ Standard - Future Proposals" group.<br /> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa= ls+unsubscribe@isocpp.org</a>.<br /> To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp= ..org">std-proposals@isocpp.org</a>.<br /> To view this discussion on the web visit <a href=3D"https://groups.google.c= om/a/isocpp.org/d/msgid/std-proposals/db7ad582-79fe-4f79-a790-84d10dc5679d%= 40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.= com/a/isocpp.org/d/msgid/std-proposals/db7ad582-79fe-4f79-a790-84d10dc5679d= %40isocpp.org</a>.<br /> ------=_Part_1925_1372842292.1498506353062-- ------=_Part_1924_1373988190.1498506353062-- .

Author: Mingxin Wang <wmx16835vv@163.com>

Date: Mon, 26 Jun 2017 22:05:43 -0700 (PDT)

------=_Part_711_1432126139.1498539944103 Content-Type: multipart/alternative; boundary="----=_Part_712_416217759.1498539944104" ------=_Part_712_416217759.1498539944104 Content-Type: text/plain; charset="UTF-8" This is a good idea! However, I think maybe the following issues shall be considered. *This feature may introduce unnecessary extra overhead* Comparing to bare comparators between signed and unsigned integral types, this feature requires *one extra comparation* between the signed one and ZERO at runtime. Actually, it is not always necessary in some cases, e.g. std::vector<int> v; for (int i = 0; i < v.size(); ++i) { // ... } Although variable i is a signed integer, the comparation is always executed correctly providing v.size() won't exceed std::numeric_limits<int>::max(). Thus the extra comparation introduced in your solution is redundant as we can assert that i is always positive. Still, I think there is enough motivation for us to have this feature. *A uniform wrapper* Although the problem can be solved with a uniform wrapper, that would introduce even much overhead, especially when there are implementation defined integral types, e.g. __int128 in GCC. *Implementation with Concepts TS* I think the implementation could be much simpler with Concepts TS. For instance, we can define different overloads for the function template cmp_less with different constraints, as is shown below: template <class T, class U> bool cmp_less(const T&, const U&); // undefined template <class T, class U> bool cmp_less(const T& lhs, const U& rhs) requires std::is_signed_v<T> == std::is_signed_v<U> { return lhs < rhs; } template <class T, class U> bool cmp_less(const T& lhs, const U& rhs) requires std::is_signed_v<T> && !std::is_signed_v<U> { return lhs < 0 ? true : lhs < rhs; } template <class T, class U> bool cmp_less(const T& lhs, const U& rhs) requires !std::is_signed_v<T> && std::is_signed_v<U> { return rhs < 0 ? false : lhs < rhs; } I hope these would help. Mingxin Wang -- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/aa356514-dd5d-4210-8882-ffcef3ae1449%40isocpp.org. ------=_Part_712_416217759.1498539944104 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">This is a good idea! However, I think maybe the following = issues shall be considered.<div><br></div><div><b>This feature=C2=A0may int= roduce unnecessary extra overhead</b></div><div><br></div><div>Comparing to= bare comparators between signed and unsigned integral types, this feature = requires <i>one extra comparation</i> between the signed one and ZERO at ru= ntime. Actually, it is not always necessary in some cases, e.g.</div><div><= br></div><div><div class=3D"prettyprint" style=3D"border: 1px solid rgb(187= , 187, 187); word-wrap: break-word; background-color: rgb(250, 250, 250);">= <code class=3D"prettyprint"><div class=3D"subprettyprint"><div class=3D"sub= prettyprint"><div class=3D"subprettyprint">std::vector<int> v;</div><= div class=3D"subprettyprint">for (int i =3D 0; i < v.size(); ++i) {</div= ><div class=3D"subprettyprint">=C2=A0 // ...</div><div class=3D"subprettypr= int">}</div></div></div></code></div><br>Although variable i is a signed in= teger, the comparation is always executed=C2=A0correctly providing v.size()= won't exceed=C2=A0std::numeric_limits<int>::max(). Thus the extr= a comparation introduced in your solution is redundant as we can assert tha= t i is always positive. Still, I think there is enough motivation for us to= have this feature.</div><div><br></div><div><b>A uniform wrapper</b></div>= <div><br></div><div>Although the problem can be solved with a uniform wrapp= er, that would introduce even much overhead, especially when there are impl= ementation defined integral types, e.g.=C2=A0__int128 in GCC.</div><div><br= ></div><div><b>Implementation with Concepts TS</b></div><div><br></div><div= >I think the implementation could be much simpler with Concepts TS. For ins= tance, we can define different overloads for the function template cmp_less= with different constraints, as is shown below:</div><div><br></div><div><d= iv class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187, 187); wor= d-wrap: break-word; background-color: rgb(250, 250, 250);"><code class=3D"p= rettyprint"><div class=3D"subprettyprint"><font color=3D"#660066"><div clas= s=3D"subprettyprint">template <class T, class U></div><div class=3D"s= ubprettyprint">bool cmp_less(const T&, const U&); // undefined</div= ><div class=3D"subprettyprint"><br></div><div class=3D"subprettyprint">temp= late <class T, class U></div><div class=3D"subprettyprint">bool cmp_l= ess(const T& lhs, const U& rhs) requires std::is_signed_v<T> = =3D=3D std::is_signed_v<U> {</div><div class=3D"subprettyprint">=C2= =A0 return lhs < rhs;</div><div class=3D"subprettyprint">}</div><div cla= ss=3D"subprettyprint"><br></div><div class=3D"subprettyprint">template <= class T, class U></div><div class=3D"subprettyprint">bool cmp_less(const= T& lhs, const U& rhs) requires std::is_signed_v<T> &&= ; !std::is_signed_v<U> {</div><div class=3D"subprettyprint">=C2=A0 re= turn lhs < 0 ? true : lhs < rhs;</div><div class=3D"subprettyprint">}= </div><div class=3D"subprettyprint"><br></div><div class=3D"subprettyprint"= >template <class T, class U></div><div class=3D"subprettyprint">bool = cmp_less(const T& lhs, const U& rhs) requires !std::is_signed_v<= T> && std::is_signed_v<U> {</div><div class=3D"subprettypr= int">=C2=A0 return rhs < 0 ? false : lhs < rhs;</div><div class=3D"su= bprettyprint">}</div></font></div></code></div></div><div><br></div><div>I = hope these would help.</div><div><br></div><div>Mingxin Wang</div></div> <p></p> -- <br /> You received this message because you are subscribed to the Google Groups &= quot;ISO C++ Standard - Future Proposals" group.<br /> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa= ls+unsubscribe@isocpp.org</a>.<br /> To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp= ..org">std-proposals@isocpp.org</a>.<br /> To view this discussion on the web visit <a href=3D"https://groups.google.c= om/a/isocpp.org/d/msgid/std-proposals/aa356514-dd5d-4210-8882-ffcef3ae1449%= 40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.= com/a/isocpp.org/d/msgid/std-proposals/aa356514-dd5d-4210-8882-ffcef3ae1449= %40isocpp.org</a>.<br /> ------=_Part_712_416217759.1498539944104-- ------=_Part_711_1432126139.1498539944103-- .

Author: federico.kircheis@gmail.com

Date: Mon, 26 Jun 2017 22:39:48 -0700 (PDT)

------=_Part_2208_1007536684.1498541988676 Content-Type: multipart/alternative; boundary="----=_Part_2209_1274626402.1498541988676" ------=_Part_2209_1274626402.1498541988676 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi, thank you for your feedback. The correct usage for the for-loop would be to use the right type,=20 otherwise you may overflow. I would not use cmp_less or cmp_equal here the real point of failure is the= =20 ++ operation. HI, I'm not sure what you mean about the extra overhead. The functions are constexpr and the branch std::is_signed can also be=20 evaluated at compile time. Therefore comparing an unsigned value with 0 is equivalent to return (t<T{ 0 }) ? false : (precision<T>() / 2>precision<U>()) ? (t =3D=3D= static_cast<T>(u)) : (static_cast<U>(t) =3D=3D u); precision is constexpr too, so it should be a simple =3D=3D operation with = a=20 static_cast. I don't see the extra comparison, or am I missing something? Of course it depends on the ability of the compiler to optimize the=20 branches at compile time (doable AFAIK), and if those functions are part of= =20 the std::, i would expect such an optimization even more. Il giorno marted=C3=AC 27 giugno 2017 07:05:44 UTC+2, Mingxin Wang ha scrit= to: > > This is a good idea! However, I think maybe the following issues shall be= =20 > considered. > > *This feature may introduce unnecessary extra overhead* > > Comparing to bare comparators between signed and unsigned integral types,= =20 > this feature requires *one extra comparation* between the signed one and= =20 > ZERO at runtime. Actually, it is not always necessary in some cases, e.g. > > std::vector<int> v; > for (int i =3D 0; i < v.size(); ++i) { > // ... > } > > Although variable i is a signed integer, the comparation is always=20 > executed correctly providing v.size() won't=20 > exceed std::numeric_limits<int>::max(). Thus the extra comparation=20 > introduced in your solution is redundant as we can assert that i is alway= s=20 > positive. Still, I think there is enough motivation for us to have this= =20 > feature. > > *A uniform wrapper* > > Although the problem can be solved with a uniform wrapper, that would=20 > introduce even much overhead, especially when there are implementation=20 > defined integral types, e.g. __int128 in GCC. > > *Implementation with Concepts TS* > > I think the implementation could be much simpler with Concepts TS. For=20 > instance, we can define different overloads for the function template=20 > cmp_less with different constraints, as is shown below: > > template <class T, class U> > bool cmp_less(const T&, const U&); // undefined > > template <class T, class U> > bool cmp_less(const T& lhs, const U& rhs) requires std::is_signed_v<T> = =3D=3D=20 > std::is_signed_v<U> { > return lhs < rhs; > } > > template <class T, class U> > bool cmp_less(const T& lhs, const U& rhs) requires std::is_signed_v<T> &&= =20 > !std::is_signed_v<U> { > return lhs < 0 ? true : lhs < rhs; > } > > template <class T, class U> > bool cmp_less(const T& lhs, const U& rhs) requires !std::is_signed_v<T> &= &=20 > std::is_signed_v<U> { > return rhs < 0 ? false : lhs < rhs; > } > > I hope these would help. > > Mingxin Wang > --=20 You received this message because you are subscribed to the Google Groups "= ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an e= mail to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp= ..org/d/msgid/std-proposals/7fa4ec6e-de06-414c-880a-7c9e52132803%40isocpp.or= g. ------=_Part_2209_1274626402.1498541988676 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">Hi, thank you for your feedback.<br><br>The correct usage = for the for-loop would be to use the right type, otherwise you may overflow= ..<br>I would not use cmp_less or cmp_equal here the real point of failure i= s the ++ operation.<br><br>HI, I'm not sure what you mean about the ext= ra overhead.<br>The functions are constexpr and the branch std::is_signed c= an also be evaluated at compile time.<br><br>Therefore comparing an unsigne= d value with 0 is equivalent to<br><div><br></div><div style=3D"border:1px = solid rgb(187,187,187);word-wrap:break-word;background-color:rgb(250,250,25= 0)"><code><div><div><pre>return (t<T{ 0 }) ? false : (precision<T>= () / 2>precision<U>()) ? (t =3D=3D static_cast<T>(u)) : (sta= tic_cast<U>(t) =3D=3D u);</pre></div></div></code></div><pre></pre>pr= ecision is constexpr too, so it should be a simple =3D=3D operation with a = static_cast. I don't see the extra comparison, or am I missing somethin= g?<br><br>Of course it depends on the ability of the compiler to optimize t= he branches at compile time (doable AFAIK), and if those functions are part= of the std::, i would expect such an optimization even more.<br><br>Il gio= rno marted=C3=AC 27 giugno 2017 07:05:44 UTC+2, Mingxin Wang ha scritto:<bl= ockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border= -left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">This is a good i= dea! However, I think maybe the following issues shall be considered.<div><= br></div><div><b>This feature=C2=A0may introduce unnecessary extra overhead= </b></div><div><br></div><div>Comparing to bare comparators between signed = and unsigned integral types, this feature requires <i>one extra comparation= </i> between the signed one and ZERO at runtime. Actually, it is not always= necessary in some cases, e.g.</div><div><br></div><div><div style=3D"borde= r:1px solid rgb(187,187,187);word-wrap:break-word;background-color:rgb(250,= 250,250)"><code><div><div><div>std::vector<int> v;</div><div>for (int= i =3D 0; i < v.size(); ++i) {</div><div>=C2=A0 // ...</div><div>}</div>= </div></div></code></div><br>Although variable i is a signed integer, the c= omparation is always executed=C2=A0correctly providing v.size() won't e= xceed=C2=A0std::numeric_limits<<wbr>int>::max(). Thus the extra compa= ration introduced in your solution is redundant as we can assert that i is = always positive. Still, I think there is enough motivation for us to have t= his feature.</div><div><br></div><div><b>A uniform wrapper</b></div><div><b= r></div><div>Although the problem can be solved with a uniform wrapper, tha= t would introduce even much overhead, especially when there are implementat= ion defined integral types, e.g.=C2=A0__int128 in GCC.</div><div><br></div>= <div><b>Implementation with Concepts TS</b></div><div><br></div><div>I thin= k the implementation could be much simpler with Concepts TS. For instance, = we can define different overloads for the function template cmp_less with d= ifferent constraints, as is shown below:</div><div><br></div><div><div styl= e=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;background-colo= r:rgb(250,250,250)"><code><div><font color=3D"#660066"><div>template <cl= ass T, class U></div><div>bool cmp_less(const T&, const U&); // = undefined</div><div><br></div><div>template <class T, class U></div><= div>bool cmp_less(const T& lhs, const U& rhs) requires std::is_sign= ed_v<T> =3D=3D std::is_signed_v<U> {</div><div>=C2=A0 return lh= s < rhs;</div><div>}</div><div><br></div><div>template <class T, clas= s U></div><div>bool cmp_less(const T& lhs, const U& rhs) require= s std::is_signed_v<T> && !std::is_signed_v<U> {</div><d= iv>=C2=A0 return lhs < 0 ? true : lhs < rhs;</div><div>}</div><div><b= r></div><div>template <class T, class U></div><div>bool cmp_less(cons= t T& lhs, const U& rhs) requires !std::is_signed_v<T> &&a= mp; std::is_signed_v<U> {</div><div>=C2=A0 return rhs < 0 ? false = : lhs < rhs;</div><div>}</div></font></div></code></div></div><div><br><= /div><div>I hope these would help.</div><div><br></div><div>Mingxin Wang</d= iv></div></blockquote></div> <p></p> -- <br /> You received this message because you are subscribed to the Google Groups &= quot;ISO C++ Standard - Future Proposals" group.<br /> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa= ls+unsubscribe@isocpp.org</a>.<br /> To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp= ..org">std-proposals@isocpp.org</a>.<br /> To view this discussion on the web visit <a href=3D"https://groups.google.c= om/a/isocpp.org/d/msgid/std-proposals/7fa4ec6e-de06-414c-880a-7c9e52132803%= 40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.= com/a/isocpp.org/d/msgid/std-proposals/7fa4ec6e-de06-414c-880a-7c9e52132803= %40isocpp.org</a>.<br /> ------=_Part_2209_1274626402.1498541988676-- ------=_Part_2208_1007536684.1498541988676-- .

Author: Mingxin Wang <wmx16835vv@163.com>

Date: Mon, 26 Jun 2017 23:43:34 -0700 (PDT)

------=_Part_2107_1791991667.1498545814293 Content-Type: multipart/alternative; boundary="----=_Part_2108_1423952121.1498545814293" ------=_Part_2108_1423952121.1498545814293 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Tuesday, June 27, 2017 at 1:39:48 PM UTC+8, federico...@gmail.com wrote: > > Hi, thank you for your feedback. > > The correct usage for the for-loop would be to use the right type,=20 > otherwise you may overflow. > I would not use cmp_less or cmp_equal here the real point of failure is= =20 > the ++ operation. > =20 Discard of the possibility of overflow, this sort of for-loop was widely=20 used in many cases, e.g. enumerating all subsets of a set with binary=20 operations: template <class T> std::vector<std::vector<T>> generate_subsets(const std::vector<T>& v) { std::vector<std::vector<T>> res; for (int i =3D 0; i < (1 << (int)v.size()); ++i) { res.emplace_back(); for (int j =3D 0; j < (int)v.size(); ++j) { if ((i >> j & 1) =3D=3D 1) { res.back().push_back(v[j]); } } } return res; } This is an algorithm whose complexity is O(2^n). Providing n is not greater= =20 than 20, I perfer to use "int" to implement this algorithm instead of=20 std::size_t to gain higher performance. =20 > HI, I'm not sure what you mean about the extra overhead. > The functions are constexpr and the branch std::is_signed can also be=20 > evaluated at compile time. > > Therefore comparing an unsigned value with 0 is equivalent to > > return (t<T{ 0 }) ? false : (precision<T>() / 2>precision<U>()) ? (t =3D= =3D static_cast<T>(u)) : (static_cast<U>(t) =3D=3D u); > > precision is constexpr too, so it should be a simple =3D=3D operation wit= h a=20 > static_cast. I don't see the extra comparison, or am I missing something? > > Of course it depends on the ability of the compiler to optimize the=20 > branches at compile time (doable AFAIK), and if those functions are part = of=20 > the std::, i would expect such an optimization even more. > If a function is constexpr, it is only guaranteed that the returned value= =20 is constexpr providing the input data is constexpr, otherwise (when the=20 input data is not constexpr) the function is not guaranteed to be=20 calculated at compile time. Il giorno marted=C3=AC 27 giugno 2017 07:05:44 UTC+2, Mingxin Wang ha scrit= to: >> >> This is a good idea! However, I think maybe the following issues shall b= e=20 >> considered. >> >> *This feature may introduce unnecessary extra overhead* >> >> Comparing to bare comparators between signed and unsigned integral types= ,=20 >> this feature requires *one extra comparation* between the signed one and= =20 >> ZERO at runtime. Actually, it is not always necessary in some cases, e.g= .. >> >> std::vector<int> v; >> for (int i =3D 0; i < v.size(); ++i) { >> // ... >> } >> >> Although variable i is a signed integer, the comparation is always=20 >> executed correctly providing v.size() won't=20 >> exceed std::numeric_limits<int>::max(). Thus the extra comparation=20 >> introduced in your solution is redundant as we can assert that i is alwa= ys=20 >> positive. Still, I think there is enough motivation for us to have this= =20 >> feature. >> >> *A uniform wrapper* >> >> Although the problem can be solved with a uniform wrapper, that would=20 >> introduce even much overhead, especially when there are implementation= =20 >> defined integral types, e.g. __int128 in GCC. >> >> *Implementation with Concepts TS* >> >> I think the implementation could be much simpler with Concepts TS. For= =20 >> instance, we can define different overloads for the function template=20 >> cmp_less with different constraints, as is shown below: >> >> template <class T, class U> >> bool cmp_less(const T&, const U&); // undefined >> >> template <class T, class U> >> bool cmp_less(const T& lhs, const U& rhs) requires std::is_signed_v<T> = =3D=3D=20 >> std::is_signed_v<U> { >> return lhs < rhs; >> } >> >> template <class T, class U> >> bool cmp_less(const T& lhs, const U& rhs) requires std::is_signed_v<T> &= &=20 >> !std::is_signed_v<U> { >> return lhs < 0 ? true : lhs < rhs; >> } >> >> template <class T, class U> >> bool cmp_less(const T& lhs, const U& rhs) requires !std::is_signed_v<T>= =20 >> && std::is_signed_v<U> { >> return rhs < 0 ? false : lhs < rhs; >> } >> >> I hope these would help. >> >> Mingxin Wang >> > --=20 You received this message because you are subscribed to the Google Groups "= ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an e= mail to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp= ..org/d/msgid/std-proposals/da719152-215c-420a-9b3d-cccdea4171d4%40isocpp.or= g. ------=_Part_2108_1423952121.1498545814293 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">On Tuesday, June 27, 2017 at 1:39:48 PM UTC+8, federico...= @gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margi= n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l= tr">Hi, thank you for your feedback.<br><br>The correct usage for the for-l= oop would be to use the right type, otherwise you may overflow.<br>I would = not use cmp_less or cmp_equal here the real point of failure is the ++ oper= ation.<br></div></blockquote><div>=C2=A0</div><div>Discard of the possibili= ty of overflow, this sort of for-loop was widely used in many cases, e.g.= =C2=A0enumerating all subsets of a set with binary operations:<br></div><di= v><br></div><div><div class=3D"prettyprint" style=3D"border: 1px solid rgb(= 187, 187, 187); word-wrap: break-word; background-color: rgb(250, 250, 250)= ;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><div class=3D"= subprettyprint">template <class T></div><div class=3D"subprettyprint"= >std::vector<std::vector<T>> generate_subsets(const std::vector= <T>& v) {</div><div class=3D"subprettyprint">=C2=A0 std::vector&l= t;std::vector<T>> res;</div><div class=3D"subprettyprint">=C2=A0 f= or (int i =3D 0; i < (1 << (int)v.size()); ++i) {</div><div class= =3D"subprettyprint">=C2=A0 =C2=A0 res.emplace_back();</div><div class=3D"su= bprettyprint">=C2=A0 =C2=A0 for (int j =3D 0; j < (int)v.size(); ++j) {<= /div><div class=3D"subprettyprint">=C2=A0 =C2=A0 =C2=A0 if ((i >> j &= amp; 1) =3D=3D 1) {</div><div class=3D"subprettyprint">=C2=A0 =C2=A0 =C2=A0= =C2=A0 res.back().push_back(v[j]);</div><div class=3D"subprettyprint">=C2= =A0 =C2=A0 =C2=A0 }</div><div class=3D"subprettyprint">=C2=A0 =C2=A0 }</div= ><div class=3D"subprettyprint">=C2=A0 }</div><div class=3D"subprettyprint">= =C2=A0 return res;</div><div class=3D"subprettyprint">}</div></div></code><= /div><br>This is an algorithm whose complexity is O(2^n). Providing n is no= t greater than 20, I perfer to use "int" to implement this algori= thm instead of std::size_t to gain higher performance.</div><div>=C2=A0</di= v><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b= order-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">HI, I'm= not sure what you mean about the extra overhead.<br>The functions are cons= texpr and the branch std::is_signed can also be evaluated at compile time.<= br><br>Therefore comparing an unsigned value with 0 is equivalent to<br><di= v><br></div><div style=3D"border:1px solid rgb(187,187,187);word-wrap:break= -word;background-color:rgb(250,250,250)"><code><div><div><pre>return (t<= T{ 0 }) ? false : (precision<T>() / 2>precision<U>()) ? (t = =3D=3D static_cast<T>(u)) : (static_cast<U>(t) =3D=3D u);</pre>= </div></div></code></div><pre></pre>precision is constexpr too, so it shoul= d be a simple =3D=3D operation with a static_cast. I don't see the extr= a comparison, or am I missing something?<br><br>Of course it depends on the= ability of the compiler to optimize the branches at compile time (doable A= FAIK), and if those functions are part of the std::, i would expect such an= optimization even more.<br></div></blockquote><div><br></div><div>If a fun= ction is constexpr, it is only guaranteed that the returned value is conste= xpr providing the input data is constexpr, otherwise (when the input data i= s not constexpr) the function is not guaranteed to be calculated at compile= time.</div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margi= n: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><di= v dir=3D"ltr">Il giorno marted=C3=AC 27 giugno 2017 07:05:44 UTC+2, Mingxin= Wang ha scritto:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin= -left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">T= his is a good idea! However, I think maybe the following issues shall be co= nsidered.<div><br></div><div><b>This feature=C2=A0may introduce unnecessary= extra overhead</b></div><div><br></div><div>Comparing to bare comparators = between signed and unsigned integral types, this feature requires <i>one ex= tra comparation</i> between the signed one and ZERO at runtime. Actually, i= t is not always necessary in some cases, e.g.</div><div><br></div><div><div= style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;background= -color:rgb(250,250,250)"><code><div><div><div>std::vector<int> v;</di= v><div>for (int i =3D 0; i < v.size(); ++i) {</div><div>=C2=A0 // ...</d= iv><div>}</div></div></div></code></div><br>Although variable i is a signed= integer, the comparation is always executed=C2=A0correctly providing v.siz= e() won't exceed=C2=A0std::numeric_limits<<wbr>int>::max(). Thus = the extra comparation introduced in your solution is redundant as we can as= sert that i is always positive. Still, I think there is enough motivation f= or us to have this feature.</div><div><br></div><div><b>A uniform wrapper</= b></div><div><br></div><div>Although the problem can be solved with a unifo= rm wrapper, that would introduce even much overhead, especially when there = are implementation defined integral types, e.g.=C2=A0__int128 in GCC.</div>= <div><br></div><div><b>Implementation with Concepts TS</b></div><div><br></= div><div>I think the implementation could be much simpler with Concepts TS.= For instance, we can define different overloads for the function template = cmp_less with different constraints, as is shown below:</div><div><br></div= ><div><div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;= background-color:rgb(250,250,250)"><code><div><font color=3D"#660066"><div>= template <class T, class U></div><div>bool cmp_less(const T&, con= st U&); // undefined</div><div><br></div><div>template <class T, cla= ss U></div><div>bool cmp_less(const T& lhs, const U& rhs) requir= es std::is_signed_v<T> =3D=3D std::is_signed_v<U> {</div><div>= =C2=A0 return lhs < rhs;</div><div>}</div><div><br></div><div>template &= lt;class T, class U></div><div>bool cmp_less(const T& lhs, const U&a= mp; rhs) requires std::is_signed_v<T> && !std::is_signed_v<= ;U> {</div><div>=C2=A0 return lhs < 0 ? true : lhs < rhs;</div><di= v>}</div><div><br></div><div>template <class T, class U></div><div>bo= ol cmp_less(const T& lhs, const U& rhs) requires !std::is_signed_v&= lt;T> && std::is_signed_v<U> {</div><div>=C2=A0 return rhs= < 0 ? false : lhs < rhs;</div><div>}</div></font></div></code></div>= </div><div><br></div><div>I hope these would help.</div><div><br></div><div= >Mingxin Wang</div></div></blockquote></div></blockquote></div> <p></p> -- <br /> You received this message because you are subscribed to the Google Groups &= quot;ISO C++ Standard - Future Proposals" group.<br /> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa= ls+unsubscribe@isocpp.org</a>.<br /> To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp= ..org">std-proposals@isocpp.org</a>.<br /> To view this discussion on the web visit <a href=3D"https://groups.google.c= om/a/isocpp.org/d/msgid/std-proposals/da719152-215c-420a-9b3d-cccdea4171d4%= 40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.= com/a/isocpp.org/d/msgid/std-proposals/da719152-215c-420a-9b3d-cccdea4171d4= %40isocpp.org</a>.<br /> ------=_Part_2108_1423952121.1498545814293-- ------=_Part_2107_1791991667.1498545814293-- .

Author: federico.kircheis@gmail.com

Date: Tue, 27 Jun 2017 08:23:46 -0700 (PDT)

------=_Part_2460_530601555.1498577026311 Content-Type: multipart/alternative; boundary="----=_Part_2461_741436227.1498577026311" ------=_Part_2461_741436227.1498577026311 Content-Type: text/plain; charset="UTF-8" I'm sorry, I might have read your message to fast. Yes, the *only* situation where some overhead is involved is when a signed and an unsigned type (your use case actually), because you need to do some minimal checks about the ranges. It's the tradeoff between security/correctness and performance. Of course if you already know that the value is in the good range, there is no need to use my proposed functions (but you should assert it in case the surrounding code changes). The functions is_signed and precision do not take any parameter, they depend on the type of the argument, not the value of it, therefore they can always be executed at compile time. Of course the compiler is not forced to evaluate them at compile time, but I would expect it to do it if optimizations are enabled (and inline the functions too to avoid the function call overhead to, if it makes any difference). Of course the actual implementation does not have to be the one I proposed, there may be other that are simpler for the compiler to optimize, or to optimize to no overhead when comparing to specific values (for example 0). If you can assure that the increment operator will not be an issue, because, like you said, you know the size is not that big, then template <class T> std::vector<std::vector<T>> generate_subsets(const std::vector<T>& v) { std::vector<std::vector<T>> res; for (int i = 0; cmp_less(i, 1 << v.size()); ++i) { res.emplace_back(); for (int j = 0; cmp_less(j, v.size()); ++j) { if ((i >> j & 1) == 1) { // unsure if >> and & gives an int as result, otherwise replace with "cmp_equal(i>>j & 1, 1)" res.back().push_back(v[j]); } } } return res; } should give you the desired output. If a compiler is good enough, because the functions are pure and so on, the extra comparison could be optimized away, but at this point is QOI issue, and you may not wan't to rely on it if it is a "hot" function. I'm unsure about you comment about __int128. AFAIK my implementation should work with all integral types, __int128 and other compiler-specific included, if they pass (at compile time), the "is_integral_not_bool" test. -- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/fe04d87e-5b5e-452c-bd66-f7f43a86009c%40isocpp.org. ------=_Part_2461_741436227.1498577026311 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">I'm sorry, I might have read your message to fast.<br>= <br>Yes, the *only* situation where some overhead is involved is when a sig= ned=20 and an unsigned type (your use case actually), because you need to do=20 some minimal checks about the ranges. It's the tradeoff between=20 security/correctness and performance.<br>Of course if you already know=20 that the value is in the good range, there is no need to use my proposed functions (but you should assert it in case the surrounding=20 code changes).<br><br>The functions is_signed and precision do not take any= parameter, they depend on the type of the argument, not the value of it, t= herefore they can always be executed at compile time. Of course the compile= r is not forced to evaluate them at compile time, but I would expect it to = do it if optimizations are enabled (and inline the functions too to avoid t= he function call overhead to, if it makes any difference).<br>Of course the= actual implementation does not have to be the one I proposed, there may be= other that are simpler for the compiler to optimize, or to optimize to no = overhead when comparing to specific values (for example 0).<br><br><br>If y= ou can assure that the increment operator will not be an issue, because, li= ke you said, you know the size is not that big, then <br><div><br></div><di= v style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;backgroun= d-color:rgb(250,250,250)"><code><div><div>template <class T></div><di= v>std::vector<std::vector<T>> generate_subsets(const std::vecto= r<T>& v) {</div><div>=C2=A0 std::vector<std::vector<T>&g= t; res;</div><div>=C2=A0 for (int i =3D 0; cmp_less(i, 1 << v.size())= ; ++i) {</div><div>=C2=A0 =C2=A0 res.emplace_back();</div><div>=C2=A0 =C2= =A0 for (int j =3D 0; <code>cmp_less(</code>j, v.size()); ++j) {</div><div>= =C2=A0 =C2=A0 =C2=A0 if ((i >> j & 1) =3D=3D 1) { // unsure if &g= t;> and & gives an int as result, otherwise replace with "cmp_e= qual(i>>j & 1, 1)"<br></div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0= res.back().push_back(v[j]);</div><div>=C2=A0 =C2=A0 =C2=A0 }</div><div>=C2= =A0 =C2=A0 }</div><div>=C2=A0 }</div><div>=C2=A0 return res;</div><div>}</d= iv></div></code></div>should give you the desired output.<br>If a compiler = is good enough, because the functions are pure and so on, the extra compari= son could be optimized away, but at this point is QOI issue, and you may no= t wan't to rely on it if it is a "hot" function.<br><br><br><= br>I'm unsure about you comment about __int128. AFAIK my implementation= should work with all integral types, __int128 and other compiler-specific = included, if they pass (at compile time), the "is_integral_not_bool&qu= ot; test.<br><br><br><br></div> <p></p> -- <br /> You received this message because you are subscribed to the Google Groups &= quot;ISO C++ Standard - Future Proposals" group.<br /> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa= ls+unsubscribe@isocpp.org</a>.<br /> To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp= ..org">std-proposals@isocpp.org</a>.<br /> To view this discussion on the web visit <a href=3D"https://groups.google.c= om/a/isocpp.org/d/msgid/std-proposals/fe04d87e-5b5e-452c-bd66-f7f43a86009c%= 40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.= com/a/isocpp.org/d/msgid/std-proposals/fe04d87e-5b5e-452c-bd66-f7f43a86009c= %40isocpp.org</a>.<br /> ------=_Part_2461_741436227.1498577026311-- ------=_Part_2460_530601555.1498577026311-- .

Author: federico.kircheis@gmail.com

Date: Tue, 27 Jun 2017 10:00:55 -0700 (PDT)

------=_Part_2355_81630189.1498582855788 Content-Type: multipart/alternative; boundary="----=_Part_2356_678608755.1498582855788" ------=_Part_2356_678608755.1498582855788 Content-Type: text/plain; charset="UTF-8" I've updated my proposal (Proposal number is P0586R0). Just fixed some minor issues and added the proposal number, the content is the same. -- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/98e56e58-69bd-49f0-945c-aa6e7b6b4abb%40isocpp.org. ------=_Part_2356_678608755.1498582855788 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">I've updated my proposal (Proposal number is P0586R0).= <br><br>Just fixed some minor issues and added the proposal number, the con= tent is the same.<br></div> <p></p> -- <br /> You received this message because you are subscribed to the Google Groups &= quot;ISO C++ Standard - Future Proposals" group.<br /> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa= ls+unsubscribe@isocpp.org</a>.<br /> To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp= ..org">std-proposals@isocpp.org</a>.<br /> To view this discussion on the web visit <a href=3D"https://groups.google.c= om/a/isocpp.org/d/msgid/std-proposals/98e56e58-69bd-49f0-945c-aa6e7b6b4abb%= 40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.= com/a/isocpp.org/d/msgid/std-proposals/98e56e58-69bd-49f0-945c-aa6e7b6b4abb= %40isocpp.org</a>.<br /> ------=_Part_2356_678608755.1498582855788-- ------=_Part_2355_81630189.1498582855788 Content-Type: text/html; charset=US-ASCII; name=proposal.html Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=proposal.html X-Attachment-Id: c20d09fd-08a4-4bc3-b11f-36e733ccb8a1 Content-ID: <c20d09fd-08a4-4bc3-b11f-36e733ccb8a1> <!DOCTYPE html> <html> <head> <title>Safe integral comparisons</title> </head> <body> <address> Document number: P0586R0</br> Date: 2017-02-04</br> Project: Programming Language C++</br> Reply-to: <a href="mailto:federico.kircheis@gmail.com">Federico Kircheis</a><br/> </address> <h1>Safe integral comparisons</h1> <a name="Table"></a><h2>I. Table of Contents</h2> <ul> <li><a href="#Table">I. Table of Contents</a></li> <li><a href="#Motivation">II. Motivation</a></li> <li><a href="#Proposal">III. Proposal</a></li> <li><a href="#Examples">IV. Examples</a></li> <li><a href="#Sample">V. Sample implementation</a></li> <li><a href="#Effects">VI. Effects on Existing Code</a></li> <li><a href="#Design">VII. Design Decisions</a></li> </ul> <a name="Motivation"></a><h2>II. Motivation</h2> <p> Comparing integrals of different types may be a more complex task than expected. Most of the time we expect that a simple <blockquote><pre> if(a < b){ // ... } else { // ... } </pre></blockquote> should work in all cases, but if a and b are of different types, things are more complicated.</br> If <code>a</code> is a signed type, and <code>b</code> unsigned, then <code>a</code> is converted to the unsigned type. If <code>a</code> held a number less than zero, then the result may be unexpected, since the expression <code>a < b</code> could evaluate to false, even if a strictly negative number is always lower than a positive one.</br> </p> <p> Also converting integrals between different types can be challenging, for simplicity, most of the time we assume that values are in range, and write <blockquote><pre> a = static_cast<decltype(a)>(b); </pre></blockquote> If we want to write a safe conversion, we need to check if <code>b</code> has a value between <code>std::numeric_limits<decltype(a)>::min()</code> and <code>std::numeric_limits<decltype(a)>::max()</code>. We also need to pay attention that no implicit conversion (for example between unsigned and signed types) invalidates our comparison. </p> <p> Comparing and converting numbers, even of different numeric types, should be a trivial task. Unfortunately it is not, and because of implicit conversions we may write, without noticing it, unsafe code. </p> <a name="Proposal"></a><h2>III. Proposal</h2> <p> This paper proposes to add a set of <code>constexpr</code> and <code>noexcept</code> functions for converting and comparing integrals of different signeddes and precision (except for <code>bool</code>): <ul> <li> Two functions to compare if two variables represent the same value or not <blockquote><pre> template <typename T, typename U> constexpr bool std::cmp_equal(T t, U u) noexcept; template <typename T, typename U> constexpr bool std::cmp_unequal(T t, U u) noexcept; </pre></blockquote> <li> A set of functions that can be used to determine the relative order of two values <blockquote><pre> template <typename T, typename U> constexpr bool std::cmp_less(T t, U u) noexcept; template <typename T, typename U> constexpr bool std::cmp_greater(T t, U u) noexcept; template <typename T, typename U> constexpr bool std::cmp_less_or_equal(T t, U u) noexcept; template <typename T, typename U> constexpr bool std::cmp_greater_or_equal(T t, U u) noexcept; </pre></blockquote> <li> One function to determine if a specific value is inside the range of possible values of another type (i.e. if we can convert the value to the other type safely) <blockquote><pre> template <typename R, typename T> constexpr bool in_range(T t) noexcept; </pre></blockquote> <li> One function for retrieving the precision of a given numeric type <blockquote><pre> template <typename T> constexpr std::size_t std::precision() noexcept; </pre></blockquote> </ul> The function <code>precision</code> is part of the proposal because we cannot use the operator <code>sizeof</code> to determine between two types which one has a wider range (quote from <a href="https://www.securecoding.cert.org/confluence/display/c/INT35-C.+Use+correct+integer+precisions">SecureCoding</a>):</br> <q>Integer types in C have both a size and a precision. The size indicates the number of bytes used by an object and can be retrieved for any object or type using the sizeof operator. The precision of an integer type is the number of bits it uses to represent values, excluding any sign and padding bits. Padding bits contribute to the integer's size, but not to its precision. Consequently, inferring the precision of an integer type from its size may result in too large a value, which can then lead to incorrect assumptions about the numeric range of these types. Programmers should use correct integer precisions in their code, and in particular, should not use the sizeof operator to compute the precision of an integer type on architectures that use padding bits or in strictly conforming (that is, portable) programs.</q> </p> <a name="Examples"></a><h2>IV. Examples</h2> <h3>Examples without current proposal</h3> <p> Comparing an unsigned int with an int: <blockquote><pre> int a = ... unsigned int b = ... // added static_cast to avoid compiler warnings since we are doing a "safe" comparison if(a < 0 || static_cast<unsigned int>(a) < b){ // do X } else { // do Y } </pre></blockquote> Comparing an uint32_t with an int16_t: <blockquote><pre> int32_t a = ... uint16_t b = ... // added static_cast to avoid compiler warnings since we are doing a "safe" comparison if(a < static_cast<int32_t>(b)){ // do X } else { // do Y } </pre></blockquote> Comparing an int with an intptr_t: <blockquote><pre> int a = ... intptr_t b = ... if(???){ // no idea how to do it in one readable line without some assumption about int and intptr_t // do X } else { // do Y } </pre></blockquote> <h3>Example with current proposal</h3> Comparing one integral type <code>A</code> with another integral type <code>B</code> (both non <code>bool</code>): <blockquote><pre> A a = ... B b = ... // no need for any cast since std::cmp_less is taking care of everything if( std::cmp_less(a,b)){ // do X } else { // do Y } </pre></blockquote> </p> <a name="Sample"></a><h2>V. Sample implementation</h2> <p> This section shows an example of how <code>precision</code>, <code>cmp_equal</code>, <code>cmp_less</code> and <code>in_range</code> can be implemented with any standard conforming C++11 compiler, without any language extension. The only dependencies are the <code>std::numeric_limits</code> function from the <code>limits</code> header and some traits from the <code>type_traits</code> header. <blockquote><pre> #include <limits> #include <type_traits> template <typename T> constexpr std::size_t precision() noexcept; namespace details{ #if defined(ERR_MSG_xxx_NEEDS_INTEGRAL_NOT_BOOL) || defined(ASSERT_INTEGRAL_NOT_BOOL_TYPE) #error "ERR_MSG_xxx_NEEDS_INTEGRAL_NOT_BOOL or ASSERT_INTEGRAL_NOT_BOOL_TYPE already defined" #endif #define ERR_MSG_xxx_NEEDS_INTEGRAL_NOT_BOOL " needs to be an integral (not bool) value type" #define ASSERT_INTEGRAL_NOT_BOOL_TYPE(T) static_assert(is_integral_not_bool<T>(), #T ERR_MSG_xxx_NEEDS_INTEGRAL_NOT_BOOL); template <typename T> constexpr bool is_integral_not_bool(){ using value_type = typename std::remove_cv<T>::type; return !std::is_same<value_type,bool>::value && std::is_integral<T>::value; } template <class T> constexpr std::size_t pop(const std::size_t precision, const T num) { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); return (num == T{0}) ? precision : pop(((num % 2 != 0) ? precision+1 : precision), num >> 1); } // could use the same implementation of in_range_signed_signed, but compiler may generate warning that t is always bigger than 0 template <typename R, typename T> constexpr bool in_range_unsigned_unsigned(const T t) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(R); return (precision<T>() > precision<R>()) ? (t < static_cast<T>(std::numeric_limits<R>::max())) : (static_cast<R>(t) <std::numeric_limits<R>::max()); } template <typename R, typename T> constexpr bool in_range_signed_signed(const T t) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(R); return (precision<T>() > precision<R>()) ? (t <= static_cast<T>(std::numeric_limits<R>::max()) && t >= static_cast<T>(std::numeric_limits<R>::min())) : (static_cast<R>(t) <= std::numeric_limits<R>::max() && static_cast<R>(t) >= std::numeric_limits<R>::max()); } template <typename R, typename T> constexpr bool in_range_signed_unsigned(const T t) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(R); return (t < T{ 0 }) ? false : (precision<T>() / 2 <= precision<R>()) ? true : (t <= static_cast<T>(std::numeric_limits<R>::max())); } template <typename R, typename T> constexpr bool in_range_unsigned_signed(const T t) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(R); return (precision<T>() >= precision<R>() / 2) ? (t <= static_cast<T>(std::numeric_limits<R>::max())) : true; } template <typename R, typename T> constexpr bool in_range_unsigned(const T t) noexcept { return std::is_unsigned<R>::value ? in_range_unsigned_unsigned<R>(t) : in_range_unsigned_signed<R>(t); } template <typename R, typename T> constexpr bool in_range_signed(const T t) noexcept { return std::is_signed<R>::value ? in_range_signed_signed<R>(t) : in_range_signed_unsigned<R>(t); } template <typename T, typename U> constexpr bool cmp_equal_same_sign(const T t, const U u) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(U); return (precision<T>()>precision<U>()) ? (t == static_cast<T>(u)) : (static_cast<U>(t) == u); } template <typename T, typename U> constexpr bool cmp_equal_signed_unsigned(const T t, const U u) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(U); return (t<T{ 0 }) ? false : (precision<T>() / 2>precision<U>()) ? (t == static_cast<T>(u)) : (static_cast<U>(t) == u); } template <typename T, typename U> constexpr bool cmp_less_same_sign(const T t, const U u) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(U); return (precision<T>()>precision<U>()) ? (t < static_cast<T>(u)) : (static_cast<U>(t) < u); } template <typename T, typename U> constexpr bool cmp_less_signed_unsigned(const T t, const U u) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(U); return (t<T{ 0 }) ? true : (precision<T>() / 2>precision<U>()) ? (t < static_cast<T>(u)) : (static_cast<U>(t) < u); } template <typename T, typename U> constexpr bool cmp_less_unsigned_signed(const T t, const U u) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(U); return (u<U{ 0 }) ? false : (precision<U>() / 2>precision<T>()) ? (static_cast<U>(t) < u) : (t < static_cast<T>(u)); } #undef ERR_MSG_xxx_NEEDS_INTEGRAL_NOT_BOOL #undef ASSERT_INTEGRAL_NOT_BOOL_TYPE } // end details template <typename T> constexpr std::size_t precision() noexcept { return details::pop(0, std::numeric_limits<T>::max()); } /// Usage: /// size_t i = ... /// if(in_range<DWORD>(i)){ /// // safe to use i as a DWORD value, parameter... /// } else { /// // not possible to rappresent i as a DWORD /// } template <typename R, typename T> constexpr bool in_range(const T t) noexcept { return std::is_unsigned<T>::value ? details::in_range_unsigned<R>(t) : details::in_range_signed<R>(t); } // equivalent of operator== for different types /// Usage: /// size_t i = ... /// DWORD j = ... /// if(cmp_equal(i,j)){ /// // i and j rappresent the same quantity /// } else { /// // i and j rappresents different quantities /// } template <typename T, typename U> constexpr bool cmp_equal(const T t, const U u) noexcept { return (std::is_signed<T>::value == std::is_signed<U>::value) ? details::cmp_equal_same_sign(t, u) : (std::is_signed<T>::value) ? details::cmp_equal_signed_unsigned(t, u) : details::cmp_equal_signed_unsigned(u,t); } // equivalent of operator< for different integral types /// Usage: /// size_t i = ... /// DWORD j = ... /// if(cmp_less(i,j)){ /// // i < j /// } else { /// // i >= j /// } template <typename T, typename U> constexpr bool cmp_less(const T t, const U u) noexcept { return (std::is_signed<T>::value == std::is_signed<U>::value) ? details::cmp_less_same_sign(t,u) : (std::is_signed<T>::value) ? details::cmp_less_signed_unsigned(t, u) : details::cmp_less_unsigned_signed(t, u); } </pre></blockquote> </p> <a name="Effects"></a><h2>VI. Effects on Existing Code</h2> <p>Since the proposed functions are not defined in any standard header, no currently existing code behavior will be changed.</p> <a name="Design"></a><h2>VII. Design Decisions</h2> <p> Since there is no reason to compare <code>true</code> and <code>false</code> with other integral types, there isn't one to provide an overload for the <code>bool</code> integral type either.</br> The name of the functions (<code>cmp_equal</code>, <code>cmp_less</code> and others) are open to discussion, but the function names <code>std::less</code> and <code>std::greater</code> should not be used, since these do already exist, and have a different meaning.</p> </body> </html> ------=_Part_2355_81630189.1498582855788-- .

Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>

Date: Wed, 28 Jun 2017 22:35:09 +0200

This is a multi-part message in MIME format. --------------49D1469227ABCCDB0820DEBF Content-Type: text/plain; charset="UTF-8"; format=flowed Content-Transfer-Encoding: quoted-printable Le 06/02/2017 =C3=A0 18:23, federico.kircheis@gmail.com a =C3=A9crit : > Hi Vicente, > > thank you for your feedback. > > I was not aware of narrow/narrow cast. > If they do provide the same functionality and it's going to be in the=20 > next std release, then I could drop the proposal for "in_range". There is not a current proposal, but I would like it on the standard. > > One possible issue is that you may not know, between two types, which=20 > is the bigger one (for example inside a templated function). So a=20 > function like "can_be_narrowed" does not seem right because you are=20 > not going to narrow, whereas "in_range" does not have that issue ->=20 > seems more generic to me. > I don't see the difference. You can use narrow when the type is a subset=20 of the other. The implementation could be specialized to just return=20 true in this case? > I cannot find any reference to the operator <=3D>=20 > (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0100r2.html),= =20 > do you have a link? Sorry it was=20 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0515r0.pdf > > I would gladly drop the function "precision", but if you are comparing=20 > an unsigned type with a signed type, and both variables contains a=20 > positive value(!), how do you know if you need to cast them both to=20 > signed or to unsigned? If you do the comparison with=20 > std::numeric_limits without casting, an implicit conversion could give=20 > you an unexpected result (thats the whole point of this proposal). My concern was to define a trait instead of a constexpr function, but=20 maybe we are going to constexpr functions now. Best, Vicente > > If you are comparing an uint_8t with an int_32t, you should cast to=20 > int_32t since it can contain all values of uint_8t, but if you are=20 > comparing and uint_16t with an int_16 you should cast to uint_16t,=20 > since it can contain all positive values of int_16t. > So it depends on how big the "range" of the types are, i.e. how=20 > precise they are. > Normally I would use the sizeof operator to determine which of both=20 > types is more precise, but as stated in securecoding, padding bits may=20 > be an issue. So why not provide this function to the end user as a=20 > bonus? Of course this function is not strictly necessary (it's an=20 > implementation detail), and can be removed from the proposal too, even=20 > if it seems to me a nice addition. > > > --=20 > You received this message because you are subscribed to the Google=20 > Groups "ISO C++ Standard - Future Proposals" group. > To unsubscribe from this group and stop receiving emails from it, send=20 > an email to std-proposals+unsubscribe@isocpp.org=20 > <mailto:std-proposals+unsubscribe@isocpp.org>. > To post to this group, send email to std-proposals@isocpp.org=20 > <mailto:std-proposals@isocpp.org>. > To view this discussion on the web visit=20 > https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/6a3e0be1-3a7= a-4cfd-a4a9-d49cd72bb52b%40isocpp.org=20 > <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/6a3e0be1-3a= 7a-4cfd-a4a9-d49cd72bb52b%40isocpp.org?utm_medium=3Demail&utm_source=3Dfoot= er>. --=20 You received this message because you are subscribed to the Google Groups "= ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an e= mail to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp= ..org/d/msgid/std-proposals/4fcbc46d-7754-1061-4c67-22ef74756fd2%40wanadoo.f= r. --------------49D1469227ABCCDB0820DEBF Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <html> <head> <meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf-8= "> </head> <body text=3D"#000000" bgcolor=3D"#FFFFFF"> <div class=3D"moz-cite-prefix">Le 06/02/2017 =C3=A0 18:23, <a class=3D"moz-txt-link-abbreviated" href=3D"mailto:federico.kirchei= s@gmail.com">federico.kircheis@gmail.com</a> a =C3=A9crit=C2=A0:<br> </div> <blockquote type=3D"cite" cite=3D"mid:6a3e0be1-3a7a-4cfd-a4a9-d49cd72bb52b@isocpp.org"> <div dir=3D"ltr">Hi Vicente,<br> <br> thank you for your feedback.<br> <br> I was not aware of narrow/narrow cast.<br> If they do provide the same functionality and it's going to be in the next std release, then I could drop the proposal for "in_range".<br> </div> </blockquote> There is not a current proposal, but I would like it on the standard.<br> <blockquote type=3D"cite" cite=3D"mid:6a3e0be1-3a7a-4cfd-a4a9-d49cd72bb52b@isocpp.org"> <div dir=3D"ltr"><br> One possible issue is that you may not know, between two types, which is the bigger one (for example inside a templated function). So a function like "can_be_narrowed" does not seem right because you are not going to narrow, whereas "in_range" does not have that issue -> seems more generic to me.<br> <br> </div> </blockquote> I don't see the difference. You can use narrow when the type is a subset of the other. The implementation could be specialized to just return true in this case?<br> <blockquote type=3D"cite" cite=3D"mid:6a3e0be1-3a7a-4cfd-a4a9-d49cd72bb52b@isocpp.org"> <div dir=3D"ltr">I cannot find any reference to the operator <=3D> (<a class=3D"moz-txt-link-freetext" href=3D"http://www.open-std.org= /jtc1/sc22/wg21/docs/papers/2016/p0100r2.html">http://www.open-std.org/jtc1= /sc22/wg21/docs/papers/2016/p0100r2.html</a>), do you have a link?<br> </div> </blockquote> Sorry it was <a class=3D"moz-txt-link-freetext" href=3D"http://www.open-std.org/jtc1= /sc22/wg21/docs/papers/2017/p0515r0.pdf">http://www.open-std.org/jtc1/sc22/= wg21/docs/papers/2017/p0515r0.pdf</a><br> <br> <blockquote type=3D"cite" cite=3D"mid:6a3e0be1-3a7a-4cfd-a4a9-d49cd72bb52b@isocpp.org"> <div dir=3D"ltr"><br> I would gladly drop the function "precision", but if you are comparing an unsigned type with a signed type, and both variables contains a positive value(!), how do you know if you need to cast them both to signed or to unsigned? If you do the comparison with std::numeric_limits without casting, an implicit conversion could give you an unexpected result (thats the whole point of this proposal).<br> </div> </blockquote> My concern was to define a trait instead of a constexpr function, but maybe we are going to constexpr functions now.<br> <br> Best,<br> Vicente<br> <blockquote type=3D"cite" cite=3D"mid:6a3e0be1-3a7a-4cfd-a4a9-d49cd72bb52b@isocpp.org"> <div dir=3D"ltr"><br> If you are comparing an uint_8t with an int_32t, you should cast to int_32t since it can contain all values of uint_8t, but if you are comparing and uint_16t with an int_16 you should cast to uint_16t, since it can contain all positive values of int_16t.<br> So it depends on how big the "range" of the types are, i.e. how precise they are.<br> Normally I would use the sizeof operator to determine which of both types is more precise, but as stated in securecoding, padding bits may be an issue. So why not provide this function to the end user as a bonus? Of course this function is not strictly necessary (it's an implementation detail), and can be removed from the proposal too, even if it seems to me a nice addition.<br> <br> <br> </div> -- <br> You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br> To unsubscribe from this group and stop receiving emails from it, send an email to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org" moz-do-not-send=3D"true">std-proposals+unsubscribe@isocpp.org</a>.<= br> To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp.org" moz-do-not-send=3D"true">s= td-proposals@isocpp.org</a>.<br> To view this discussion on the web visit <a href=3D"https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/6a3e0b= e1-3a7a-4cfd-a4a9-d49cd72bb52b%40isocpp.org?utm_medium=3Demail&utm_sour= ce=3Dfooter" moz-do-not-send=3D"true">https://groups.google.com/a/isocpp.org/d/m= sgid/std-proposals/6a3e0be1-3a7a-4cfd-a4a9-d49cd72bb52b%40isocpp.org</a>.<b= r> </blockquote> <p><br> </p> </body> </html> <p></p> -- <br /> You received this message because you are subscribed to the Google Groups &= quot;ISO C++ Standard - Future Proposals" group.<br /> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa= ls+unsubscribe@isocpp.org</a>.<br /> To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp= ..org">std-proposals@isocpp.org</a>.<br /> To view this discussion on the web visit <a href=3D"https://groups.google.c= om/a/isocpp.org/d/msgid/std-proposals/4fcbc46d-7754-1061-4c67-22ef74756fd2%= 40wanadoo.fr?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.= com/a/isocpp.org/d/msgid/std-proposals/4fcbc46d-7754-1061-4c67-22ef74756fd2= %40wanadoo.fr</a>.<br /> --------------49D1469227ABCCDB0820DEBF-- .

Author: Robert Ramey <ramey@rrsd.com>

Date: Wed, 28 Jun 2017 14:47:17 -0700

The following is what I use #ifndef BOOST_NUMERIC_SAFE_COMPARE_HPP #define BOOST_NUMERIC_SAFE_COMPARE_HPP // MS compatible compilers support #pragma once #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif // Copyright (c) 2012 Robert Ramey // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include <type_traits> #include <limits> #include <boost/mpl/if.hpp> #include <boost/mpl/identity.hpp> #include "safe_common.hpp" namespace boost { namespace numeric { namespace safe_compare { //////////////////////////////////////////////////// // safe comparison on primitive types namespace safe_compare_detail { template<typename T> using make_unsigned = typename boost::mpl::if_c< //std::numeric_limits<T>::is_signed, std::is_signed<T>::value, std::make_unsigned<T>, boost::mpl::identity<T> >::type; // both arguments unsigned or signed template<bool TS, bool US> struct less_than { template<class T, class U> constexpr static bool invoke(const T & t, const U & u){ return t < u; } }; // T unsigned, U signed template<> struct less_than<false, true> { template<class T, class U> constexpr static bool invoke(const T & t, const U & u){ return (u < 0) ? false : less_than<false, false>::invoke( t, static_cast<const typename make_unsigned<U>::type &>(u) ) ; } }; // T signed, U unsigned template<> struct less_than<true, false> { template<class T, class U> constexpr static bool invoke(const T & t, const U & u){ return (t < 0) ? true : less_than<false, false>::invoke( static_cast<const typename make_unsigned<T>::type &>(t), u ) ; } }; } // safe_compare_detail template<class T, class U> constexpr bool less_than(const T & lhs, const U & rhs) { return safe_compare_detail::less_than< std::is_signed<T>::value, std::is_signed<U>::value >::template invoke(lhs, rhs); } template<class T, class U> constexpr bool greater_than(const T & lhs, const U & rhs) { return less_than(rhs, lhs); } template<class T, class U> constexpr bool less_than_equal(const T & lhs, const U & rhs) { return ! greater_than(lhs, rhs); } template<class T, class U> constexpr bool greater_than_equal(const T & lhs, const U & rhs) { return ! less_than(lhs, rhs); } namespace safe_compare_detail { // both arguments unsigned or signed template<bool TS, bool US> struct equal { template<class T, class U> constexpr static bool invoke(const T & t, const U & u){ return t == u; } }; // T unsigned, U signed template<> struct equal<false, true> { template<class T, class U> constexpr static bool invoke(const T & t, const U & u){ return (u < 0) ? false : equal<false, false>::invoke( t, static_cast<const typename make_unsigned<U>::type &>(u) ) ; } }; // T signed, U unsigned template<> struct equal<true, false> { template<class T, class U> constexpr static bool invoke(const T & t, const U & u){ return (t < 0) ? false : equal<false, false>::invoke( static_cast<const typename make_unsigned<T>::type &>(t), u ) ; } }; } // safe_compare_detail template<class T, class U> constexpr bool equal(const T & lhs, const U & rhs) { return safe_compare_detail::equal< std::numeric_limits<T>::is_signed, std::numeric_limits<U>::is_signed >::template invoke(lhs, rhs); } template<class T, class U> constexpr bool not_equal(const T & lhs, const U & rhs) { return ! safe_compare_detail::equal< std::numeric_limits<T>::is_signed, std::numeric_limits<U>::is_signed >::template invoke(lhs, rhs); } } // safe_compare } // numeric } // boost #endif // BOOST_NUMERIC_SAFE_COMPARE_HPP -- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/4473c388-1bc0-24b3-b1f2-fc8bfc834df3%40rrsd.com. .

Author: federico.kircheis@gmail.com

Date: Wed, 28 Jun 2017 22:10:13 -0700 (PDT)

------=_Part_3259_1335460591.1498713013342 Content-Type: multipart/alternative; boundary="----=_Part_3260_1643007177.1498713013342" ------=_Part_3260_1643007177.1498713013342 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi, One possible issue is that you may not know, between two types, which is=20 > the bigger one (for example inside a templated function). So a function= =20 > like "can_be_narrowed" does not seem right because you are not going to= =20 > narrow, whereas "in_range" does not have that issue -> seems more generic= =20 > to me. > > I don't see the difference. You can use narrow when the type is a subset= =20 > of the other. The implementation could be specialized to just return true= =20 > in this case? > It's more a naming issue, but nothing. With narrowing you expect to get s= =20 smaller type, that's all. I wan't to stress that narrow_cast alone is not enough, we should have,=20 like you have called it, a can_be_narrowed. IMHO narrow_cast should throw. I'm not against throwing, but it makes=20 little sense if you already know how to handle that error, for example=20 splitting you operation in multiple steps. If you have for example a hash routine, with an update function, which=20 length parameter is an int and not a size_t(happened to me moer than once),= =20 you can write your wrapper that takes the size_t, and if the value is=20 bigger than numeri_limits<int>__max() split the operation in multiple=20 updates. If you are casting immediately, you have to write less clear code IMHO.=20 Therefore we should really have a function for checking the relative=20 position of different integers.? > I cannot find any reference to the operator <=3D> ( > http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0100r2.html), do= =20 > you have a link? > > Sorry it was=20 > http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0515r0.pdf > > Looks very interesting, I have mixed feelings about another operator for= =20 comparing value, but that behaves differently (even if in a more sensible= =20 way) with native types. Is there some active discussion about it? If we would have such an=20 operator, most of the functions I'm proposing will be unnecessary. I'ill=20 add a reference, thank you. > I would gladly drop the function "precision", but if you are comparing an= =20 > unsigned type with a signed type, and both variables contains a positive= =20 > value(!), how do you know if you need to cast them both to signed or to= =20 > unsigned? If you do the comparison with std::numeric_limits without=20 > casting, an implicit conversion could give you an unexpected result (that= s=20 > the whole point of this proposal). > > My concern was to define a trait instead of a constexpr function, but=20 > maybe we are going to constexpr functions now. > I've implemented it as a constexpr function, since I find it a lot easier= =20 to reason about it and use it (like I said, I'm not a template master), of= =20 course it can also be implemented as a trait, maybe I should mention it.=20 =20 Il giorno mercoled=C3=AC 28 giugno 2017 22:35:13 UTC+2, Vicente J. Botet Es= criba=20 ha scritto: > > Le 06/02/2017 =C3=A0 18:23, federico...@gmail.com <javascript:void(0)> a= =20 > =C3=A9crit : > > Hi Vicente, > > thank you for your feedback. > > I was not aware of narrow/narrow cast. > If they do provide the same functionality and it's going to be in the nex= t=20 > std release, then I could drop the proposal for "in_range". > > There is not a current proposal, but I would like it on the standard. > > > One possible issue is that you may not know, between two types, which is= =20 > the bigger one (for example inside a templated function). So a function= =20 > like "can_be_narrowed" does not seem right because you are not going to= =20 > narrow, whereas "in_range" does not have that issue -> seems more generic= =20 > to me. > > I don't see the difference. You can use narrow when the type is a subset= =20 > of the other. The implementation could be specialized to just return true= =20 > in this case? > > I cannot find any reference to the operator <=3D> ( > http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0100r2.html), do= =20 > you have a link? > > Sorry it was=20 > http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0515r0.pdf > > > I would gladly drop the function "precision", but if you are comparing an= =20 > unsigned type with a signed type, and both variables contains a positive= =20 > value(!), how do you know if you need to cast them both to signed or to= =20 > unsigned? If you do the comparison with std::numeric_limits without=20 > casting, an implicit conversion could give you an unexpected result (that= s=20 > the whole point of this proposal). > > My concern was to define a trait instead of a constexpr function, but=20 > maybe we are going to constexpr functions now. > > Best, > Vicente > > > If you are comparing an uint_8t with an int_32t, you should cast to=20 > int_32t since it can contain all values of uint_8t, but if you are=20 > comparing and uint_16t with an int_16 you should cast to uint_16t, since = it=20 > can contain all positive values of int_16t. > So it depends on how big the "range" of the types are, i.e. how precise= =20 > they are. > Normally I would use the sizeof operator to determine which of both types= =20 > is more precise, but as stated in securecoding, padding bits may be an=20 > issue. So why not provide this function to the end user as a bonus? Of=20 > course this function is not strictly necessary (it's an implementation=20 > detail), and can be removed from the proposal too, even if it seems to me= a=20 > nice addition. > > > --=20 > You received this message because you are subscribed to the Google Groups= =20 > "ISO C++ Standard - Future Proposals" group. > To unsubscribe from this group and stop receiving emails from it, send an= =20 > email to std-proposal...@isocpp.org <javascript:void(0)>. > To post to this group, send email to std-pr...@isocpp.org=20 > <javascript:void(0)>. > To view this discussion on the web visit=20 > https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/6a3e0be1-3a7= a-4cfd-a4a9-d49cd72bb52b%40isocpp.org=20 > <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/6a3e0be1-3a= 7a-4cfd-a4a9-d49cd72bb52b%40isocpp.org?utm_medium=3Demail&utm_source=3Dfoot= er> > . > > > --=20 You received this message because you are subscribed to the Google Groups "= ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an e= mail to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp= ..org/d/msgid/std-proposals/47af44a1-4895-44da-b9af-090c75b53c37%40isocpp.or= g. ------=_Part_3260_1643007177.1498713013342 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">Hi,<br><br><blockquote class=3D"gmail_quote" style=3D"marg= in: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><d= iv bgcolor=3D"#FFFFFF"><blockquote type=3D"cite"><div dir=3D"ltr"> One possible issue is that you may not know, between two types, which is the bigger one (for example inside a templated function). So a function like "can_be_narrowed" does not = seem right because you are not going to narrow, whereas "in_range&q= uot; does not have that issue -> seems more generic to me.<br> <br> </div> </blockquote> I don't see the difference. You can use narrow when the type is a subset of the other. The implementation could be specialized to just return true in this case?<br></div></blockquote><div><br>It's more = a naming issue, but nothing. With narrowing you expect to get s smaller typ= e, that's all.<br>I wan't to stress that narrow_cast alone is not e= nough, we should have, like you have called it, a can_be_narrowed.<br>IMHO = narrow_cast should throw. I'm not against throwing, but it makes little= sense if you already know how to handle that error, for example splitting = you operation in multiple steps.<br><br>If you have for example a hash rout= ine, with an update function, which length parameter is an int and not a si= ze_t(happened to me moer than once), you can write your wrapper that takes = the size_t, and if the value is bigger than numeri_limits<int>__max()= split the operation in multiple updates.<br>If you are casting immediately= , you have to write less clear code IMHO. Therefore we should really have a= function for checking the relative position of different integers.?<br> <blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex= ;border-left: 1px #ccc solid;padding-left: 1ex;"><div bgcolor=3D"#FFFFFF"><= blockquote type=3D"cite"> <div dir=3D"ltr">I cannot find any reference to the operator <=3D> (<a href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016= /p0100r2.html" target=3D"_blank" rel=3D"nofollow">http://www.open-std.org/j= tc1/<wbr>sc22/wg21/docs/papers/2016/<wbr>p0100r2.html</a>), do you have a link?<br> </div> </blockquote> Sorry it was <a href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p051= 5r0.pdf" target=3D"_blank" rel=3D"nofollow">http://www.open-std.org/jtc1/<w= br>sc22/wg21/docs/papers/2017/<wbr>p0515r0.pdf</a><br> <br></div></blockquote><div>Looks very interesting, I have mixed feelin= gs about another operator for comparing value, but that behaves differently= (even if in a more sensible way) with native types.<br>Is there some activ= e discussion about it? If we would have such an operator, most of the funct= ions I'm proposing will be unnecessary. I'ill add a reference, than= k you.<br><br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: = 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div b= gcolor=3D"#FFFFFF"> <blockquote type=3D"cite"> <div dir=3D"ltr"><br> I would gladly drop the function "precision", but if you = are comparing an unsigned type with a signed type, and both variables contains a positive value(!), how do you know if you need to cast them both to signed or to unsigned? If you do the comparison with std::numeric_limits without casting, an implicit conversion could give you an unexpected result (thats the whole point of this proposal).<br> </div> </blockquote> My concern was to define a trait instead of a constexpr function, but maybe we are going to constexpr functions now.<br></div></blockquot= e><div><br>I've implemented it as a constexpr function, since I find it= a lot easier to reason about it and use it (like I said, I'm not a tem= plate master), of course it can also be implemented as a trait, maybe I sho= uld mention it. <br></div>=C2=A0</div>Il giorno mercoled=C3=AC 28 giugno 20= 17 22:35:13 UTC+2, Vicente J. Botet Escriba ha scritto:<blockquote class=3D= "gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc s= olid;padding-left: 1ex;"> =20 =20 =20 <div text=3D"#000000" bgcolor=3D"#FFFFFF"> <div>Le 06/02/2017 =C3=A0 18:23, <a href=3D"javascript:void(0)" target=3D"_blank" gdf-obfuscated-mailt= o=3D"sAlZdx1NAAAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascr= ipt:';return true;" onclick=3D"this.href=3D'javascript:';return= true;">federico...@gmail.com</a> a =C3=A9crit=C2=A0:<br> </div> <blockquote type=3D"cite"> <div dir=3D"ltr">Hi Vicente,<br> <br> thank you for your feedback.<br> <br> I was not aware of narrow/narrow cast.<br> If they do provide the same functionality and it's going to be in the next std release, then I could drop the proposal for "in_range".<br> </div> </blockquote> There is not a current proposal, but I would like it on the standard.<br> <blockquote type=3D"cite"> <div dir=3D"ltr"><br> One possible issue is that you may not know, between two types, which is the bigger one (for example inside a templated function). So a function like "can_be_narrowed" does not = seem right because you are not going to narrow, whereas "in_range&q= uot; does not have that issue -> seems more generic to me.<br> <br> </div> </blockquote> I don't see the difference. You can use narrow when the type is a subset of the other. The implementation could be specialized to just return true in this case?<br> <blockquote type=3D"cite"> <div dir=3D"ltr">I cannot find any reference to the operator <=3D> (<a href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016= /p0100r2.html" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href= =3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fwww.open-std.org%2Fjtc1= %2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2016%2Fp0100r2.html\x26sa\x3dD\x26sntz\x3d= 1\x26usg\x3dAFQjCNGJMEXwPcHJobcg5jbfuQ-pRwOE8A';return true;" onclick= =3D"this.href=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fwww.open-s= td.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2016%2Fp0100r2.html\x26sa\x3d= D\x26sntz\x3d1\x26usg\x3dAFQjCNGJMEXwPcHJobcg5jbfuQ-pRwOE8A';return tru= e;">http://www.open-std.org/jtc1/<wbr>sc22/wg21/docs/papers/2016/<wbr>p0100= r2.html</a>), do you have a link?<br> </div> </blockquote> Sorry it was <a href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p051= 5r0.pdf" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'= ;http://www.google.com/url?q\x3dhttp%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22= %2Fwg21%2Fdocs%2Fpapers%2F2017%2Fp0515r0.pdf\x26sa\x3dD\x26sntz\x3d1\x26usg= \x3dAFQjCNFnqU4U3X-EXMwB_lo5oZrgVV0o7g';return true;" onclick=3D"this.h= ref=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fwww.open-std.org%2Fj= tc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2017%2Fp0515r0.pdf\x26sa\x3dD\x26sntz\x= 3d1\x26usg\x3dAFQjCNFnqU4U3X-EXMwB_lo5oZrgVV0o7g';return true;">http://= www.open-std.org/jtc1/<wbr>sc22/wg21/docs/papers/2017/<wbr>p0515r0.pdf</a><= br> <br> <blockquote type=3D"cite"> <div dir=3D"ltr"><br> I would gladly drop the function "precision", but if you = are comparing an unsigned type with a signed type, and both variables contains a positive value(!), how do you know if you need to cast them both to signed or to unsigned? If you do the comparison with std::numeric_limits without casting, an implicit conversion could give you an unexpected result (thats the whole point of this proposal).<br> </div> </blockquote> My concern was to define a trait instead of a constexpr function, but maybe we are going to constexpr functions now.<br> <br> Best,<br> Vicente<br> <blockquote type=3D"cite"> <div dir=3D"ltr"><br> If you are comparing an uint_8t with an int_32t, you should cast to int_32t since it can contain all values of uint_8t, but if you are comparing and uint_16t with an int_16 you should cast to uint_16t, since it can contain all positive values of int_16t.<br> So it depends on how big the "range" of the types are, i.= e. how precise they are.<br> Normally I would use the sizeof operator to determine which of both types is more precise, but as stated in securecoding, padding bits may be an issue. So why not provide this function to the end user as a bonus? Of course this function is not strictly necessary (it's an implementation detail), and can be removed from the proposal too, even if it seems to me a nice addition.<br> <br> <br> </div> -- <br> You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br> To unsubscribe from this group and stop receiving emails from it, send an email to <a href=3D"javascript:void(0)" target=3D"_blank" gdf= -obfuscated-mailto=3D"sAlZdx1NAAAJ" rel=3D"nofollow" onmousedown=3D"this.hr= ef=3D'javascript:';return true;" onclick=3D"this.href=3D'javasc= ript:';return true;">std-proposal...@<wbr>isocpp.org</a>.<br> To post to this group, send email to <a href=3D"javascript:void(0)" t= arget=3D"_blank" gdf-obfuscated-mailto=3D"sAlZdx1NAAAJ" rel=3D"nofollow" on= mousedown=3D"this.href=3D'javascript:';return true;" onclick=3D"thi= s.href=3D'javascript:';return true;">std-pr...@isocpp.org</a>.<br> To view this discussion on the web visit <a href=3D"https://groups.go= ogle.com/a/isocpp.org/d/msgid/std-proposals/6a3e0be1-3a7a-4cfd-a4a9-d49cd72= bb52b%40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter" target=3D"_b= lank" rel=3D"nofollow" onmousedown=3D"this.href=3D'https://groups.googl= e.com/a/isocpp.org/d/msgid/std-proposals/6a3e0be1-3a7a-4cfd-a4a9-d49cd72bb5= 2b%40isocpp.org?utm_medium\x3demail\x26utm_source\x3dfooter';return tru= e;" onclick=3D"this.href=3D'https://groups.google.com/a/isocpp.org/d/ms= gid/std-proposals/6a3e0be1-3a7a-4cfd-a4a9-d49cd72bb52b%40isocpp.org?utm_med= ium\x3demail\x26utm_source\x3dfooter';return true;">https://groups.goog= le.com/a/<wbr>isocpp.org/d/msgid/std-<wbr>proposals/6a3e0be1-3a7a-4cfd-<wbr= >a4a9-d49cd72bb52b%40isocpp.org</a><wbr>.<br> </blockquote> <p><br> </p> </div> </blockquote></div> <p></p> -- <br /> You received this message because you are subscribed to the Google Groups &= quot;ISO C++ Standard - Future Proposals" group.<br /> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa= ls+unsubscribe@isocpp.org</a>.<br /> To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp= ..org">std-proposals@isocpp.org</a>.<br /> To view this discussion on the web visit <a href=3D"https://groups.google.c= om/a/isocpp.org/d/msgid/std-proposals/47af44a1-4895-44da-b9af-090c75b53c37%= 40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.= com/a/isocpp.org/d/msgid/std-proposals/47af44a1-4895-44da-b9af-090c75b53c37= %40isocpp.org</a>.<br /> ------=_Part_3260_1643007177.1498713013342-- ------=_Part_3259_1335460591.1498713013342-- .

Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>

Date: Thu, 29 Jun 2017 08:10:34 +0200

This is a multi-part message in MIME format. --------------14AAA5EF9C674F191D92619C Content-Type: text/plain; charset="UTF-8"; format=flowed Content-Transfer-Encoding: quoted-printable Le 29/06/2017 =C3=A0 07:10, federico.kircheis@gmail.com a =C3=A9crit : > Hi, > >> One possible issue is that you may not know, between two types, >> which is the bigger one (for example inside a templated >> function). So a function like "can_be_narrowed" does not seem >> right because you are not going to narrow, whereas "in_range" >> does not have that issue -> seems more generic to me. >> > I don't see the difference. You can use narrow when the type is a > subset of the other. The implementation could be specialized to > just return true in this case? > > > It's more a naming issue, but nothing. With narrowing you expect to=20 > get s smaller type, that's all. Okay. Let name it narrow_if_needed if you prefer. > I wan't to stress that narrow_cast alone is not enough, we should=20 > have, like you have called it, a can_be_narrowed. Agreed. > IMHO narrow_cast should throw. I'm not against throwing, but it makes=20 > little sense if you already know how to handle that error, for example=20 > splitting you operation in multiple steps. I believe it is interesting to signal that we are narrowing even if we=20 know that in this context we don't loss information. The goal of=20 narrow_cast is just this. > > If you have for example a hash routine, with an update function, which=20 > length parameter is an int and not a size_t(happened to me moer than=20 > once), you can write your wrapper that takes the size_t, and if the=20 > value is bigger than numeri_limits<int>__max() split the operation in=20 > multiple updates. > If you are casting immediately, you have to write less clear code=20 > IMHO. Therefore we should really have a function for checking the=20 > relative position of different integers.? I'm a little bit lost. Could you elaborate? > >> I cannot find any reference to the operator <=3D> >> (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0100r2.htm= l >> <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0100r2.htm= l>), >> do you have a link? > Sorry it was > http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0515r0.pdf > <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0515r0.pdf> > > Looks very interesting, I have mixed feelings about another operator=20 > for comparing value, but that behaves differently (even if in a more=20 > sensible way) with native types. > Is there some active discussion about it? If we would have such an=20 > operator, most of the functions I'm proposing will be unnecessary.=20 > I'ill add a reference, thank you. > I don't know of any active discussion. Maybe you can start it. > >> >> I would gladly drop the function "precision", but if you are >> comparing an unsigned type with a signed type, and both variables >> contains a positive value(!), how do you know if you need to cast >> them both to signed or to unsigned? If you do the comparison with >> std::numeric_limits without casting, an implicit conversion could >> give you an unexpected result (thats the whole point of this >> proposal). > My concern was to define a trait instead of a constexpr function, > but maybe we are going to constexpr functions now. > > > I've implemented it as a constexpr function, since I find it a lot=20 > easier to reason about it and use it (like I said, I'm not a template=20 > master), of course it can also be implemented as a trait, maybe I=20 > should mention it. Don't worry. It is clear this way. Vicente --=20 You received this message because you are subscribed to the Google Groups "= ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an e= mail to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp= ..org/d/msgid/std-proposals/bcb5def9-0239-d0a4-faac-4921b404b1f6%40wanadoo.f= r. --------------14AAA5EF9C674F191D92619C Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <html> <head> <meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf-8= "> </head> <body text=3D"#000000" bgcolor=3D"#FFFFFF"> <div class=3D"moz-cite-prefix">Le 29/06/2017 =C3=A0 07:10, <a class=3D"moz-txt-link-abbreviated" href=3D"mailto:federico.kirchei= s@gmail.com">federico.kircheis@gmail.com</a> a =C3=A9crit=C2=A0:<br> </div> <blockquote type=3D"cite" cite=3D"mid:47af44a1-4895-44da-b9af-090c75b53c37@isocpp.org"> <div dir=3D"ltr">Hi,<br> <br> <blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"> <div bgcolor=3D"#FFFFFF"> <blockquote type=3D"cite"> <div dir=3D"ltr"> One possible issue is that you may not know, between two types, which is the bigger one (for example inside a templated function). So a function like "can_be_narrowed" does not seem right because you are not going to narrow, whereas "in_range" does not have that issue -> seems more generic to me.<br> <br> </div> </blockquote> I don't see the difference. You can use narrow when the type is a subset of the other. The implementation could be specialized to just return true in this case?<br> </div> </blockquote> <div><br> It's more a naming issue, but nothing. With narrowing you expect to get s smaller type, that's all.<br> </div> </div> </blockquote> Okay. Let name it narrow_if_needed if you prefer.<br> <blockquote type=3D"cite" cite=3D"mid:47af44a1-4895-44da-b9af-090c75b53c37@isocpp.org"> <div dir=3D"ltr"> <div>I wan't to stress that narrow_cast alone is not enough, we should have, like you have called it, a can_be_narrowed.<br> </div> </div> </blockquote> Agreed.<br> <blockquote type=3D"cite" cite=3D"mid:47af44a1-4895-44da-b9af-090c75b53c37@isocpp.org"> <div dir=3D"ltr"> <div>IMHO narrow_cast should throw. I'm not against throwing, but it makes little sense if you already know how to handle that error, for example splitting you operation in multiple steps.<br> </div> </div> </blockquote> I believe it is interesting to signal that we are narrowing even if we know that in this context we don't loss information. The goal of narrow_cast is just this.<br> <blockquote type=3D"cite" cite=3D"mid:47af44a1-4895-44da-b9af-090c75b53c37@isocpp.org"> <div dir=3D"ltr"> <div><br> If you have for example a hash routine, with an update function, which length parameter is an int and not a size_t(happened to me moer than once), you can write your wrapper that takes the size_t, and if the value is bigger than numeri_limits<int>__max() split the operation in multiple updates.<br> If you are casting immediately, you have to write less clear code IMHO. Therefore we should really have a function for checking the relative position of different integers.?<br> </div> </div> </blockquote> I'm a little bit lost. Could you elaborate?<br> <blockquote type=3D"cite" cite=3D"mid:47af44a1-4895-44da-b9af-090c75b53c37@isocpp.org"> <div dir=3D"ltr"> <div> <blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"> <div bgcolor=3D"#FFFFFF"> <blockquote type=3D"cite"> <div dir=3D"ltr">I cannot find any reference to the operator <=3D> (<a href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0100r2.htm= l" target=3D"_blank" rel=3D"nofollow" moz-do-not-send=3D"true">http://www.open-std.org/jtc1/<= wbr>sc22/wg21/docs/papers/2016/<wbr>p0100r2.html</a>), do you have a link?<br> </div> </blockquote> Sorry it was <a href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0515r0.pdf= " target=3D"_blank" rel=3D"nofollow" moz-do-not-send=3D"true"= >http://www.open-std.org/jtc1/<wbr>sc22/wg21/docs/papers/2017/<wbr>p0515r0.= pdf</a><br> <br> </div> </blockquote> <div>Looks very interesting, I have mixed feelings about another operator for comparing value, but that behaves differently (even if in a more sensible way) with native types.<br> Is there some active discussion about it? If we would have such an operator, most of the functions I'm proposing will be unnecessary. I'ill add a reference, thank you.<br> <br> </div> </div> </div> </blockquote> I don't know of any active discussion. Maybe you can start it.<br> <blockquote type=3D"cite" cite=3D"mid:47af44a1-4895-44da-b9af-090c75b53c37@isocpp.org"> <div dir=3D"ltr"> <div> <div><br> </div> <blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"> <div bgcolor=3D"#FFFFFF"> <blockquote type=3D"cite"> <div dir=3D"ltr"><br> I would gladly drop the function "precision", but if you are comparing an unsigned type with a signed type, and both variables contains a positive value(!), how do you know if you need to cast them both to signed or to unsigned? If you do the comparison with std::numeric_limits without casting, an implicit conversion could give you an unexpected result (thats the whole point of this proposal).<br> </div> </blockquote> My concern was to define a trait instead of a constexpr function, but maybe we are going to constexpr functions now.<br> </div> </blockquote> <div><br> I've implemented it as a constexpr function, since I find it a lot easier to reason about it and use it (like I said, I'm not a template master), of course it can also be implemented as a trait, maybe I should mention it. <br> </div> </div> </div> </blockquote> Don't worry. It is clear this way.<br> <br> Vicente </body> </html> <p></p> -- <br /> You received this message because you are subscribed to the Google Groups &= quot;ISO C++ Standard - Future Proposals" group.<br /> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa= ls+unsubscribe@isocpp.org</a>.<br /> To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp= ..org">std-proposals@isocpp.org</a>.<br /> To view this discussion on the web visit <a href=3D"https://groups.google.c= om/a/isocpp.org/d/msgid/std-proposals/bcb5def9-0239-d0a4-faac-4921b404b1f6%= 40wanadoo.fr?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.= com/a/isocpp.org/d/msgid/std-proposals/bcb5def9-0239-d0a4-faac-4921b404b1f6= %40wanadoo.fr</a>.<br /> --------------14AAA5EF9C674F191D92619C-- .

Author: federico.kircheis@gmail.com

Date: Thu, 29 Jun 2017 09:41:27 -0700 (PDT)

------=_Part_3576_234751402.1498754487857 Content-Type: multipart/alternative; boundary="----=_Part_3577_1888084006.1498754487857" ------=_Part_3577_1888084006.1498754487857 Content-Type: text/plain; charset="UTF-8" > If you have for example a hash routine, with an update function, which > length parameter is an int and not a size_t(happened to me moer than once), > you can write your wrapper that takes the size_t, and if the value is > bigger than numeri_limits<int>__max() split the operation in multiple > updates. > If you are casting immediately, you have to write less clear code IMHO. > Therefore we should really have a function for checking the relative > position of different integers.? > > I'm a little bit lost. Could you elaborate? > > It was just an example that came to my mind where you do not want a narrow_cast but a less_cmp operation, suppose you have the function signature: void update(hash_type t, unsigned char* tohash, int len) but most of the time you have the length expressed in terms of size_t. You might therefore write something like void my_update(hash_type t, unsigned char* tohash, std::size_t len){ auto intmax = std::numeric_limits<int>::max(); while(cmp_less(intmax, len)){ update(t, tohash, intmax) len -= intmax; tohash +=intmax } update(t, tohash, len) } whereas narrow_casting directly "size_t len" to "int len", would just hide the problem since in this case, you know how to deal with the overflow (which may not be true in most cases). -- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/7d74dcfa-358f-4fb9-8cc7-ffa854563952%40isocpp.org. ------=_Part_3577_1888084006.1498754487857 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr"><br><blockquote class=3D"gmail_quote" style=3D"margin: 0;m= argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div text= =3D"#000000" bgcolor=3D"#FFFFFF"><blockquote type=3D"cite"><div dir=3D"ltr"= ><div> If you have for example a hash routine, with an update function, which length parameter is an int and not a size_t(happened to me moer than once), you can write your wrapper that takes the size_t, and if the value is bigger than numeri_limits<int>__max() split the operation in multiple updates.<br> If you are casting immediately, you have to write less clear code IMHO. Therefore we should really have a function for checking the relative position of different integers.?<br> </div> </div> </blockquote> I'm a little bit lost. Could you elaborate?<br><br></div></blockquo= te><div>It was just an example that came to my mind where you do not want a= narrow_cast but a less_cmp operation, suppose you have the function signat= ure:<br><br>void update(hash_type t, unsigned char* tohash, int len)<br><br= >but most of the time you have the length expressed in terms of size_t. You= might therefore write something like<br>=C2=A0<br>void my_update(hash_type= t, unsigned char* tohash, std::size_t len){<br>=C2=A0=C2=A0 auto intmax = =3D std::numeric_limits<int>::max();<br>=C2=A0=C2=A0 while(cmp_less(i= ntmax, len)){<br>=C2=A0=C2=A0=C2=A0=C2=A0 update(t, tohash, intmax)<br>=C2= =A0=C2=A0=C2=A0=C2=A0 len -=3D intmax;<br>=C2=A0=C2=A0=C2=A0=C2=A0 tohash += =3Dintmax<br>=C2=A0=C2=A0 }<br>=C2=A0=C2=A0 update(t, tohash, len)<br>}<br= ><br>whereas narrow_casting directly "size_t len" to "int le= n", would just hide the problem since in this case, you know how to de= al with the overflow (which may not be true in most cases).<br></div></div> <p></p> -- <br /> You received this message because you are subscribed to the Google Groups &= quot;ISO C++ Standard - Future Proposals" group.<br /> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa= ls+unsubscribe@isocpp.org</a>.<br /> To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp= ..org">std-proposals@isocpp.org</a>.<br /> To view this discussion on the web visit <a href=3D"https://groups.google.c= om/a/isocpp.org/d/msgid/std-proposals/7d74dcfa-358f-4fb9-8cc7-ffa854563952%= 40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.= com/a/isocpp.org/d/msgid/std-proposals/7d74dcfa-358f-4fb9-8cc7-ffa854563952= %40isocpp.org</a>.<br /> ------=_Part_3577_1888084006.1498754487857-- ------=_Part_3576_234751402.1498754487857-- .

Author: federico.kircheis@gmail.com

Date: Thu, 29 Jun 2017 10:00:00 -0700 (PDT)

------=_Part_3560_1354070715.1498755600740 Content-Type: multipart/alternative; boundary="----=_Part_3561_366027867.1498755600740" ------=_Part_3561_366027867.1498755600740 Content-Type: text/plain; charset="UTF-8" Hi, I was just reading your implementation a couple of days ago, it's pretty complicated with all those templated types ;-) (To be honest I found out of your library in March, when I listened to the podcast episode, but then forgot to give a look to your implementation) I noticed you were not comparing the precision of the types like I did, I guess I missed that I could use "make_unsigned". I think the only difference is that I'm converting both types to the one with the biggest range, and accounting that it may be the signed one. I guess it may use less stack space, but I also think that it will never make some difference. I guess your implementation for comparing integral types and mine are completely interchangeable. Maybe I should also add to my proposal the implementation of cmp_greater and the others comparator, even if given cmp_less they all trivial. And surely a link to your repository as possible alternative implementation without using a "precision" function. -- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/23282d1f-aaaa-45a1-a1fe-2056addfe835%40isocpp.org. ------=_Part_3561_366027867.1498755600740 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">Hi, <br><br>I was just reading your implementation a coupl= e of days ago, it's pretty complicated with all those templated types ;= -)<br><br>(To be honest I found out of your library in March, when I listen= ed to the podcast episode, but then forgot to give a look to your implement= ation)<br><br>I noticed you were not comparing the precision of the types l= ike I did, I guess I missed that I could use "make_unsigned". <br= >I think the only difference is that I'm converting both types to the o= ne with the biggest range, and accounting that it may be the signed one. I = guess it may use less stack space, but I also think that it will never make= some difference.<br><br><div>I guess your implementation for comparing int= egral types and mine are completely interchangeable. <br><br>Maybe I should= also add to my proposal the implementation of cmp_greater and the others c= omparator, even if given cmp_less they all trivial.<br>And surely a link to= your repository as possible alternative implementation without using a &qu= ot;precision" function.<br><br><br></div></div> <p></p> -- <br /> You received this message because you are subscribed to the Google Groups &= quot;ISO C++ Standard - Future Proposals" group.<br /> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa= ls+unsubscribe@isocpp.org</a>.<br /> To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp= ..org">std-proposals@isocpp.org</a>.<br /> To view this discussion on the web visit <a href=3D"https://groups.google.c= om/a/isocpp.org/d/msgid/std-proposals/23282d1f-aaaa-45a1-a1fe-2056addfe835%= 40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.= com/a/isocpp.org/d/msgid/std-proposals/23282d1f-aaaa-45a1-a1fe-2056addfe835= %40isocpp.org</a>.<br /> ------=_Part_3561_366027867.1498755600740-- ------=_Part_3560_1354070715.1498755600740-- .

Author: Robert Ramey <ramey@rrsd.com>

Date: Thu, 29 Jun 2017 12:10:53 -0700

On 6/29/17 10:00 AM, federico.kircheis@gmail.com wrote: > Hi, > > I was just reading your implementation a couple of days ago, it's pretty > complicated with all those templated types ;-) > > (To be honest I found out of your library in March, when I listened to > the podcast episode, but then forgot to give a look to your implementation) > > I noticed you were not comparing the precision of the types like I did, > I guess I missed that I could use "make_unsigned". > I think the only difference is that I'm converting both types to the one > with the biggest range, and accounting that it may be the signed one. I > guess it may use less stack space, but I also think that it will never > make some difference. > > I guess your implementation for comparing integral types and mine are > completely interchangeable. > This is unnecessary. C/C++ type promotion rules do exactly this so it's redundant to do this in your code. The only problem is that C++ promotion rules sometime change signed to unsigned and change the value. The attached code keeps this from happening which is why it works. Note that my code guarantees zero runtime overhead in space or time. In fact it could even make one's program faster as in the case: unsigned int x; signed int y = -1 y < x // can be eliminated as it will always be true. Robert Ramey -- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/8c168cd3-6dc2-97ab-848d-7eab8321e114%40rrsd.com. .

Author: federico.kircheis@gmail.com

Date: Thu, 29 Jun 2017 12:27:57 -0700 (PDT)

------=_Part_3894_881021322.1498764478021 Content-Type: multipart/alternative; boundary="----=_Part_3895_319721557.1498764478021" ------=_Part_3895_319721557.1498764478021 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable You are right about the promotion rules, problems arise only when mixing=20 signed and unsigned types. I think I made all the casts explicit, also in order to avoid possible=20 compiler warning, even if there shouldn't be any. Most of the time I enable all possible warnings, and MSVC in particular=20 generates a lot of them. There may be also something about safe promotions,= =20 but I should check it to be sure. I also think that I tried to use only the types that where passed as=20 parameter (and maybe thats the reason why I didn't want to use=20 make_unsigned, but it's an implementation detail), in order to deal cases where a compiler provides some integral=20 type but only the signed or unsigned variant and not boht of them. I have actually no idea if something like this exists somewhere, or if it= =20 does even make sense, but AFAIK there is no rule that states that for every= =20 signed type we need an unsigned, and for every unsigned a signed. Il giorno gioved=C3=AC 29 giugno 2017 21:10:59 UTC+2, Robert Ramey ha scrit= to: > > On 6/29/17 10:00 AM, federico...@gmail.com <javascript:> wrote:=20 > > Hi,=20 > >=20 > > I was just reading your implementation a couple of days ago, it's prett= y=20 > > complicated with all those templated types ;-)=20 > >=20 > > (To be honest I found out of your library in March, when I listened to= =20 > > the podcast episode, but then forgot to give a look to your=20 > implementation)=20 > >=20 > > I noticed you were not comparing the precision of the types like I did,= =20 > > I guess I missed that I could use "make_unsigned".=20 > > I think the only difference is that I'm converting both types to the on= e=20 > > with the biggest range, and accounting that it may be the signed one. I= =20 > > guess it may use less stack space, but I also think that it will never= =20 > > make some difference.=20 > >=20 > > I guess your implementation for comparing integral types and mine are= =20 > > completely interchangeable.=20 > >=20 > > This is unnecessary. C/C++ type promotion rules do exactly this so it's= =20 > redundant to do this in your code. The only problem is that C++=20 > promotion rules sometime change signed to=20 > unsigned and change the value.=20 > The attached code keeps this from happening which is why it works.=20 > > Note that my code guarantees zero runtime overhead in space or time. In= =20 > fact it could even make one's program faster as in the case:=20 > > unsigned int x;=20 > signed int y =3D -1=20 > > y < x // can be eliminated as it will always be true.=20 > > Robert Ramey=20 > --=20 You received this message because you are subscribed to the Google Groups "= ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an e= mail to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp= ..org/d/msgid/std-proposals/c0774539-8c72-4467-ba0c-a04042a7cc94%40isocpp.or= g. ------=_Part_3895_319721557.1498764478021 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">You are right about the promotion rules, problems arise on= ly when mixing signed and unsigned types.<br><br>I think I made all the cas= ts explicit, also in order to avoid possible compiler warning, even if ther= e shouldn't be any.<br>Most of the time I enable all possible warnings,= and MSVC in particular generates a lot of them. There may be also somethin= g about safe promotions, but I should check it to be sure.<br><br><br>I als= o think that I tried to use only the types that where passed as parameter (= and maybe thats the reason why I didn't want to use make_unsigned, but = it's an implementation<br>detail), in order to deal cases where a compi= ler provides some integral type but only the signed or unsigned variant and= not boht of them.<br>I have actually no idea if something like this exists= somewhere, or if it does even make sense, but AFAIK there is no rule that = states that for every signed type we need an<br>unsigned, and for every uns= igned a signed.<br><br><br>Il giorno gioved=C3=AC 29 giugno 2017 21:10:59 U= TC+2, Robert Ramey ha scritto:<blockquote class=3D"gmail_quote" style=3D"ma= rgin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">= On 6/29/17 10:00 AM, <a href=3D"javascript:" target=3D"_blank" gdf-obfuscat= ed-mailto=3D"Scw9RhmXAAAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'= ;javascript:';return true;" onclick=3D"this.href=3D'javascript:'= ;;return true;">federico...@gmail.com</a> wrote: <br>> Hi, <br>>=20 <br>> I was just reading your implementation a couple of days ago, it= 9;s pretty=20 <br>> complicated with all those templated types ;-) <br>>=20 <br>> (To be honest I found out of your library in March, when I listene= d to=20 <br>> the podcast episode, but then forgot to give a look to your implem= entation) <br>>=20 <br>> I noticed you were not comparing the precision of the types like I= did,=20 <br>> I guess I missed that I could use "make_unsigned". <br>> I think the only difference is that I'm converting both types = to the one=20 <br>> with the biggest range, and accounting that it may be the signed o= ne. I=20 <br>> guess it may use less stack space, but I also think that it will n= ever=20 <br>> make some difference. <br>>=20 <br>> I guess your implementation for comparing integral types and mine = are=20 <br>> completely interchangeable. <br>>=20 <br> <br>This is unnecessary. =C2=A0C/C++ type promotion rules do exactly this s= o it's=20 <br>redundant to do this in your code. =C2=A0The only problem is that C++= =20 <br>promotion rules sometime change signed to <br>unsigned and change the value. <br>The attached code keeps this from happening which is why it works. <br> <br>Note that my code guarantees zero runtime overhead in space or time. In= =20 <br>fact it could even make one's program faster as in the case: <br> <br>unsigned int x; <br>signed int y =3D -1 <br> <br>y < x // can be eliminated as it will always be true. <br> <br>Robert Ramey <br></blockquote></div> <p></p> -- <br /> You received this message because you are subscribed to the Google Groups &= quot;ISO C++ Standard - Future Proposals" group.<br /> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa= ls+unsubscribe@isocpp.org</a>.<br /> To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp= ..org">std-proposals@isocpp.org</a>.<br /> To view this discussion on the web visit <a href=3D"https://groups.google.c= om/a/isocpp.org/d/msgid/std-proposals/c0774539-8c72-4467-ba0c-a04042a7cc94%= 40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.= com/a/isocpp.org/d/msgid/std-proposals/c0774539-8c72-4467-ba0c-a04042a7cc94= %40isocpp.org</a>.<br /> ------=_Part_3895_319721557.1498764478021-- ------=_Part_3894_881021322.1498764478021-- .

Author: federico.kircheis@gmail.com

Date: Fri, 14 Jul 2017 21:14:09 -0700 (PDT)

------=_Part_1694_2092871861.1500092049207 Content-Type: multipart/alternative; boundary="----=_Part_1695_50826025.1500092049207" ------=_Part_1695_50826025.1500092049207 Content-Type: text/plain; charset="UTF-8" Hi Robert, I gave a look to your proposal. Are the comparison functions part of it or just an implementation detail? I may have missed it. If they are just an implementation detail, would you consider to make them part of the proposal? If yes, then it does not make any sense for my proposal to exist since it would be part contained of yous. On Wednesday, June 28, 2017 at 11:47:28 PM UTC+2, Robert Ramey wrote: > > The following is what I use > > ... > -- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/b54fed46-33ea-4d62-ab6a-163aec2b7bd3%40isocpp.org. ------=_Part_1695_50826025.1500092049207 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr"><br>Hi Robert,<br><br>I gave a look to your proposal.=C2= =A0 Are the comparison functions part of it or just an implementation detai= l?<br><br>I may have missed it.<br><br>If they are just an implementation d= etail, would you consider to make them part of the proposal?<br>If yes, the= n it does not make any sense for my proposal to exist since it would be par= t contained of yous.<br><br><br><br>On Wednesday, June 28, 2017 at 11:47:28= PM UTC+2, Robert Ramey wrote:<blockquote class=3D"gmail_quote" style=3D"ma= rgin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">= The following is what I use <br> <br> ....<br></blockquote></div> <p></p> -- <br /> You received this message because you are subscribed to the Google Groups &= quot;ISO C++ Standard - Future Proposals" group.<br /> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa= ls+unsubscribe@isocpp.org</a>.<br /> To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp= ..org">std-proposals@isocpp.org</a>.<br /> To view this discussion on the web visit <a href=3D"https://groups.google.c= om/a/isocpp.org/d/msgid/std-proposals/b54fed46-33ea-4d62-ab6a-163aec2b7bd3%= 40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.= com/a/isocpp.org/d/msgid/std-proposals/b54fed46-33ea-4d62-ab6a-163aec2b7bd3= %40isocpp.org</a>.<br /> ------=_Part_1695_50826025.1500092049207-- ------=_Part_1694_2092871861.1500092049207-- .

Author: federico.kircheis@gmail.com

Date: Sun, 16 Jul 2017 01:00:17 -0700 (PDT)

------=_Part_538_349762377.1500192018086 Content-Type: multipart/alternative; boundary="----=_Part_539_1765635022.1500192018087" ------=_Part_539_1765635022.1500192018087 Content-Type: text/plain; charset="UTF-8" Another update to the proposal, I've added the references to Robert Ramey's proposal (and a link to an alternative implementation of the comparison functions in his github repository) and Herb Sutter's proposal for operator<=>. -- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/4a572c09-5142-4834-a907-93c3cc87e79c%40isocpp.org. ------=_Part_539_1765635022.1500192018087 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">Another update to the proposal,<br><br>I've added the = references to Robert Ramey's proposal (and a link to an alternative imp= lementation of the comparison functions in his github repository) and Herb = Sutter's proposal for operator<=3D>.<br></div> <p></p> -- <br /> You received this message because you are subscribed to the Google Groups &= quot;ISO C++ Standard - Future Proposals" group.<br /> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa= ls+unsubscribe@isocpp.org</a>.<br /> To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp= ..org">std-proposals@isocpp.org</a>.<br /> To view this discussion on the web visit <a href=3D"https://groups.google.c= om/a/isocpp.org/d/msgid/std-proposals/4a572c09-5142-4834-a907-93c3cc87e79c%= 40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.= com/a/isocpp.org/d/msgid/std-proposals/4a572c09-5142-4834-a907-93c3cc87e79c= %40isocpp.org</a>.<br /> ------=_Part_539_1765635022.1500192018087-- ------=_Part_538_349762377.1500192018086 Content-Type: text/html; charset=US-ASCII; name=proposal.html Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=proposal.html X-Attachment-Id: 1746a96f-c239-4a45-b6af-058adc3784f5 Content-ID: <1746a96f-c239-4a45-b6af-058adc3784f5> <!DOCTYPE html> <html lang="en"> <head> <title>Safe integral comparisons</title> </head> <body> <address> Document number: P0586R0<br/> Date: 2017-02-04<br/> Project: Programming Language C++<br/> Reply-to: <a href="mailto:federico.kircheis@gmail.com">Federico Kircheis</a><br/> </address> <h1>Safe integral comparisons</h1> <h2 id="Table">I. Table of Contents</h2> <ul style="font-family:monospace"> <li><a href="#Table" >I).......Table of Contents</a></li> <li><a href="#Motivation" >II)......Motivation</a></li> <li><a href="#Proposal" >III).....Proposal</a></li> <li><a href="#Examples" >IV)......Examples</a></li> <li><a href="#Example" >V)......Example implementation</a></li> <li><a href="#Effects" >VI)......Effects on Existing Code</a></li> <li><a href="#Design" >VII).....Design Decisions</a></li> <li><a href="#Related" >VIII)....Related Works</a></li> </ul> <h2 id="Motivation">II. Motivation</h2> <p> Comparing integrals of different types may be a more complex task than expected. Most of the time we expect that a simple </p> <pre><code> if(a < b){ // ... } else { // ... } </code></pre> <p> should work in all cases, but if <code>a</code> and <code>b</code> are of different types, things are more complicated.<br/> If <code>a</code> is a signed type, and <code>b</code> unsigned, then <code>a</code> is converted to the unsigned type. If <code>a</code> held a number less than zero, then the result may be unexpected, since the expression <code>a < b</code> could evaluate to false, even if a strictly negative number is always lower than a positive one. </p> <p> Also converting integrals between different types can be challenging, for simplicity, most of the time we assume that values are in range, and write </p> <pre><code> a = static_cast<decltype(a)>(b);</code></pre> <p> If we want to write a safe conversion, we need to check if <code>b</code> has a value between <code>std::numeric_limits<decltype(a)>::min()</code> and <code>std::numeric_limits<decltype(a)>::max()</code>. We also need to pay attention that no implicit conversion (for example between unsigned and signed types) invalidates our comparison. </p> <p> Comparing and converting numbers, even of different numeric types, should be a trivial task. Unfortunately it is not, and because of implicit conversions we may write, without noticing it, unsafe code. </p> <h2 id="Proposal">III. Proposal</h2> <p> This paper proposes to add a set of <code>constexpr</code> and <code>noexcept</code> functions for converting and comparing integrals of different signeddes and precision (except for <code>bool</code>): </p> <ul> <li> Two functions to compare if two variables represent the same value or not <pre><code> template <typename T, typename U> constexpr bool std::cmp_equal(T t, U u) noexcept; template <typename T, typename U> constexpr bool std::cmp_unequal(T t, U u) noexcept; </code></pre> <li> A set of functions that can be used to determine the relative order of two values <pre><code> template <typename T, typename U> constexpr bool std::cmp_less(T t, U u) noexcept; template <typename T, typename U> constexpr bool std::cmp_greater(T t, U u) noexcept; template <typename T, typename U> constexpr bool std::cmp_less_or_equal(T t, U u) noexcept; template <typename T, typename U> constexpr bool std::cmp_greater_or_equal(T t, U u) noexcept; </code></pre> <li> One function to determine if a specific value is inside the range of possible values of another type (i.e. if we can convert the value to the other type safely) <pre><code> template <typename R, typename T> constexpr bool in_range(T t) noexcept; </code></pre> <li> One function for retrieving the precision of a given numeric type <pre><code> template <typename T> constexpr std::size_t std::precision() noexcept; </code></pre> </ul> <p> The function <code>precision</code> is part of the proposal because we cannot use the operator <code>sizeof</code> to determine between two types which one has a wider range (quote from <a href="https://www.securecoding.cert.org/confluence/display/c/INT35-C.+Use+correct+integer+precisions">SecureCoding</a>):<br/> </p> <q> Integer types in C have both a size and a precision. The size indicates the number of bytes used by an object and can be retrieved for any object or type using the sizeof operator. The precision of an integer type is the number of bits it uses to represent values, excluding any sign and padding bits. Padding bits contribute to the integer's size, but not to its precision. Consequently, inferring the precision of an integer type from its size may result in too large a value, which can then lead to incorrect assumptions about the numeric range of these types. Programmers should use correct integer precisions in their code, and in particular, should not use the sizeof operator to compute the precision of an integer type on architectures that use padding bits or in strictly conforming (that is, portable) programs. </q> <p> The <code>precision</code> function does not have to be part of the proposal, but it seems an useful addition. </p> <h2 id="Examples">IV. Examples</h2> <h3>Examples without current proposal</h3> <p>Comparing an unsigned int with an int:</p> <pre><code> int a = ... unsigned int b = ... // added static_cast to avoid compiler warnings since we are doing a "safe" comparison if(a < 0 || static_cast<unsigned int>(a) < b){ // do X } else { // do Y } </code></pre> <p>Comparing an uint32_t with an int16_t:</p> <pre><code> int32_t a = ... uint16_t b = ... // added static_cast to avoid compiler warnings since we are doing a "safe" comparison if(a < static_cast<int32_t>(b)){ // do X } else { // do Y } </code></pre> <p>Comparing an int with an intptr_t:</p> <pre><code> int a = ... intptr_t b = ... if(???){ // no idea how to do it in one readable line without some assumption about int and intptr_t // do X } else { // do Y } </code></pre> <h3>Example with current proposal</h3> <p> Comparing one integral type <code>A</code> with another integral type <code>B</code> (both non <code>bool</code>): </p> <pre><code> A a = ... B b = ... // no need for any cast since std::cmp_less is taking care of everything if( std::cmp_less(a,b)){ // do X } else { // do Y } </code></pre> <h2 id="Example">V. Example implementation</h2> <p> This section shows an example of how <code>precision</code>, <code>cmp_equal</code>, <code>cmp_less</code> and <code>in_range</code> can be implemented with any standard conforming C++11 compiler. The only dependencies are the <code>std::numeric_limits</code> function from the <code>limits</code> header and some traits from the <code>type_traits</code> header. </p> <pre><code> #include <limits> #include <type_traits> template <typename T> constexpr std::size_t precision() noexcept; namespace details{ #if defined(ERR_MSG_xxx_NEEDS_INTEGRAL_NOT_BOOL) || defined(ASSERT_INTEGRAL_NOT_BOOL_TYPE) #error "ERR_MSG_xxx_NEEDS_INTEGRAL_NOT_BOOL or ASSERT_INTEGRAL_NOT_BOOL_TYPE already defined" #endif #define ERR_MSG_xxx_NEEDS_INTEGRAL_NOT_BOOL " needs to be an integral (not bool) value type" #define ASSERT_INTEGRAL_NOT_BOOL_TYPE(T) static_assert(is_integral_not_bool<T>(), #T ERR_MSG_xxx_NEEDS_INTEGRAL_NOT_BOOL); template <typename T> constexpr bool is_integral_not_bool(){ using value_type = typename std::remove_cv<T>::type; return !std::is_same<value_type,bool>::value && std::is_integral<T>::value; } template <class T> constexpr std::size_t pop(const std::size_t precision, const T num) { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); return (num == T{0}) ? precision : pop(((num % 2 != 0) ? precision+1 : precision), num >> 1); } // could use the same implementation of in_range_signed_signed, but compiler may generate warning that t is always bigger than 0 template <typename R, typename T> constexpr bool in_range_unsigned_unsigned(const T t) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(R); return (precision<T>() > precision<R>()) ? (t < static_cast<T>(std::numeric_limits<R>::max())) : (static_cast<R>(t) <std::numeric_limits<R>::max()); } template <typename R, typename T> constexpr bool in_range_signed_signed(const T t) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(R); return (precision<T>() > precision<R>()) ? (t <= static_cast<T>(std::numeric_limits<R>::max()) && t >= static_cast<T>(std::numeric_limits<R>::min())) : (static_cast<R>(t) <= std::numeric_limits<R>::max() && static_cast<R>(t) >= std::numeric_limits<R>::max()); } template <typename R, typename T> constexpr bool in_range_signed_unsigned(const T t) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(R); return (t < T{ 0 }) ? false : (precision<T>() / 2 <= precision<R>()) ? true : (t <= static_cast<T>(std::numeric_limits<R>::max())); } template <typename R, typename T> constexpr bool in_range_unsigned_signed(const T t) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(R); return (precision<T>() >= precision<R>() / 2) ? (t <= static_cast<T>(std::numeric_limits<R>::max())) : true; } template <typename R, typename T> constexpr bool in_range_unsigned(const T t) noexcept { return std::is_unsigned<R>::value ? in_range_unsigned_unsigned<R>(t) : in_range_unsigned_signed<R>(t); } template <typename R, typename T> constexpr bool in_range_signed(const T t) noexcept { return std::is_signed<R>::value ? in_range_signed_signed<R>(t) : in_range_signed_unsigned<R>(t); } template <typename T, typename U> constexpr bool cmp_equal_same_sign(const T t, const U u) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(U); return (precision<T>()>precision<U>()) ? (t == static_cast<T>(u)) : (static_cast<U>(t) == u); } template <typename T, typename U> constexpr bool cmp_equal_signed_unsigned(const T t, const U u) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(U); return (t<T{ 0 }) ? false : (precision<T>() / 2>precision<U>()) ? (t == static_cast<T>(u)) : (static_cast<U>(t) == u); } template <typename T, typename U> constexpr bool cmp_less_same_sign(const T t, const U u) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(U); return (precision<T>()>precision<U>()) ? (t < static_cast<T>(u)) : (static_cast<U>(t) < u); } template <typename T, typename U> constexpr bool cmp_less_signed_unsigned(const T t, const U u) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(U); return (t<T{ 0 }) ? true : (precision<T>() / 2>precision<U>()) ? (t < static_cast<T>(u)) : (static_cast<U>(t) < u); } template <typename T, typename U> constexpr bool cmp_less_unsigned_signed(const T t, const U u) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(U); return (u<U{ 0 }) ? false : (precision<U>() / 2>precision<T>()) ? (static_cast<U>(t) < u) : (t < static_cast<T>(u)); } #undef ERR_MSG_xxx_NEEDS_INTEGRAL_NOT_BOOL #undef ASSERT_INTEGRAL_NOT_BOOL_TYPE } // end details template <typename T> constexpr std::size_t precision() noexcept { return details::pop(0, std::numeric_limits<T>::max()); } /// Usage: /// size_t i = ... /// if(in_range<DWORD>(i)){ /// // safe to use i as a DWORD value, parameter... /// } else { /// // not possible to rappresent i as a DWORD /// } template <typename R, typename T> constexpr bool in_range(const T t) noexcept { return std::is_unsigned<T>::value ? details::in_range_unsigned<R>(t) : details::in_range_signed<R>(t); } // equivalent of operator== for different types /// Usage: /// size_t i = ... /// DWORD j = ... /// if(cmp_equal(i,j)){ /// // i and j rappresent the same quantity /// } else { /// // i and j rappresents different quantities /// } template <typename T, typename U> constexpr bool cmp_equal(const T t, const U u) noexcept { return (std::is_signed<T>::value == std::is_signed<U>::value) ? details::cmp_equal_same_sign(t, u) : (std::is_signed<T>::value) ? details::cmp_equal_signed_unsigned(t, u) : details::cmp_equal_signed_unsigned(u,t); } // equivalent of operator< for different integral types /// Usage: /// size_t i = ... /// DWORD j = ... /// if(cmp_less(i,j)){ /// // i < j /// } else { /// // i >= j /// } template <typename T, typename U> constexpr bool cmp_less(const T t, const U u) noexcept { return (std::is_signed<T>::value == std::is_signed<U>::value) ? details::cmp_less_same_sign(t,u) : (std::is_signed<T>::value) ? details::cmp_less_signed_unsigned(t, u) : details::cmp_less_unsigned_signed(t, u); } </code></pre> <h2 id="Effects">VI. Effects on Existing Code</h2> <p> Since the proposed functions are not defined in any standard header, no currently existing code behavior will be changed. </p> <h2 id="Design">VII. Design Decisions</h2> <p> Since there is no reason to compare <code>true</code> and <code>false</code> with other integral types, there isn't one to provide an overload for the <code>bool</code> integral type either.<br/> The name of the functions (<code>cmp_equal</code>, <code>cmp_less</code> and others) are open to discussion, but the function names <code>std::less</code> and <code>std::greater</code> should not be used, since these do already exist, and have a different meaning. </p> <h2 id="Related">VIII. Related Works</h2> <p> In 2016, Robert Ramey did a much bigger proposal (see <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0228r0.pdf">p0228r0</a>) regaridng safe integer types. He also used similar functions proposed in this paper for implementing his classes and operators, therefore an alternative implementation can be found on his <a href="https://github.com/robertramey/safe_numerics/blob/master/include/safe_compare.hpp">github repository</a>. This proposal addresses a smaller problem, namely comparing integral values, and is therefore much smaller.<br/> The functions provided can be also used for creating safe integer types. </p> <p> Another work, by Herb Sutter (see <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0515r0.pdf">p0515r0</a>), is about a new comparison operator (<code><=></code>). As far as I've understood the proposal the <code>operator<=></code> should compare correctly different integral types, making part of this proposal obsolete if the operator is added to the language. While it would be a nice thing to have, having a new comparison operator that operates differently from the old operators may be counterintuitive and cause confusion, even if the new behaviour is more correct. </p> </body> </html> ------=_Part_538_349762377.1500192018086-- .

Author: John McFarlane <mcfarlane.john@gmail.com>

Date: Sun, 16 Jul 2017 11:56:43 -0700 (PDT)

------=_Part_731_864007483.1500231403769 Content-Type: multipart/alternative; boundary="----=_Part_732_2087271091.1500231403770" ------=_Part_732_2087271091.1500231403770 Content-Type: text/plain; charset="UTF-8" On Sunday, July 16, 2017 at 1:00:18 AM UTC-7, federico...@gmail.com wrote: > > Another update to the proposal, > > I've added the references to Robert Ramey's proposal (and a link to an > alternative implementation of the comparison functions in his github > repository) and Herb Sutter's proposal for operator<=>. > Hi Federico, I took a quick look at this revision and had a few comments. If this document has changed by more than a few minor fix-ups, you should probably give it a different paper number to avoid confusion. It is no longer revision #0. I /think/ the correct approach is to call it D0586R1 until you've finished revising it and then submit it as P0586R1. (But I'm usually wrong!) As this mostly seems to be about avoiding cases where overflow would occur, it might be worth also mentioning P0105 and discussing how it relates, e.g. what is the mapping between functions in P0586 and P0105. A possible addition alongside `in_range` might be an `is_losslessly_convertible` which performs a compile-time check to determine if an error is ever possible, e.g. <unsigned,int8>==false, <int8,unsigned>==false, <signed,uint8>==true. This should determine whether there is a run-time cost. Re. precision, I believe numeric_limits::digits and numeric_limits::is_signed give you everything you might need there. Proposals which are proven to be implementable are a good thing. But you might want to link to a reference implementation -- rather than include the entire example implementation. These functions should be generic: they should either work with floating-point types or there should be consideration of making this possible in the future. Further, it should be possible for users to add their own versions of these functions for types which they wish to be used in place of integers when writing generic code. Thanks, John -- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/0537f2f2-645d-4a75-826b-c7f8fba9291e%40isocpp.org. ------=_Part_732_2087271091.1500231403770 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">On Sunday, July 16, 2017 at 1:00:18 AM UTC-7, federico...@= gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin= -left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"lt= r">Another update to the proposal,<br><br>I've added the references to = Robert Ramey's proposal (and a link to an alternative implementation of= the comparison functions in his github repository) and Herb Sutter's p= roposal for operator<=3D>.<br></div></blockquote><div><br>Hi Federico= ,<br><br>I took a quick look at this revision and had a few comments.<br><b= r>If this document has changed by more than a few minor fix-ups, you should= probably give it a different paper number to avoid confusion. It is no lon= ger revision #0.=C2=A0 I /think/ the correct approach is to call it D0586R1= until you've finished revising it and then submit it as P0586R1.=C2=A0= (But I'm usually wrong!)<br><br>As this mostly seems to be about avoid= ing cases where overflow would occur, it might be worth also mentioning P01= 05 and discussing how it relates, e.g. what is the mapping between function= s in P0586 and P0105. <br><br>A possible addition alongside `in_range` migh= t be an `is_losslessly_convertible` which performs a compile-time check to = determine if an error is ever possible, e.g. <unsigned,int8>=3D=3Dfal= se, <int8,unsigned>=3D=3Dfalse, <signed,uint8>=3D=3Dtrue.=C2=A0= This should determine whether there is a run-time cost.<br><br>Re. precisi= on, I believe numeric_limits::digits and numeric_limits::is_signed give you= everything you might need there.<br><br>Proposals which are proven to be i= mplementable are a good thing.=C2=A0 But you might want to link to a refere= nce implementation -- rather than include the entire example implementation= ..<br><br>These functions should be generic: they should either work with fl= oating-point types or there should be consideration of making this possible= in the future.=C2=A0 Further, it should be possible for users to add their= own versions of these functions for types which they wish to be used in pl= ace of integers when writing generic code.<br><br>Thanks,<br>John<br></div>= </div> <p></p> -- <br /> You received this message because you are subscribed to the Google Groups &= quot;ISO C++ Standard - Future Proposals" group.<br /> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa= ls+unsubscribe@isocpp.org</a>.<br /> To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp= ..org">std-proposals@isocpp.org</a>.<br /> To view this discussion on the web visit <a href=3D"https://groups.google.c= om/a/isocpp.org/d/msgid/std-proposals/0537f2f2-645d-4a75-826b-c7f8fba9291e%= 40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.= com/a/isocpp.org/d/msgid/std-proposals/0537f2f2-645d-4a75-826b-c7f8fba9291e= %40isocpp.org</a>.<br /> ------=_Part_732_2087271091.1500231403770-- ------=_Part_731_864007483.1500231403769-- .

Author: federico.kircheis@gmail.com

Date: Sun, 16 Jul 2017 12:34:14 -0700 (PDT)

------=_Part_909_1473260855.1500233654919 Content-Type: multipart/alternative; boundary="----=_Part_910_659620989.1500233654919" ------=_Part_910_659620989.1500233654919 Content-Type: text/plain; charset="UTF-8" Hi John, thank you for your feedback and your time. I think the changes were just minor fixups (add references, make some sentences more clear), but to be honest I didn't give the version number a thought. I'll probably increase it. I'm unaware of P0105, I've only found this discussion: https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/TDSkjdJS1M0 I did not know std::numeric_limits<T>::digits, from the description it seems to offer the same functionality of my precision function. I'll run a couple of tests and update my proposal if this is true. Thank you very much. I might add a reference to a separate header file with the complete implementation, I thought it would have been nice to have it directly in the paper. I do not think that those function should work with floating point types, since the arithmetic is completely different because of rounding, infinity values, and nan. The arithmetic of integral types, if no overflow occurs, is error-free, and the comparison operators behave well to each other, for example 'a<b' is equivalent to '!(b<=a)' for every a and b, unfortunately for floats this is not true. I would therefor prefer not to supply overloaded functions for floating types, but only for integral types, this way we can eventually add them afterward. I also think that situations where you need to compare different float types are not so common as with integral types. And since all float types are signed, there are usually no unsafe conversions. I didn't think about user-provided types. Since users can't add types that will pass the "std::is_integral" test, everyone if free to add his own overload in the global or in a separate namespace without risking to pick the wrong function. I think you can provide overloads in the std::namespace, but I do not know exactly on which situations. But I'm unsure if it would be really useful. In my mind, there are two situations where you may want to provide your function 1) A custom comparison operator takes the user provided class as a parameter and a integral. 2) The class is implicitly convertible to some integral type. Maybe it would make sense if you do not want to make the conversion explicit, I need to think about it. On Sunday, July 16, 2017 at 8:56:43 PM UTC+2, John McFarlane wrote: > > On Sunday, July 16, 2017 at 1:00:18 AM UTC-7, federico...@gmail.com wrote: >> >> Another update to the proposal, >> >> I've added the references to Robert Ramey's proposal (and a link to an >> alternative implementation of the comparison functions in his github >> repository) and Herb Sutter's proposal for operator<=>. >> > > Hi Federico, > > I took a quick look at this revision and had a few comments. > > If this document has changed by more than a few minor fix-ups, you should > probably give it a different paper number to avoid confusion. It is no > longer revision #0. I /think/ the correct approach is to call it D0586R1 > until you've finished revising it and then submit it as P0586R1. (But I'm > usually wrong!) > > As this mostly seems to be about avoiding cases where overflow would > occur, it might be worth also mentioning P0105 and discussing how it > relates, e.g. what is the mapping between functions in P0586 and P0105. > > A possible addition alongside `in_range` might be an > `is_losslessly_convertible` which performs a compile-time check to > determine if an error is ever possible, e.g. <unsigned,int8>==false, > <int8,unsigned>==false, <signed,uint8>==true. This should determine > whether there is a run-time cost. > > Re. precision, I believe numeric_limits::digits and > numeric_limits::is_signed give you everything you might need there. > > Proposals which are proven to be implementable are a good thing. But you > might want to link to a reference implementation -- rather than include the > entire example implementation. > > These functions should be generic: they should either work with > floating-point types or there should be consideration of making this > possible in the future. Further, it should be possible for users to add > their own versions of these functions for types which they wish to be used > in place of integers when writing generic code. > > Thanks, > John > -- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/0b338a7a-6d2c-44cb-ac96-6ca8bb8b992c%40isocpp.org. ------=_Part_910_659620989.1500233654919 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">Hi John,<br><br>thank you for your feedback and your time.= <br><br>I think the changes were just minor fixups (add references, make so= me sentences more clear), but to be honest I didn't give the version nu= mber a thought. I'll probably increase it.<br><br>I'm unaware of P0= 105, I've only found this discussion: https://groups.google.com/a/isocp= p.org/forum/#!topic/std-discussion/TDSkjdJS1M0<br><br>I did not know std::n= umeric_limits<T>::digits, from the description it seems to offer the = same functionality of my precision function.<br>I'll run a couple of te= sts and update my proposal if this is true. Thank you very much.<br><br>I m= ight add a reference to a separate header file with the complete implementa= tion, I thought it would have been nice to have it directly in the paper.<b= r><br>I do not think that those function should work with floating point ty= pes, since the arithmetic is completely different because of rounding, infi= nity values, and nan.<br>The arithmetic of integral types, if no overflow o= ccurs, is error-free, and the comparison operators behave well to each othe= r, for example 'a<b' is equivalent to '!(b<=3Da)' for= every a and b, unfortunately for floats this is not true.<br>I would there= for prefer not to supply overloaded functions for floating types, but only = for integral types, this way we can eventually add them afterward.<br>I als= o think that situations where you need to compare different float types are= not so common as with integral types. And since all float types are signed= , there are usually no unsafe conversions.<br><br><br>I didn't think ab= out user-provided types.<br><br>Since users can't add types that will p= ass the "std::is_integral" test, everyone if free to add his own = overload in the global or in a separate namespace without risking to pick t= he wrong function.<br>I think you can provide overloads in the std::namespa= ce, but I do not know exactly on which situations. But I'm unsure if it= would be really useful.<br><br>In my mind, there are two situations where = you may want to provide your function<br><br>1) A custom comparison operato= r takes the user provided class as a parameter and a integral.<br>2) The cl= ass is implicitly convertible to some integral type.<br><br>Maybe it would = make sense if you do not want to make the conversion explicit, I need to th= ink about it.<br><br><br><br>On Sunday, July 16, 2017 at 8:56:43 PM UTC+2, = John McFarlane wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;m= argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir= =3D"ltr">On Sunday, July 16, 2017 at 1:00:18 AM UTC-7, <a>federico...@gmail= ..com</a> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-l= eft:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">Ano= ther update to the proposal,<br><br>I've added the references to Robert= Ramey's proposal (and a link to an alternative implementation of the c= omparison functions in his github repository) and Herb Sutter's proposa= l for operator<=3D>.<br></div></blockquote><div><br>Hi Federico,<br><= br>I took a quick look at this revision and had a few comments.<br><br>If t= his document has changed by more than a few minor fix-ups, you should proba= bly give it a different paper number to avoid confusion. It is no longer re= vision #0.=C2=A0 I /think/ the correct approach is to call it D0586R1 until= you've finished revising it and then submit it as P0586R1.=C2=A0 (But = I'm usually wrong!)<br><br>As this mostly seems to be about avoiding ca= ses where overflow would occur, it might be worth also mentioning P0105 and= discussing how it relates, e.g. what is the mapping between functions in P= 0586 and P0105. <br><br>A possible addition alongside `in_range` might be a= n `is_losslessly_convertible` which performs a compile-time check to determ= ine if an error is ever possible, e.g. <unsigned,int8>=3D=3Dfalse, &l= t;int8,unsigned>=3D=3Dfalse, <signed,uint8>=3D=3Dtrue.=C2=A0 This = should determine whether there is a run-time cost.<br><br>Re. precision, I = believe numeric_limits::digits and numeric_limits::is_signed give you every= thing you might need there.<br><br>Proposals which are proven to be impleme= ntable are a good thing.=C2=A0 But you might want to link to a reference im= plementation -- rather than include the entire example implementation.<br><= br>These functions should be generic: they should either work with floating= -point types or there should be consideration of making this possible in th= e future.=C2=A0 Further, it should be possible for users to add their own v= ersions of these functions for types which they wish to be used in place of= integers when writing generic code.<br><br>Thanks,<br>John<br></div></div>= </blockquote></div> <p></p> -- <br /> You received this message because you are subscribed to the Google Groups &= quot;ISO C++ Standard - Future Proposals" group.<br /> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa= ls+unsubscribe@isocpp.org</a>.<br /> To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp= ..org">std-proposals@isocpp.org</a>.<br /> To view this discussion on the web visit <a href=3D"https://groups.google.c= om/a/isocpp.org/d/msgid/std-proposals/0b338a7a-6d2c-44cb-ac96-6ca8bb8b992c%= 40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.= com/a/isocpp.org/d/msgid/std-proposals/0b338a7a-6d2c-44cb-ac96-6ca8bb8b992c= %40isocpp.org</a>.<br /> ------=_Part_910_659620989.1500233654919-- ------=_Part_909_1473260855.1500233654919-- .

Author: Nicol Bolas <jmckesson@gmail.com>

Date: Sun, 16 Jul 2017 14:47:42 -0700 (PDT)

------=_Part_879_1189021430.1500241662207 Content-Type: multipart/alternative; boundary="----=_Part_880_1271837243.1500241662207" ------=_Part_880_1271837243.1500241662207 Content-Type: text/plain; charset="UTF-8" On Sunday, July 16, 2017 at 2:56:43 PM UTC-4, John McFarlane wrote: > > On Sunday, July 16, 2017 at 1:00:18 AM UTC-7, federico...@gmail.com wrote: >> >> Another update to the proposal, >> >> I've added the references to Robert Ramey's proposal (and a link to an >> alternative implementation of the comparison functions in his github >> repository) and Herb Sutter's proposal for operator<=>. >> > > Hi Federico, > > I took a quick look at this revision and had a few comments. > > If this document has changed by more than a few minor fix-ups, you should > probably give it a different paper number to avoid confusion. It is no > longer revision #0. I /think/ the correct approach is to call it D0586R1 > until you've finished revising it and then submit it as P0586R1. (But I'm > usually wrong!) > I think the R numbers are for published papers. I've yet to see an R1 without a published R0, even though sometimes they're published in the same mailing. -- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/091ab70e-2f91-419d-9a60-345813d59aee%40isocpp.org. ------=_Part_880_1271837243.1500241662207 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr"><br><br>On Sunday, July 16, 2017 at 2:56:43 PM UTC-4, John= McFarlane wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margi= n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l= tr">On Sunday, July 16, 2017 at 1:00:18 AM UTC-7, <a>federico...@gmail.com<= /a> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0= ..8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">Another = update to the proposal,<br><br>I've added the references to Robert Rame= y's proposal (and a link to an alternative implementation of the compar= ison functions in his github repository) and Herb Sutter's proposal for= operator<=3D>.<br></div></blockquote><div><br>Hi Federico,<br><br>I = took a quick look at this revision and had a few comments.<br><br>If this d= ocument has changed by more than a few minor fix-ups, you should probably g= ive it a different paper number to avoid confusion. It is no longer revisio= n #0.=C2=A0 I /think/ the correct approach is to call it D0586R1 until you&= #39;ve finished revising it and then submit it as P0586R1.=C2=A0 (But I'= ;m usually wrong!)<br></div></div></blockquote><div><br>I think the R numbe= rs are for published papers. I've yet to see an R1 without a published = R0, even though sometimes they're published in the same mailing.<br></d= iv></div> <p></p> -- <br /> You received this message because you are subscribed to the Google Groups &= quot;ISO C++ Standard - Future Proposals" group.<br /> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa= ls+unsubscribe@isocpp.org</a>.<br /> To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp= ..org">std-proposals@isocpp.org</a>.<br /> To view this discussion on the web visit <a href=3D"https://groups.google.c= om/a/isocpp.org/d/msgid/std-proposals/091ab70e-2f91-419d-9a60-345813d59aee%= 40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.= com/a/isocpp.org/d/msgid/std-proposals/091ab70e-2f91-419d-9a60-345813d59aee= %40isocpp.org</a>.<br /> ------=_Part_880_1271837243.1500241662207-- ------=_Part_879_1189021430.1500241662207-- .

Author: John McFarlane <mcfarlane.john@gmail.com>

Date: Sun, 16 Jul 2017 19:38:39 -0700 (PDT)

------=_Part_1065_1223749780.1500259119290 Content-Type: multipart/alternative; boundary="----=_Part_1066_51934554.1500259119290" ------=_Part_1066_51934554.1500259119290 Content-Type: text/plain; charset="UTF-8" OK. I assumed P0586R0 was a published paper. It sounds like it should be D0586R0 for the time being then. On Sunday, July 16, 2017 at 2:47:42 PM UTC-7, Nicol Bolas wrote: > > > > On Sunday, July 16, 2017 at 2:56:43 PM UTC-4, John McFarlane wrote: >> >> On Sunday, July 16, 2017 at 1:00:18 AM UTC-7, federico...@gmail.com >> wrote: >>> >>> Another update to the proposal, >>> >>> I've added the references to Robert Ramey's proposal (and a link to an >>> alternative implementation of the comparison functions in his github >>> repository) and Herb Sutter's proposal for operator<=>. >>> >> >> Hi Federico, >> >> I took a quick look at this revision and had a few comments. >> >> If this document has changed by more than a few minor fix-ups, you should >> probably give it a different paper number to avoid confusion. It is no >> longer revision #0. I /think/ the correct approach is to call it D0586R1 >> until you've finished revising it and then submit it as P0586R1. (But I'm >> usually wrong!) >> > > I think the R numbers are for published papers. I've yet to see an R1 > without a published R0, even though sometimes they're published in the same > mailing. > -- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/c126f65a-e607-4fc8-bc4e-f95d541140ca%40isocpp.org. ------=_Part_1066_51934554.1500259119290 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">OK. I assumed P0586R0 was a published paper.=C2=A0 It soun= ds like it should be D0586R0 for the time being then.<br><br>On Sunday, Jul= y 16, 2017 at 2:47:42 PM UTC-7, Nicol Bolas wrote:<blockquote class=3D"gmai= l_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;= padding-left: 1ex;"><div dir=3D"ltr"><br><br>On Sunday, July 16, 2017 at 2:= 56:43 PM UTC-4, John McFarlane wrote:<blockquote class=3D"gmail_quote" styl= e=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex= "><div dir=3D"ltr">On Sunday, July 16, 2017 at 1:00:18 AM UTC-7, <a>federic= o...@gmail.com</a> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:= 0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir= =3D"ltr">Another update to the proposal,<br><br>I've added the referenc= es to Robert Ramey's proposal (and a link to an alternative implementat= ion of the comparison functions in his github repository) and Herb Sutter&#= 39;s proposal for operator<=3D>.<br></div></blockquote><div><br>Hi Fe= derico,<br><br>I took a quick look at this revision and had a few comments.= <br><br>If this document has changed by more than a few minor fix-ups, you = should probably give it a different paper number to avoid confusion. It is = no longer revision #0.=C2=A0 I /think/ the correct approach is to call it D= 0586R1 until you've finished revising it and then submit it as P0586R1.= =C2=A0 (But I'm usually wrong!)<br></div></div></blockquote><div><br>I = think the R numbers are for published papers. I've yet to see an R1 wit= hout a published R0, even though sometimes they're published in the sam= e mailing.<br></div></div></blockquote></div> <p></p> -- <br /> You received this message because you are subscribed to the Google Groups &= quot;ISO C++ Standard - Future Proposals" group.<br /> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa= ls+unsubscribe@isocpp.org</a>.<br /> To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp= ..org">std-proposals@isocpp.org</a>.<br /> To view this discussion on the web visit <a href=3D"https://groups.google.c= om/a/isocpp.org/d/msgid/std-proposals/c126f65a-e607-4fc8-bc4e-f95d541140ca%= 40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.= com/a/isocpp.org/d/msgid/std-proposals/c126f65a-e607-4fc8-bc4e-f95d541140ca= %40isocpp.org</a>.<br /> ------=_Part_1066_51934554.1500259119290-- ------=_Part_1065_1223749780.1500259119290-- .

Author: John McFarlane <mcfarlane.john@gmail.com>

Date: Sun, 16 Jul 2017 21:57:58 -0700 (PDT)

------=_Part_977_1046310725.1500267478166 Content-Type: multipart/alternative; boundary="----=_Part_978_395160080.1500267478167" ------=_Part_978_395160080.1500267478167 Content-Type: text/plain; charset="UTF-8" On Sunday, July 16, 2017 at 12:34:15 PM UTC-7, federico...@gmail.com wrote: > > I think the changes were just minor fixups (add references, make some > sentences more clear), but to be honest I didn't give the version number a > thought. I'll probably increase it. > Until publication, it should use D, not P. Here are some guidelines: https://isocpp.org/std/standing-documents/sd-7-mailing-procedures-and-how-to-write-papers > > I'm unaware of P0105, I've only found this discussion: > https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/TDSkjdJS1M0 > You can use "http://wg21.link" to look up papers, e.g. wg21.link/P0105 A list of published papers can be found here: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/ > > I do not think that those function should work with floating point types, > since the arithmetic is completely different because of rounding, infinity > values, and nan. > The arithmetic of integral types, if no overflow occurs, is error-free, > and the comparison operators behave well to each other, for example 'a<b' > is equivalent to '!(b<=a)' for every a and b, unfortunately for floats this > is not true. > I would therefor prefer not to supply overloaded functions for floating > types, but only for integral types, this way we can eventually add them > afterward. > I also think that situations where you need to compare different float > types are not so common as with integral types. And since all float types > are signed, there are usually no unsafe conversions. > > That all makes sense. At least leaving the door open seems wise. > > I didn't think about user-provided types. > > Since users can't add types that will pass the "std::is_integral" test, > everyone if free to add his own overload in the global or in a separate > namespace without risking to pick the wrong function. > I think you can provide overloads in the std::namespace, but I do not know > exactly on which situations. But I'm unsure if it would be really useful. > > In my mind, there are two situations where you may want to provide your > function > > 1) A custom comparison operator takes the user provided class as a > parameter and a integral. > 2) The class is implicitly convertible to some integral type. > > Maybe it would make sense if you do not want to make the conversion > explicit, I need to think about it. > I'm not sure what the best way is to provide customization points but making user-defined types work with existing APIs seems achievable and of potential benefit. Cheers John -- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/dba2f844-8b2f-45ed-875f-2a85460056e8%40isocpp.org. ------=_Part_978_395160080.1500267478167 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">On Sunday, July 16, 2017 at 12:34:15 PM UTC-7, federico...= @gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margi= n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l= tr">I think the changes were just minor fixups (add references, make some s= entences more clear), but to be honest I didn't give the version number= a thought. I'll probably increase it.<br></div></blockquote><div><br>U= ntil publication, it should use D, not P.=C2=A0 Here are some guidelines: h= ttps://isocpp.org/std/standing-documents/sd-7-mailing-procedures-and-how-to= -write-papers <br></div><blockquote class=3D"gmail_quote" style=3D"margin: = 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div d= ir=3D"ltr"><br>I'm unaware of P0105, I've only found this discussio= n: <a href=3D"https://groups.google.com/a/isocpp.org/forum/#!topic/std-disc= ussion/TDSkjdJS1M0" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.= href=3D'https://groups.google.com/a/isocpp.org/forum/#!topic/std-discus= sion/TDSkjdJS1M0';return true;" onclick=3D"this.href=3D'https://gro= ups.google.com/a/isocpp.org/forum/#!topic/std-discussion/TDSkjdJS1M0';r= eturn true;">https://groups.google.com/a/<wbr>isocpp.org/forum/#!topic/std-= <wbr>discussion/TDSkjdJS1M0</a></div></blockquote><div><br>You can use &quo= t;http://wg21.link" to look up papers, e.g. <a href=3D"http://wg21.lin= k/P0105">wg21.link/P0105</a><br>A list of published papers can be found her= e: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/<br></div><blockquote= class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1= px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><br>I do not think that = those function should work with floating point types, since the arithmetic = is completely different because of rounding, infinity values, and nan.<br>T= he arithmetic of integral types, if no overflow occurs, is error-free, and = the comparison operators behave well to each other, for example 'a<b= ' is equivalent to '!(b<=3Da)' for every a and b, unfortunat= ely for floats this is not true.<br>I would therefor prefer not to supply o= verloaded functions for floating types, but only for integral types, this w= ay we can eventually add them afterward.<br>I also think that situations wh= ere you need to compare different float types are not so common as with int= egral types. And since all float types are signed, there are usually no uns= afe conversions.<br><br></div></blockquote><div class=3D"">That all makes s= ense.=C2=A0 At least leaving the door open seems wise.<br></div><blockquote= class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1= px #ccc solid;padding-left: 1ex;"><div><br>I didn't think about user-pr= ovided types.<br><br>Since users can't add types that will pass the &qu= ot;std::is_integral" test, everyone if free to add his own overload in= the global or in a separate namespace without risking to pick the wrong fu= nction.<br>I think you can provide overloads in the std::namespace, but I d= o not know exactly on which situations. But I'm unsure if it would be r= eally useful.<br><br>In my mind, there are two situations where you may wan= t to provide your function<br><br>1) A custom comparison operator takes the= user provided class as a parameter and a integral.<br>2) The class is impl= icitly convertible to some integral type.<br><br>Maybe it would make sense = if you do not want to make the conversion explicit, I need to think about i= t.<br></div></blockquote><div dir=3D"ltr"><br>I'm not sure what the bes= t way is to provide customization points but making user-defined types work= with existing APIs seems achievable and of potential benefit.<br><br>Cheer= s<br>John<br></div></div> <p></p> -- <br /> You received this message because you are subscribed to the Google Groups &= quot;ISO C++ Standard - Future Proposals" group.<br /> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa= ls+unsubscribe@isocpp.org</a>.<br /> To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp= ..org">std-proposals@isocpp.org</a>.<br /> To view this discussion on the web visit <a href=3D"https://groups.google.c= om/a/isocpp.org/d/msgid/std-proposals/dba2f844-8b2f-45ed-875f-2a85460056e8%= 40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.= com/a/isocpp.org/d/msgid/std-proposals/dba2f844-8b2f-45ed-875f-2a85460056e8= %40isocpp.org</a>.<br /> ------=_Part_978_395160080.1500267478167-- ------=_Part_977_1046310725.1500267478166-- .

Author: federico.kircheis@gmail.com

Date: Sun, 16 Jul 2017 22:44:45 -0700 (PDT)

------=_Part_1014_1682361185.1500270285274 Content-Type: multipart/alternative; boundary="----=_Part_1015_2015077776.1500270285275" ------=_Part_1015_2015077776.1500270285275 Content-Type: text/plain; charset="UTF-8" Sorry, I'm new to this process, I've read the guidelines more than once, and you are completely right. I should have used Rxxx. Somehow I missed that point (and possibly others). I did not know about "http://wg21.link", thank you very much. it seems to me that P0105 <http://wg21.link/P0105> is for floating point types. I do not see any correlation with this work, which handles only integral types. I gave a second thought about custom structures. I fear that last night I was too tired ... If a class/structure is implicit-convertible to an integral, then you can use the provided functions without adding your own. If you provide a comparison operator between a class/structure and a integral, then it is not a comparison between integrals(!). If there are implicit conversions when the comparison operator gets called, the most sensible way to handle it would be to add an overload for this comparison operator. Can you template a comparison operator? I do not think so, but if you can, you could write for your custom class template<class integral> bool operator==(const myclass& c, integral i){ return cmp_equal(c.member, i); } And again there would be no need to write your own cmp_equal function. (same holds for other comparison operators). But as I said before: since those function should not compile for types that are not integrals, you can always add your version in the global namespace. And then, like with std::begin, std::end, std::swap and so on, you can write: using std::xxxxx xxx(a,b) But I do not think there are any use cases for doing so. Federico On Monday, July 17, 2017 at 6:57:58 AM UTC+2, John McFarlane wrote: > > On Sunday, July 16, 2017 at 12:34:15 PM UTC-7, federico...@gmail.com > wrote: >> >> I think the changes were just minor fixups (add references, make some >> sentences more clear), but to be honest I didn't give the version number a >> thought. I'll probably increase it. >> > > Until publication, it should use D, not P. Here are some guidelines: > https://isocpp.org/std/standing-documents/sd-7-mailing-procedures-and-how-to-write-papers > >> >> I'm unaware of P0105, I've only found this discussion: >> https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/TDSkjdJS1M0 >> > > You can use "http://wg21.link" to look up papers, e.g. wg21.link/P0105 > A list of published papers can be found here: > http://www.open-std.org/jtc1/sc22/wg21/docs/papers/ > >> >> I do not think that those function should work with floating point types, >> since the arithmetic is completely different because of rounding, infinity >> values, and nan. >> The arithmetic of integral types, if no overflow occurs, is error-free, >> and the comparison operators behave well to each other, for example 'a<b' >> is equivalent to '!(b<=a)' for every a and b, unfortunately for floats this >> is not true. >> I would therefor prefer not to supply overloaded functions for floating >> types, but only for integral types, this way we can eventually add them >> afterward. >> I also think that situations where you need to compare different float >> types are not so common as with integral types. And since all float types >> are signed, there are usually no unsafe conversions. >> >> That all makes sense. At least leaving the door open seems wise. > >> >> I didn't think about user-provided types. >> >> Since users can't add types that will pass the "std::is_integral" test, >> everyone if free to add his own overload in the global or in a separate >> namespace without risking to pick the wrong function. >> I think you can provide overloads in the std::namespace, but I do not >> know exactly on which situations. But I'm unsure if it would be really >> useful. >> >> In my mind, there are two situations where you may want to provide your >> function >> >> 1) A custom comparison operator takes the user provided class as a >> parameter and a integral. >> 2) The class is implicitly convertible to some integral type. >> >> Maybe it would make sense if you do not want to make the conversion >> explicit, I need to think about it. >> > > I'm not sure what the best way is to provide customization points but > making user-defined types work with existing APIs seems achievable and of > potential benefit. > > Cheers > John > -- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/f48451b9-5933-4868-b7c4-b37518e72681%40isocpp.org. ------=_Part_1015_2015077776.1500270285275 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">Sorry,<br><br>I'm new to this process, I've read t= he guidelines more than once, and you are completely right. I should have u= sed Rxxx. Somehow I missed that point (and possibly others).<br><br>I did n= ot know about "<a href=3D"http://wg21.link" target=3D"_blank" rel=3D"= nofollow">http://wg21.link</a>", thank you very much.<br>it seems to m= e that <a href=3D"http://wg21.link/P0105" target=3D"_blank" rel=3D"nofollow= ">P0105</a> is for floating point types. I do not see any correlation with = this work, which handles only integral types.<br><br><br>I gave a second th= ought about custom structures. I fear that last night I was too tired ...<b= r><br>If a class/structure is implicit-convertible to an integral, then you= can use the provided functions without adding your own.<br><br>If you prov= ide a comparison operator between a class/structure and a integral, then it= is not a comparison between integrals(!).<br>If there are implicit convers= ions when the comparison operator gets called, the most sensible way to han= dle it would be to add an overload for this comparison operator.<br><br>Can= you template a comparison operator? I do not think so, but if you can, you= could write for your custom class<br><br>template<class integral><br= >bool operator=3D=3D(const myclass& c, integral i){<br>=C2=A0 return cm= p_equal(c.member, i);<br>}<br><br>And again there would be no need to write= your own cmp_equal function. (same holds for other comparison operators).<= br><br>But as I said before: since those function should not compile for ty= pes that are not integrals, you can always add your version in the global n= amespace.<br>And then, like with std::begin, std::end, std::swap and so on,= you can write:<br><br>using std::xxxxx<br>xxx(a,b)<br><br>But I do not thi= nk there are any use cases for doing so.<br><br>Federico<br><br>On Monday, = July 17, 2017 at 6:57:58 AM UTC+2, John McFarlane wrote:<blockquote class= =3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc= c solid;padding-left: 1ex;"><div dir=3D"ltr">On Sunday, July 16, 2017 at 12= :34:15 PM UTC-7, <a>federico...@gmail.com</a> wrote:<blockquote class=3D"gm= ail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;p= adding-left:1ex"><div dir=3D"ltr">I think the changes were just minor fixup= s (add references, make some sentences more clear), but to be honest I didn= 't give the version number a thought. I'll probably increase it.<br= ></div></blockquote><div><br>Until publication, it should use D, not P.=C2= =A0 Here are some guidelines: <a href=3D"https://isocpp.org/std/standing-do= cuments/sd-7-mailing-procedures-and-how-to-write-papers" target=3D"_blank" = rel=3D"nofollow" onmousedown=3D"this.href=3D'https://www.google.com/url= ?q\x3dhttps%3A%2F%2Fisocpp.org%2Fstd%2Fstanding-documents%2Fsd-7-mailing-pr= ocedures-and-how-to-write-papers\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFb= owV1_Vqqdqz3w7nv5ud_Q6mdKA';return true;" onclick=3D"this.href=3D'h= ttps://www.google.com/url?q\x3dhttps%3A%2F%2Fisocpp.org%2Fstd%2Fstanding-do= cuments%2Fsd-7-mailing-procedures-and-how-to-write-papers\x26sa\x3dD\x26snt= z\x3d1\x26usg\x3dAFQjCNFbowV1_Vqqdqz3w7nv5ud_Q6mdKA';return true;">http= s://isocpp.org/std/<wbr>standing-documents/sd-7-<wbr>mailing-procedures-and= -how-to-<wbr>write-papers</a> <br></div><blockquote class=3D"gmail_quote" s= tyle=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:= 1ex"><div dir=3D"ltr"><br>I'm unaware of P0105, I've only found thi= s discussion: <a href=3D"https://groups.google.com/a/isocpp.org/forum/#!top= ic/std-discussion/TDSkjdJS1M0" rel=3D"nofollow" target=3D"_blank" onmousedo= wn=3D"this.href=3D'https://groups.google.com/a/isocpp.org/forum/#!topic= /std-discussion/TDSkjdJS1M0';return true;" onclick=3D"this.href=3D'= https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/TDSkjdJ= S1M0';return true;">https://groups.google.com/a/<wbr>isocpp.org/forum/#= !topic/std-<wbr>discussion/TDSkjdJS1M0</a></div></blockquote><div><br>You c= an use "<a href=3D"http://wg21.link" target=3D"_blank" rel=3D"nofollow= " onmousedown=3D"this.href=3D'http://www.google.com/url?q\x3dhttp%3A%2F= %2Fwg21.link\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFxqi7Dz6JZ7q97ahzl89Ea= vaqfKw';return true;" onclick=3D"this.href=3D'http://www.google.com= /url?q\x3dhttp%3A%2F%2Fwg21.link\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFx= qi7Dz6JZ7q97ahzl89EavaqfKw';return true;">http://wg21.link</a>" to= look up papers, e.g. <a href=3D"http://wg21.link/P0105" target=3D"_blank" = rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.google.com/url?= q\x3dhttp%3A%2F%2Fwg21.link%2FP0105\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjC= NEFx1ykzFDInFfOHUQOcE23a69PQg';return true;" onclick=3D"this.href=3D= 9;http://www.google.com/url?q\x3dhttp%3A%2F%2Fwg21.link%2FP0105\x26sa\x3dD\= x26sntz\x3d1\x26usg\x3dAFQjCNEFx1ykzFDInFfOHUQOcE23a69PQg';return true;= ">wg21.link/P0105</a><br>A list of published papers can be found here: <a h= ref=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/" target=3D"_blan= k" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.google.com/u= rl?q\x3dhttp%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%= 2F\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFFc3M1yEyY0Eq_HisSyQ1t1b2fXg'= ;;return true;" onclick=3D"this.href=3D'http://www.google.com/url?q\x3d= http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F\x26sa= \x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFFc3M1yEyY0Eq_HisSyQ1t1b2fXg';return= true;">http://www.open-std.org/jtc1/<wbr>sc22/wg21/docs/papers/</a><br></d= iv><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bo= rder-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><br>I do not th= ink that those function should work with floating point types, since the ar= ithmetic is completely different because of rounding, infinity values, and = nan.<br>The arithmetic of integral types, if no overflow occurs, is error-f= ree, and the comparison operators behave well to each other, for example &#= 39;a<b' is equivalent to '!(b<=3Da)' for every a and b, u= nfortunately for floats this is not true.<br>I would therefor prefer not to= supply overloaded functions for floating types, but only for integral type= s, this way we can eventually add them afterward.<br>I also think that situ= ations where you need to compare different float types are not so common as= with integral types. And since all float types are signed, there are usual= ly no unsafe conversions.<br><br></div></blockquote><div>That all makes sen= se.=C2=A0 At least leaving the door open seems wise.<br></div><blockquote c= lass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #c= cc solid;padding-left:1ex"><div><br>I didn't think about user-provided = types.<br><br>Since users can't add types that will pass the "std:= :is_integral" test, everyone if free to add his own overload in the gl= obal or in a separate namespace without risking to pick the wrong function.= <br>I think you can provide overloads in the std::namespace, but I do not k= now exactly on which situations. But I'm unsure if it would be really u= seful.<br><br>In my mind, there are two situations where you may want to pr= ovide your function<br><br>1) A custom comparison operator takes the user p= rovided class as a parameter and a integral.<br>2) The class is implicitly = convertible to some integral type.<br><br>Maybe it would make sense if you = do not want to make the conversion explicit, I need to think about it.<br><= /div></blockquote><div dir=3D"ltr"><br>I'm not sure what the best way i= s to provide customization points but making user-defined types work with e= xisting APIs seems achievable and of potential benefit.<br><br>Cheers<br>Jo= hn<br></div></div></blockquote></div> <p></p> -- <br /> You received this message because you are subscribed to the Google Groups &= quot;ISO C++ Standard - Future Proposals" group.<br /> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa= ls+unsubscribe@isocpp.org</a>.<br /> To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp= ..org">std-proposals@isocpp.org</a>.<br /> To view this discussion on the web visit <a href=3D"https://groups.google.c= om/a/isocpp.org/d/msgid/std-proposals/f48451b9-5933-4868-b7c4-b37518e72681%= 40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.= com/a/isocpp.org/d/msgid/std-proposals/f48451b9-5933-4868-b7c4-b37518e72681= %40isocpp.org</a>.<br /> ------=_Part_1015_2015077776.1500270285275-- ------=_Part_1014_1682361185.1500270285274-- .

Author: federico.kircheis@gmail.com

Date: Tue, 18 Jul 2017 09:57:03 -0700 (PDT)

------=_Part_2173_573810066.1500397024009 Content-Type: multipart/alternative; boundary="----=_Part_2174_1656511224.1500397024009" ------=_Part_2174_1656511224.1500397024009 Content-Type: text/plain; charset="UTF-8" Updated the proposal again, I've removed the precision function, John McFarian was right about "std::numeric_limits<T>::digits" and set the version number to D0586R1, since it is still a draft. is_losslessly_convertible might be a nice compile-time function, but I think that in_range with the std::numeric_limits<T>::max and std::numeric_limits<T>::min value will gave you the same result (and it can of course be used at compile-time too). -- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/4c552140-4029-4b28-af22-9e2843993516%40isocpp.org. ------=_Part_2174_1656511224.1500397024009 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">Updated the proposal again,<br><br>I've removed the pr= ecision function, John McFarian was right about "std::numeric_limits&l= t;T>::digits" and set the version number to D0586R1, since it is st= ill a draft.<br><br><br>is_losslessly_convertible might be a nice compile-t= ime function, but I think that in_range with the std::numeric_limits<T&g= t;::max and std::numeric_limits<T>::min value will gave you the same = result (and it can of course be used at compile-time too).<br></div> <p></p> -- <br /> You received this message because you are subscribed to the Google Groups &= quot;ISO C++ Standard - Future Proposals" group.<br /> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa= ls+unsubscribe@isocpp.org</a>.<br /> To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp= ..org">std-proposals@isocpp.org</a>.<br /> To view this discussion on the web visit <a href=3D"https://groups.google.c= om/a/isocpp.org/d/msgid/std-proposals/4c552140-4029-4b28-af22-9e2843993516%= 40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.= com/a/isocpp.org/d/msgid/std-proposals/4c552140-4029-4b28-af22-9e2843993516= %40isocpp.org</a>.<br /> ------=_Part_2174_1656511224.1500397024009-- ------=_Part_2173_573810066.1500397024009-- .

Author: federico.kircheis@gmail.com

Date: Tue, 18 Jul 2017 09:57:57 -0700 (PDT)

------=_Part_2200_1803443752.1500397077513 Content-Type: multipart/alternative; boundary="----=_Part_2201_1963458137.1500397077514" ------=_Part_2201_1963458137.1500397077514 Content-Type: text/plain; charset="UTF-8" Forgot to attach the new proposal ;-) On Tuesday, July 18, 2017 at 6:57:04 PM UTC+2, federico...@gmail.com wrote: > > Updated the proposal again, > > I've removed the precision function, John McFarian was right about > "std::numeric_limits<T>::digits" and set the version number to D0586R1, > since it is still a draft. > > > is_losslessly_convertible might be a nice compile-time function, but I > think that in_range with the std::numeric_limits<T>::max and > std::numeric_limits<T>::min value will gave you the same result (and it can > of course be used at compile-time too). > -- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/10063dea-8668-4096-a0da-58a142229e13%40isocpp.org. ------=_Part_2201_1963458137.1500397077514 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">Forgot to attach the new proposal ;-)<br><br>On Tuesday, J= uly 18, 2017 at 6:57:04 PM UTC+2, federico...@gmail.com wrote:<blockquote c= lass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px= #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">Updated the proposal again= ,<br><br>I've removed the precision function, John McFarian was right a= bout "std::numeric_limits<T>::<wbr>digits" and set the vers= ion number to D0586R1, since it is still a draft.<br><br><br>is_losslessly_= convertible might be a nice compile-time function, but I think that in_rang= e with the std::numeric_limits<T>::max and std::numeric_limits<T&g= t;::min value will gave you the same result (and it can of course be used a= t compile-time too).<br></div></blockquote></div> <p></p> -- <br /> You received this message because you are subscribed to the Google Groups &= quot;ISO C++ Standard - Future Proposals" group.<br /> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa= ls+unsubscribe@isocpp.org</a>.<br /> To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp= ..org">std-proposals@isocpp.org</a>.<br /> To view this discussion on the web visit <a href=3D"https://groups.google.c= om/a/isocpp.org/d/msgid/std-proposals/10063dea-8668-4096-a0da-58a142229e13%= 40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.= com/a/isocpp.org/d/msgid/std-proposals/10063dea-8668-4096-a0da-58a142229e13= %40isocpp.org</a>.<br /> ------=_Part_2201_1963458137.1500397077514-- ------=_Part_2200_1803443752.1500397077513 Content-Type: text/html; charset=US-ASCII; name=proposal.html Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=proposal.html X-Attachment-Id: c59e2312-90c2-4802-b4cb-a663187335f7 Content-ID: <c59e2312-90c2-4802-b4cb-a663187335f7> <!DOCTYPE html> <html lang="en"> <head> <title>Safe integral comparisons</title> </head> <body> <address> Document number: D0586R1<br/> Date: 2017-02-04<br/> Project: Programming Language C++<br/> Reply-to: <a href="mailto:federico.kircheis@gmail.com">Federico Kircheis</a><br/> </address> <h1>Safe integral comparisons</h1> <h2 id="Table">I. Table of Contents</h2> <ul style="font-family:monospace"> <li><a href="#Table" >I).......Table of Contents</a></li> <li><a href="#Motivation" >II)......Motivation</a></li> <li><a href="#Proposal" >III).....Proposal</a></li> <li><a href="#Examples" >IV)......Examples</a></li> <li><a href="#Implementation" >V).......Possible implementation</a></li> <li><a href="#Effects" >VI)......Effects on Existing Code</a></li> <li><a href="#Design" >VII).....Design Decisions</a></li> <li><a href="#Related" >VIII)....Related Works</a></li> </ul> <h2 id="Motivation">II. Motivation</h2> <p> Comparing integrals of different types may be a more complex task than expected. Most of the time we expect that a simple </p> <pre><code> if(a < b){ // ... } else { // ... } </code></pre> <p> should work in all cases, but if <code>a</code> and <code>b</code> are of different types, things are more complicated.<br/> If <code>a</code> is a signed type, and <code>b</code> unsigned, then <code>a</code> is converted to the unsigned type. If <code>a</code> held a number less than zero, then the result may be unexpected, since the expression <code>a < b</code> could evaluate to false, even if a strictly negative number is always lower than a positive one. </p> <p> Also converting integrals between different types can be challenging, for simplicity, most of the time we assume that values are in range, and write </p> <pre><code> a = static_cast<decltype(a)>(b);</code></pre> <p> If we want to write a safe conversion, we need to check if <code>b</code> has a value between <code>std::numeric_limits<decltype(a)>::min()</code> and <code>std::numeric_limits<decltype(a)>::max()</code>. We also need to pay attention that no implicit conversion (for example between unsigned and signed types) invalidates our comparison. </p> <p> Comparing and converting numbers, even of different numeric types, should be a trivial task. Unfortunately it is not, and because of implicit conversions we may write, without noticing it, unsafe code. </p> <h2 id="Proposal">III. Proposal</h2> <p> This paper proposes to add a set of <code>constexpr</code> and <code>noexcept</code> functions for converting and comparing integrals of different signeddes (except for <code>bool</code>): </p> <ul> <li> Two functions to compare if two variables represent the same value or not <pre><code> template <typename T, typename U> constexpr bool std::cmp_equal(T t, U u) noexcept; template <typename T, typename U> constexpr bool std::cmp_unequal(T t, U u) noexcept; </code></pre> <li> A set of functions that can be used to determine the relative order of two values <pre><code> template <typename T, typename U> constexpr bool std::cmp_less(T t, U u) noexcept; template <typename T, typename U> constexpr bool std::cmp_greater(T t, U u) noexcept; template <typename T, typename U> constexpr bool std::cmp_less_or_equal(T t, U u) noexcept; template <typename T, typename U> constexpr bool std::cmp_greater_or_equal(T t, U u) noexcept; </code></pre> <li> One function to determine if a specific value is inside the range of possible values of another type (i.e. if we can convert the value to the other type safely) <pre><code> template <typename R, typename T> constexpr bool in_range(T t) noexcept; </code></pre> <h2 id="Examples">IV. Examples</h2> <h3>Examples without current proposal</h3> <p>Comparing an unsigned int with an int:</p> <pre><code> int a = ... unsigned int b = ... // added static_cast to avoid compiler warnings since we are doing a "safe" comparison if(a < 0 || static_cast<unsigned int>(a) < b){ // do X } else { // do Y } </code></pre> <p>Comparing an uint32_t with an int16_t:</p> <pre><code> int32_t a = ... uint16_t b = ... // added static_cast to avoid compiler warnings since we are doing a "safe" comparison if(a < static_cast<int32_t>(b)){ // do X } else { // do Y } </code></pre> <p>Comparing an int with an intptr_t:</p> <pre><code> int a = ... intptr_t b = ... if(???){ // no idea how to do it in one readable line without some assumption about int and intptr_t // do X } else { // do Y } </code></pre> <h3>Example with current proposal</h3> <p> Comparing one integral type <code>A</code> with another integral type <code>B</code> (both non <code>bool</code>): </p> <pre><code> A a = ... B b = ... // no need for any cast since std::cmp_less is taking care of everything if( std::cmp_less(a,b)){ // do X } else { // do Y } </code></pre> <h2 id="Implementation">V. Possible implementation</h2> <p> This section shows an example of how <code>cmp_equal</code>, <code>cmp_less</code> and <code>in_range</code> can be implemented with any standard conforming C++11 compiler. The only dependencies are the <code>std::numeric_limits</code> function from the <code>limits</code> header and some traits from the <code>type_traits</code> header. This implementation can also be found on <a href="https://raw.githubusercontent.com/fekir/safeintegral/master/safeintegral/safeintegralop_cmp.hpp">github</a>. </p> <pre><code> #include <limits> #include <type_traits> namespace details{ #if defined(ERR_MSG_xxx_NEEDS_INTEGRAL_NOT_BOOL) || defined(ASSERT_INTEGRAL_NOT_BOOL_TYPE) #error "ERR_MSG_xxx_NEEDS_INTEGRAL_NOT_BOOL or ASSERT_INTEGRAL_NOT_BOOL_TYPE already defined" #endif #define ERR_MSG_xxx_NEEDS_INTEGRAL_NOT_BOOL " needs to be an integral (not bool) value type" #define ASSERT_INTEGRAL_NOT_BOOL_TYPE(T) static_assert(is_integral_not_bool<T>(), #T ERR_MSG_xxx_NEEDS_INTEGRAL_NOT_BOOL); template <typename T> constexpr bool is_integral_not_bool(){ using value_type = typename std::remove_cv<T>::type; return !std::is_same<value_type,bool>::value && std::is_integral<T>::value; } // could use the same implementation of in_range_signed_signed, but compiler may generate warning that t is always bigger than 0 template <typename R, typename T> constexpr bool in_range_unsigned_unsigned(const T t) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(R); return (std::numeric_limits<T>::digits > std::numeric_limits<R>::digits ) ? (t < static_cast<T>(std::numeric_limits<R>::max())) : (static_cast<R>(t) <std::numeric_limits<R>::max()); } template <typename R, typename T> constexpr bool in_range_signed_signed(const T t) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(R); return (std::numeric_limits<T>::digits > std::numeric_limits<R>::digits ) ? (t <= static_cast<T>(std::numeric_limits<R>::max()) && t >= static_cast<T>(std::numeric_limits<R>::min())) : (static_cast<R>(t) <= std::numeric_limits<R>::max() && static_cast<R>(t) >= std::numeric_limits<R>::max()); } template <typename R, typename T> constexpr bool in_range_signed_unsigned(const T t) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(R); return (t < T{ 0 }) ? false : (std::numeric_limits<T>::digits / 2 <= std::numeric_limits<R>::digits ) ? true : (t <= static_cast<T>(std::numeric_limits<R>::max())); } template <typename R, typename T> constexpr bool in_range_unsigned_signed(const T t) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(R); return (std::numeric_limits<T>::digits >= std::numeric_limits<R>::digits / 2) ? (t <= static_cast<T>(std::numeric_limits<R>::max())) : true; } template <typename R, typename T> constexpr bool in_range_unsigned(const T t) noexcept { return std::is_unsigned<R>::value ? in_range_unsigned_unsigned<R>(t) : in_range_unsigned_signed<R>(t); } template <typename R, typename T> constexpr bool in_range_signed(const T t) noexcept { return std::is_signed<R>::value ? in_range_signed_signed<R>(t) : in_range_signed_unsigned<R>(t); } template <typename T, typename U> constexpr bool cmp_equal_same_sign(const T t, const U u) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(U); return (std::numeric_limits<T>::digits > std::numeric_limits<U>::digits ) ? (t == static_cast<T>(u)) : (static_cast<U>(t) == u); } template <typename T, typename U> constexpr bool cmp_equal_signed_unsigned(const T t, const U u) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(U); return (t<T{ 0 }) ? false : (std::numeric_limits<T>::digits / 2> std::numeric_limits<U>::digits ) ? (t == static_cast<T>(u)) : (static_cast<U>(t) == u); } template <typename T, typename U> constexpr bool cmp_less_same_sign(const T t, const U u) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(U); return (std::numeric_limits<T>::digits >std::numeric_limits<U>::digits ) ? (t < static_cast<T>(u)) : (static_cast<U>(t) < u); } template <typename T, typename U> constexpr bool cmp_less_signed_unsigned(const T t, const U u) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(U); return (t<T{ 0 }) ? true : (std::numeric_limits<T>::digits / 2>std::numeric_limits<U>::digits ) ? (t < static_cast<T>(u)) : (static_cast<U>(t) < u); } template <typename T, typename U> constexpr bool cmp_less_unsigned_signed(const T t, const U u) noexcept { ASSERT_INTEGRAL_NOT_BOOL_TYPE(T); ASSERT_INTEGRAL_NOT_BOOL_TYPE(U); return (u<U{ 0 }) ? false : (std::numeric_limits<U>::digits / 2>std::numeric_limits<T>::digits ) ? (static_cast<U>(t) < u) : (t < static_cast<T>(u)); } #undef ERR_MSG_xxx_NEEDS_INTEGRAL_NOT_BOOL #undef ASSERT_INTEGRAL_NOT_BOOL_TYPE } // end details /// Usage: /// size_t i = ... /// if(in_range<DWORD>(i)){ /// // safe to use i as a DWORD value, parameter... /// } else { /// // not possible to rappresent i as a DWORD /// } template <typename R, typename T> constexpr bool in_range(const T t) noexcept { return std::is_unsigned<T>::value ? details::in_range_unsigned<R>(t) : details::in_range_signed<R>(t); } // equivalent of operator== for different types /// Usage: /// size_t i = ... /// DWORD j = ... /// if(cmp_equal(i,j)){ /// // i and j rappresent the same quantity /// } else { /// // i and j rappresents different quantities /// } template <typename T, typename U> constexpr bool cmp_equal(const T t, const U u) noexcept { return (std::is_signed<T>::value == std::is_signed<U>::value) ? details::cmp_equal_same_sign(t, u) : (std::is_signed<T>::value) ? details::cmp_equal_signed_unsigned(t, u) : details::cmp_equal_signed_unsigned(u,t); } // equivalent of operator< for different integral types /// Usage: /// size_t i = ... /// DWORD j = ... /// if(cmp_less(i,j)){ /// // i < j /// } else { /// // i >= j /// } template <typename T, typename U> constexpr bool cmp_less(const T t, const U u) noexcept { return (std::is_signed<T>::value == std::is_signed<U>::value) ? details::cmp_less_same_sign(t,u) : (std::is_signed<T>::value) ? details::cmp_less_signed_unsigned(t, u) : details::cmp_less_unsigned_signed(t, u); } </code></pre> <h2 id="Effects">VI. Effects on Existing Code</h2> <p> Since the proposed functions are not defined in any standard header, no currently existing code behavior will be changed. </p> <h2 id="Design">VII. Design Decisions</h2> <p> Since there is no reason to compare <code>true</code> and <code>false</code> with other integral types, there isn't one to provide an overload for the <code>bool</code> integral type either.<br/> The name of the functions (<code>cmp_equal</code>, <code>cmp_less</code> and others) are open to discussion, but the function names <code>std::less</code> and <code>std::greater</code> should not be used, since these do already exist, and have a different meaning. </p> <h2 id="Related">VIII. Related Works</h2> <p> In 2016, Robert Ramey did a much bigger proposal (see <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0228r0.pdf">p0228r0</a>) regaridng safe integer types. He also used similar functions proposed in this paper for implementing his classes and operators, therefore an alternative implementation can be found on his <a href="https://github.com/robertramey/safe_numerics/blob/master/include/safe_compare.hpp">github repository</a>. This proposal addresses a smaller problem, namely comparing integral values, and is therefore much smaller.<br/> The functions provided can be also used for creating safe integer types. </p> <p> Another work, by Herb Sutter (see <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0515r0.pdf">p0515r0</a>), is about a new comparison operator (<code><=></code>). As far as I've understood the proposal the <code>operator<=></code> should compare correctly different integral types, making part of this proposal obsolete if the operator is added to the language. While it would be a nice thing to have, having a new comparison operator that operates differently from the old operators may be counterintuitive and cause confusion, even if the new behaviour is more correct. </p> </body> </html> ------=_Part_2200_1803443752.1500397077513-- .

Author: federico.kircheis@gmail.com

Date: Sat, 25 Nov 2017 09:04:23 -0800 (PST)

------=_Part_5171_1543445565.1511629463703 Content-Type: multipart/alternative; boundary="----=_Part_5172_1729226462.1511629463703" ------=_Part_5172_1729226462.1511629463703 Content-Type: text/plain; charset="UTF-8" For those interested in this proposal, you might give a look at https://issues.isocpp.org/show_bug.cgi?id=361 I've attached the currently updated version of the proposal. -- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/d8b05d52-2a7e-42de-ab98-ce7063fe52e7%40isocpp.org. ------=_Part_5172_1729226462.1511629463703 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">For those interested in this proposal, you might give a lo= ok at<br><br>https://issues.isocpp.org/show_bug.cgi?id=3D361<br><br><br>I&#= 39;ve attached the currently updated version of the proposal.<br></div> <p></p> -- <br /> You received this message because you are subscribed to the Google Groups &= quot;ISO C++ Standard - Future Proposals" group.<br /> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa= ls+unsubscribe@isocpp.org</a>.<br /> To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp= ..org">std-proposals@isocpp.org</a>.<br /> To view this discussion on the web visit <a href=3D"https://groups.google.c= om/a/isocpp.org/d/msgid/std-proposals/d8b05d52-2a7e-42de-ab98-ce7063fe52e7%= 40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.= com/a/isocpp.org/d/msgid/std-proposals/d8b05d52-2a7e-42de-ab98-ce7063fe52e7= %40isocpp.org</a>.<br /> ------=_Part_5172_1729226462.1511629463703-- ------=_Part_5171_1543445565.1511629463703 Content-Type: text/html; charset=US-ASCII; name=proposal.html Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=proposal.html X-Attachment-Id: 46398f19-bbf2-4d74-b7c1-398c20d987e2 Content-ID: <46398f19-bbf2-4d74-b7c1-398c20d987e2> <!DOCTYPE html> <html lang="en"> <head> <title>Safe integral comparisons</title> </head> <body> <address> Document number: P0586R0.2<br/> Date: 2017-11-25<br/> Project: Programming Language C++<br/> Reply-to: <a href="mailto:federico.kircheis@gmail.com">Federico Kircheis</a><br/> Audience: Library Evolution Working Group<br/> </address> <h1>Safe integral comparisons</h1> <h2 id="Table">I. Table of Contents</h2> <ul style="font-family:monospace"> <li><a href="#Table" >I).......Table of Contents</a></li> <li><a href="#Motivation" >II)......Motivation</a></li> <li><a href="#Proposal" >III).....Proposal</a></li> <li><a href="#Examples" >IV)......Examples</a></li> <li><a href="#Implementation" >V).......Possible implementation</a></li> <li><a href="#Effects" >VI)......Effects on Existing Code</a></li> <li><a href="#Design" >VII).....Design Decisions</a></li> <li><a href="#Further" >VIII)....Further Considerations</a></li> <li><a href="#Related" >IX)......Related Works</a></li> <li><a href="#Wording" >X).......Proposed Wording</a></li> </ul> <h2 id="Motivation">II. Motivation</h2> <p> Comparing integrals of different types may be a more complex task than expected. Most of the time we expect that a simple </p> <pre><code> if(a < b){ // ... } else { // ... } </code></pre> <p> should work in all cases, but if <code>a</code> and <code>b</code> are of different types, things are more complicated. </p> <p> If <code>a</code> is a signed type, and <code>b</code> unsigned, then, supposing that no integral promotion is taking place, <code>a</code> is converted to the unsigned type. If <code>a</code> holds a number less than zero, then the result may be unexpected, since the expression <code>a < b</code> would evaluate to false, even though a strictly negative number is always lower than a positive one. Also, converting integrals between different types can be challenging. For simplicity, most of the time we assume that values are in range, and write </p> <pre><code> a = static_cast<decltype(a)>(b);</code></pre> <p> If we want to write a safe conversion, we need to check if <code>b</code> has a value between <code>std::numeric_limits<decltype(a)>::min()</code> and <code>std::numeric_limits<decltype(a)>::max()</code>. We also need to pay attention that no implicit conversion (for example between unsigned and signed types) invalidates our comparison. </p> <p> Comparing and converting numbers, even of different numeric types, should be a trivial task. Unfortunately it is not, and because of implicit conversions we may write, without noticing it, unsafe code. <p> Most compilers are able to provide diagnostics and generate warnings when comparing values of different types, or when doing a narrowing conversion. </p> <p> Developers are tempted to assume that values will mostly be in range and write a simple, but possibly wrong, cast in order to silence the warning, or not to turn on the corresponding compiler warning at all. </p> <h2 id="Proposal">III. Proposal</h2> <p> This paper proposes to add a set of <code>constexpr</code> and <code>noexcept</code> functions for converting and comparing integrals of different signedness, except for <code>bool</code> and character types. </p> <ul> <li> Two functions to compare if two variables represent the same value or not <pre><code> template <typename T, typename U> constexpr bool std::cmp_equal(T t, U u) noexcept; template <typename T, typename U> constexpr bool std::cmp_unequal(T t, U u) noexcept; </code></pre> <li> A set of functions that can be used to determine the relative order of two values <pre><code> template <typename T, typename U> constexpr bool std::cmp_less(T t, U u) noexcept; template <typename T, typename U> constexpr bool std::cmp_greater(T t, U u) noexcept; template <typename T, typename U> constexpr bool std::cmp_less_or_equal(T t, U u) noexcept; template <typename T, typename U> constexpr bool std::cmp_greater_or_equal(T t, U u) noexcept; </code></pre> <li> One function to determine if a specific value is inside the range of possible values of another type (i.e. if we can convert the value to the other type safely) <pre><code> template <typename R, typename T> constexpr bool in_range(T t) noexcept; </code></pre> </ul> <h2 id="Examples">IV. Examples</h2> <h3>Examples without current proposal</h3> <p>Comparing an unsigned int with an int:</p> <pre><code> int a = ... unsigned int b = ... // add static_cast to avoid compiler warnings since we are doing a "safe" comparison if(a < 0 || static_cast<unsigned int>(a) < b){ // do X } else { // do Y } </code></pre> <p>Comparing a uint32_t with an int16_t:</p> <pre><code> int32_t a = ... uint16_t b = ... // add static_cast to avoid compiler warnings since we are doing a "safe" comparison if(a < static_cast<int32_t>(b)){ // do X } else { // do Y } </code></pre> <p>Comparing an int with an intptr_t:</p> <pre><code> int a = ... intptr_t b = ... if(???){ // no idea how to do it in one readable line without some assumption about int and intptr_t // do X } else { // do Y } </code></pre> <h3>Example with current proposal</h3> <p> Comparing one integral type <code>A</code> with another integral type <code>B</code> (both non <code>bool</code> or character type): </p> <pre><code> A a = ... B b = ... // no need for any cast since std::cmp_less is taking care of everything if(std::cmp_less(a,b)){ // do X } else { // do Y } </code></pre> <h2 id="Implementation">V. Possible implementation</h2> <p> A possible implementation can be found on <a href="https://raw.githubusercontent.com/fekir/safeintegral/master/safeintegral/safeintegralop_cmp.hpp">github</a>. The only dependencies are the <code>std::numeric_limits</code> function from the <code>limits</code> header, some traits from the <code>type_traits</code> header and a standard conforming C++11 compiler. </p> <h2 id="Effects">VI. Effects on Existing Code</h2> <p> Since the proposed functions are not defined in any standard header, the meaning of no existing code will be changed. </p> <h2 id="Design">VII. Design Decisions</h2> <p> This proposal addresses how to compare <em>numerical values</em> of different types (aka standard integer types and extended integer types) in a safe and simple way. It makes little sense to compare <code>true</code>, <code>false</code>, <code>'a'</code> and other characters to numbers, since they represent different logical entities. The encoding of characters is also not specified, therefore the possible valid comparison <code>'a' == 97</code> might yield different results depending on the locale, compiler or platform. </p> <p> Providing an overload for <code>char</code> might not reduce confusion, for example: </p> <pre><code> int32_t a = ... char c = -1; cmp_less(c, 0) // true if char is signed, false if char is unsigned. </code></pre> <p> If the user has to choose between <code>signed char</code> or <code>unsigned char</code>, the behaviour will always be consistent. Using <code>char</code> for storing a number is a valid use case (the language permits it), but the types <code>signed char</code> and <code>unsigned char</code> should be preferred since those are standard integer types and have the same size. </p> <p> I would also recommend not to provide overloads for <code>bool</code> and the character types because it is easier to add them later if needed, whereas removing them might be more difficult since it would be a breaking change. </p> <p> If the LEWG would like to include <code>char</code>, I think it would be better to provide an overload for every character type for consistency. </p> <p> The name of the functions (<code>cmp_equal</code>, <code>cmp_less</code> and others) are open to discussion, but the function names <code>std::less</code> and <code>std::greater</code> should not be used, since these do already exist and have a different meaning. </p> <h2 id="Further">VIII. Further Considerations</h2> <p> I've heard rumors that it might be possible that the current <code>operator<</code> et al. could get deprecated and maybe changed someday to behave like the functions proposed in this proposal.<br> I would like to add some considerations: </p> <ul> <li> <p>Doing the right thing might be less efficient than doing the wrong thing. Changing how <code>operator<</code> works on integral types might make it less efficient, it may require extra instructions, even an extra branch instruction. but performance is mostly irrelevant if we need to choose between the right result and a possibly wrong result. Compilers are able to detect when comparing numbers of different types and they'll very probably be able to do so in the future even if operator< changes meaning. If a developer wants a better efficiency, they should use the correct type to avoid conversions.</p> </li> <li> <p>Even today, comparing numbers might require more instructions and branches than expected on some targets.</p> </li> <li> <p>Because of optimizations and branch prediction, the <code>cmp_less</code> function might be as efficient as the current <code>operator<</code>.</p> </li> <li> <p>There are some use cases where, today, we have a warning as a side-effect that shows the user that the code might be wrong, but by changing <code>operator<</code> it will still be wrong and we will not have the warning anymore:</p> <code>for(auto i = 0; i < container.size(); ++i){/**/}</code>.<br> <p>The code is wrong with all standard containers because the condition may never be met and there is a possible overflow. Since we are comparing, we get a warning because of <code>operator<</code>. The problem is that in this case it's not the comparison that is wrong, but the whole expression (it could also be that size returns a signed type but with a bigger range). As stated above, the warning caused by <code>operator<</code> is just a fortunate side-effect. I do not know if compilers in the future will be able to warn about those and more complex expressions.</p> </li> </ul> <h2 id="Related">IX. Related Works</h2> <p> In 2016, Robert Ramey did a much bigger proposal (see <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0228r0.pdf">p0228r0</a>) regarding safe integer types. He also used functions similar to those proposed in this paper for implementing his classes and operators, so an alternative implementation can be found on his <a href="https://github.com/robertramey/safe_numerics/blob/master/include/safe_compare.hpp">github repository</a>. This proposal addresses a smaller problem, namely comparing integral values, and is therefore much smaller.<br/> The functions provided can be also used for creating safe integer types. </p> <p> Another work, by Herb Sutter (see <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0515r2.pdf">p0515r2</a>), is about a new comparison operator (<code><=></code>). In its current state the <code>operator<=></code> will not compare different integral types, but in a previous revision as far as I've understood, the proposal stated that <code>operator<=></code> should compare correctly different integral types, making part of this proposal obsolete. </p> <h2 id="Wording">X. Proposed Wording</h2> <p> This section presents the wording changes for P0586R0. Any differences in semantics are unintentional. n4659 has been used as reference. </p> <p> In 23.2.1 Header <utility> synopsis, add declarations: </p> <pre><code> // 23.2.10, safe integral comparisons template <typename R, typename T> constexpr bool in_range(const T t) noexcept; template <typename T, typename U> constexpr bool cmp_equal(const T t, const U u) noexcept; template <typename T, typename U> constexpr bool cmp_unequal(const T t, const U u) noexcept; template <typename T, typename U> constexpr bool cmp_less(const T t, const U u) noexcept; template <typename T, typename U> constexpr bool cmp_greater(const T t, const U u) noexcept; template <typename T, typename U> constexpr bool cmp_less_or_equal(const T t, const U u) noexcept; template <typename T, typename U> constexpr bool cmp_greater_or_equal(const T t, const U u) noexcept; </code></pre> <p> Add a new Section <q>23.2.10, safe integral comparisons</q>, with following content: </p> <pre> 1. For each of the following functions, if either of `T` or `U` is not a standard integer type or an extended integer type, as specified in 6.9.1, the call is ill-formed. [Note: std::byte, char, char16_t, char32_t, wchar_t, and bool are not comparable with these functions. --end note] template <typename T, typename U> constexpr bool cmp_equal(const T t, const U u) noexcept; Returns: If `T` and `U` are both signed, or both unsigned types, returns `t == u`. Otherwise, if `t` or `u` is negative, returns `false`. Otherwise, if `T` is a signed type, constructs from `t` a value `tu` of the corresponding unsigned type and returns `tu == u`. Otherwise, if `U` is a signed type, constructs from `u` a value `uu` of the corresponding unsigned type and returns `t == uu`. template <typename T, typename U> constexpr bool cmp_unequal(const T t, const U u) noexcept; Returns: If `T` and `U` are both signed, or both unsigned types, returns `t != u`. Otherwise, if `t` or `u` is negative, returns `true`. Otherwise, if `T` is a signed type, constructs from `t` a value `tu` of the corresponding unsigned type and returns `tu != u`. Otherwise, if `U` is a signed type, constructs from `u` a value `uu` of the corresponding unsigned type and returns `t != uu`. template <typename T, typename U> constexpr bool cmp_less(const T t, const U u) noexcept; Returns: If `T` and `U` are both signed, or both unsigned types, returns `t < u`. Otherwise, if `t` is negative, returns `true`. Otherwise, if `u` is negative, returns `false`. Otherwise, if `T` is a signed type, constructs from `t` a value `tu` of the corresponding unsigned type and returns `tu < u`. Otherwise, if `U` is a signed type, constructs from `u` a value `uu` of the corresponding unsigned type and returns `t < uu`. template <typename T, typename U> constexpr bool cmp_greater(const T t, const U u) noexcept; Returns: If `T` and `U` are both signed, or both unsigned types, returns `t > u`. Otherwise, if `t` is negative, returns `false`. Otherwise, if `u` is negative, returns `true`. Otherwise, if `T` is a signed type, constructs from `t` a value `tu` of the corresponding unsigned type and returns `tu > u`. Otherwise, if `U` is a signed type, constructs from `u` a value `uu` of the corresponding unsigned type and returns `t > uu`. template <typename T, typename U> constexpr bool cmp_less_or_equal(const T t, const U u) noexcept; Returns: If `T` and `U` are both signed, or both unsigned types, returns `t <= u`. Otherwise, if `t` is negative, returns `true`. Otherwise, if `u` is negative, returns `false`. Otherwise, if `T` is a signed type, constructs from `t` a value `tu` of the corresponding unsigned type and returns `tu <= u`. Otherwise, if `U` is a signed type, constructs from `u` a value `uu` of the corresponding unsigned type and returns `t <= uu`. template <typename T, typename U> constexpr bool cmp_greater_or_equal(const T t, const U u) noexcept; Returns: If `T` and `U` are both signed, or both unsigned types, returns `t >= u`. Otherwise, if `t` is negative, returns `false`. Otherwise, if `u` is negative, returns `true`. Otherwise, if `T` is a signed type, constructs from `t` a value `tu` of the corresponding unsigned type and returns `tu >= u`. Otherwise, if `U` is a signed type, constructs from `u` a value `uu` of the corresponding unsigned type and returns `t >= uu`. template <typename R, typename T> constexpr bool in_range(T t) noexcept; Returns: Returns the same value of `cmp_greater_or_equal(t, std::numeric_limits<R>::min()) && cmp_less_or_equal(t, std::numeric_limits<R>::max())` </pre> In case the LEWG would like to include char in the argument set, replace <pre>1.</pre> with <pre> 1. For each of the following functions, if either of `T` or `U` is not a standard integer type or extended integer type, as defined in 6.9.1, and not char, the call is ill-formed. If the implementation defines `char` to be a signed type, its corresponding unsigned type, in the following, is `unsigned char`. [Note: std::byte, char16_t, char32_t, wchar_t, and bool are not comparable using these functions. --end note] </pre> </body> </html> ------=_Part_5171_1543445565.1511629463703-- .

Author: Ben Craig <ben.craig@gmail.com>

Date: Sun, 26 Nov 2017 05:59:15 -0800 (PST)

------=_Part_22576_996406390.1511704755740 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable This paper was discussed briefly in Albuquerque. It was the opinion of lewg= that this was largely supplanted by op<=3D>, which was voted into c++20. O= f you want to continue supporting this paper, you should devote more text, = much earlier in the paper, discussing why this is sufficiently valuable com= pared to op<=3D>. It was lewgs understanding that op<=3D> did the safe comparison with differ= ent int types. If possible, you should also attend Jacksonville, or find a champion to dis= cuss the paper for you. --=20 You received this message because you are subscribed to the Google Groups "= ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an e= mail to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp= ..org/d/msgid/std-proposals/033c6637-44bc-4dd7-8770-a8473834f483%40isocpp.or= g. ------=_Part_22576_996406390.1511704755740-- .

Author: federico.kircheis@gmail.com

Date: Sun, 26 Nov 2017 07:50:04 -0800 (PST)

------=_Part_19697_206156943.1511711404118 Content-Type: multipart/alternative; boundary="----=_Part_19698_650160517.1511711404118" ------=_Part_19698_650160517.1511711404118 Content-Type: text/plain; charset="UTF-8" Hi, thank you for your feedback. If you look at the history of the "bug", it has been closed by Titus Winters with your same motivation: op<=> did the safe comparison with different int types. In its current state, op<=> does not compare different integral types at all, it provides only comparison semantic for the same type. This is the reason why the bug was reopened and Nathan Myers asked me for wording. I'll not be able to attend Jacksonville, but I've probably already found someone that could discuss the paper for me. On Sunday, November 26, 2017 at 2:59:15 PM UTC+1, Ben Craig wrote: > > This paper was discussed briefly in Albuquerque. It was the opinion of > lewg that this was largely supplanted by op<=>, which was voted into c++20. > Of you want to continue supporting this paper, you should devote more text, > much earlier in the paper, discussing why this is sufficiently valuable > compared to op<=>. > > It was lewgs understanding that op<=> did the safe comparison with > different int types. > > If possible, you should also attend Jacksonville, or find a champion to > discuss the paper for you. > > -- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group. To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org. To post to this group, send email to std-proposals@isocpp.org. To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/9d64f8ff-ae72-433f-a5ac-c621348ede3f%40isocpp.org. ------=_Part_19698_650160517.1511711404118 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">Hi,<br><br>thank you for your feedback.<br><br>If you look= at the history of the "bug", it has been closed by <span class= =3D"bz_comment_number"> </span> <span class=3D"bz_comment_user"> <span class=3D"vcard"><span class=3D"fn">Titus Winters </span></s= pan></span>with your same motivation: op<=3D> did the safe comparison= with different int types.<br><br>In its current state, op<=3D> does = not compare different integral types at all, it provides only comparison se= mantic for the same type.<br><br>This is the reason why the bug was reopene= d and <span class=3D"bz_comment_number"> </span> <span class=3D"bz_comment_user"> <span class=3D"vcard"><span class=3D"fn">Nathan Myers asked me fo= r wording.<br><br>I'll not be able to attend </span></span></span><span= class=3D"bz_comment_user"><span class=3D"vcard"><span class=3D"fn">Jackson= ville, but I've probably already found someone that could discuss the p= aper for me.<br><br><br></span></span></span>On Sunday, November 26, 2017 a= t 2:59:15 PM UTC+1, Ben Craig wrote:<blockquote class=3D"gmail_quote" style= =3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: = 1ex;">This paper was discussed briefly in Albuquerque. It was the opinion o= f lewg that this was largely supplanted by op<=3D>, which was voted i= nto c++20. Of you want to continue supporting this paper, you should devote= more text, much earlier in the paper, discussing why this is sufficiently = valuable compared to op<=3D>.<p>It was lewgs understanding that op<= ;=3D> did the safe comparison with different int types.</p><p>If possibl= e, you should also attend Jacksonville, or find a champion to discuss the p= aper for you.</p><p></p></blockquote></div> <p></p> -- <br /> You received this message because you are subscribed to the Google Groups &= quot;ISO C++ Standard - Future Proposals" group.<br /> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa= ls+unsubscribe@isocpp.org</a>.<br /> To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp= ..org">std-proposals@isocpp.org</a>.<br /> To view this discussion on the web visit <a href=3D"https://groups.google.c= om/a/isocpp.org/d/msgid/std-proposals/9d64f8ff-ae72-433f-a5ac-c621348ede3f%= 40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.= com/a/isocpp.org/d/msgid/std-proposals/9d64f8ff-ae72-433f-a5ac-c621348ede3f= %40isocpp.org</a>.<br /> ------=_Part_19698_650160517.1511711404118-- ------=_Part_19697_206156943.1511711404118-- .