- "C++ on the Move" by Darryl K. Taft - 9 Updates
- Why no structured bings in catch()? - 1 Update
- Functions and Global Variables defined in Libraries - 1 Update
- Pass by rvalue reference - 2 Updates
scott@slp53.sl.home (Scott Lurndal): Mar 08 07:49PM >Two example of [not so] new non-crap libraries that are entangled with [not= > so] new >crap - std::chrono and std::random. There are platform native interfaces providing the functionality of both std::chrono and std::random, so yes, it's true. |
Michael S <already5chosen@yahoo.com>: Mar 08 12:08PM -0800 On Wednesday, March 8, 2023 at 9:49:54 PM UTC+2, Scott Lurndal wrote: > >crap - std::chrono and std::random. > There are platform native interfaces providing the functionality of both > std::chrono and std::random, so yes, it's true. The whole point of std::chrono and std:random is that they are cross-platform. May be, you don't care for anything non-Linux, but I certainly do. |
Keith Thompson <Keith.S.Thompson+u@gmail.com>: Mar 08 12:28PM -0800 >> and >> defining it would require runtime checks. > I guess you meant to write, "detecting it", not "defining it". I meant "defining it", as in making the behavior defined rather than undefined. > Defining signed overflow as wrap-around requires no runtime checks, > now that C++ integers are guaranteed two's complement. Probably true. Two's complement representation doesn't necessarily imply two's complement behavior on overflow, but that's probably the default behavior on most platforms. > Some optimization opportunities would be lost, but maybe others gained. The only virtue of defining signed overflow as two's complement wraparound is that it's convenient for the implementation. For users, it would provide consistency, but having INT_MAX+1 yield INT_MIN is not likely to be *useful*. If you want the language to define the behavior, there are a number of options. I wasn't assuming wraparound. (Throwing an exception is another possibility.) -- Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com Working, but not speaking, for XCOM Labs void Void(void) { Void(); } /* The recursive call of the void */ |
Michael S <already5chosen@yahoo.com>: Mar 08 12:48PM -0800 On Wednesday, March 8, 2023 at 10:28:30 PM UTC+2, Keith Thompson wrote: > wraparound is that it's convenient for the implementation. For users, > it would provide consistency, but having INT_MAX+1 yield INT_MIN is not > likely to be *useful*. My favorite example of usefulness of wrapping signed overflow behavior is CIC (a.k.a. Hogenauer) interpolation and decimation filters. |
Keith Thompson <Keith.S.Thompson+u@gmail.com>: Mar 08 12:59PM -0800 > are some, but I'd be surprised it were as many as half. > Just one example: Signed integer overflow has undefined behavior, and > defining it would require runtime checks. Perhaps it would have been better if I hadn't provided an example. Nothing wrong with talking about signed integer overflow, but it wasn't what I intended to focus on. Öö Tiib speculated that about half of the cases of undefined behavior could be replaced by "program is ill formed" (detectable at compile time) or "std::terminate is called" (detectable at run time). I'm sure that *some* cases of undefined behavior could be made not-undefined, but I'm skeptical that as many as half could be. (Counting cases of UB is tricky, especially given the cases that are undefined by omission.) -- Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com Working, but not speaking, for XCOM Labs void Void(void) { Void(); } /* The recursive call of the void */ |
"Alf P. Steinbach" <alf.p.steinbach@gmail.com>: Mar 08 10:34PM +0100 On 2023-03-08 8:10 PM, James Kuyper wrote: > behavior of signed integer overflow, then on platforms where the defined > behavior was not the same as that which would naturally occur, run-time > checks would be required to change the behavior. Can you give a concrete (even if hypothetical) example of what you mean? - Alf |
"Alf P. Steinbach" <alf.p.steinbach@gmail.com>: Mar 08 10:40PM +0100 On 2023-03-08 9:48 PM, Michael S wrote: >> likely to be *useful*. > My favorite example of usefulness of wrapping signed overflow behavior > is CIC (a.k.a. Hogenauer) interpolation and decimation filters. In Windows, the millisecond resolution `GetTickCount()` function wraps every 49.7 days. Happily the result is an unsigned type. So, as long as the time between two invocations is less than 49 days, one can simply subtract the last from the first in order to find elapsed time. With signed overflow defined as wrapping that func could have had signed type return value, so as to not cause inadvertent wrapping problems in comparisons and arithmetic involving negative signed type values. So it's a bit about safety, of being able to choose signed type freely. - Alf |
Keith Thompson <Keith.S.Thompson+u@gmail.com>: Mar 08 02:29PM -0800 >> behavior was not the same as that which would naturally occur, run-time >> checks would be required to change the behavior. > Can you give a concrete (even if hypothetical) example of what you mean? For example, a future C++ standard might specify that signed integer overflow throws a language-defined exception, or it might require saturation (so INT_MAX + 1 == INT_MAX). If the target hardware doesn't support that in some way, then checks have to be added. If the standard defined signed integer overflow as two's-complement wraparound (INT_MAX + 1 == INT_MIN), additional checks would not be required on most target systems (perhaps all current ones). I didn't have that specific definition in mind. Or it might define out-of-bounds array indexing (for plain C-like arrays) to wrap around, so that given `int a[10];` the expression `a[15]` or `a[-5]` would be equivalent to `a[5]`. Or it could require an exception to be thrown. Ada defines signed integer overflow and out-of-bounds indexing to raise an exception, so there is precedent. Both require the compiler to insert run-time checks, which can be removed during optimization if the compiler can prove that the error will never occur. And there are mechanisms to suppress the checks; if an exception would have been raised but the check is suppressed, the behavior is undefined (Ada calls it "erroneous execution"). Again, I didn't intend to concentrate on the case of signed integer overflow. My question was about which cases of undefined behavior could be made into defined behavior without adding runtime checks. -- Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com Working, but not speaking, for XCOM Labs void Void(void) { Void(); } /* The recursive call of the void */ |
James Kuyper <jameskuyper@alumni.caltech.edu>: Mar 08 06:11PM -0500 On 3/8/23 16:34, Alf P. Steinbach wrote: > On 2023-03-08 8:10 PM, James Kuyper wrote: ... >> behavior was not the same as that which would naturally occur, run-time >> checks would be required to change the behavior. > Can you give a concrete (even if hypothetical) example of what you mean? David has already done so. The committee could define the behavior as wrapping, in a fashion compatible with 2's complement behavior. In that case, run-time checks would required on any platform where that wasn't the native behavior - a small number of platforms, to be sure, but they do exist. However, as David pointed out, wrapping is the most useless possible behavior on signed overflow - it almost never gives a useful result. Signed overflow almost always is the result of an error of some kind, and should be treated as such. If the committee were, for example, to choose to define the behavior as calling std::terminate(), it would be more useful, but that would require run-time checks on virtually every existing system. |
Andrey Tarasevich <andreytarasevich@hotmail.com>: Mar 08 02:55PM -0800 >> It has none of information at all. The throw can be anywhere far up > Of course it has the information. It knows whats been thrown so it knows > if it can be captured in a structure binding. No, it doesn't. Exception throwing and catching is a run-time mechanism that cannot be fully analyzed at compile time in any reasonable sense of the word. So, no, the compiler _does_ _not_ have that information. > How does it know how to > set a binding from the return value of a function then? Easy. Because it fully knows the exact return type at compile time. >> of whatever (struct {? a, ? b;} , std::array<?,2>, std::tuple<?,?>, >> std::pair<?, ?>, etc.) structurally by current language rules? > You could use the same argument for structured bindings anywhere. Nope. Structured bindings in C++ allowed only where the specific type of the right-hand side is easily and immediately known at compile time. Exceptions do not even remotely fit this description. -- Best regards, Andrey |
Frederick Virchanza Gotham <cauldwell.thomas@gmail.com>: Mar 08 02:46PM -0800 On Wednesday, March 8, 2023, Alf P. Steinbach wrote: > bytes of the loaded image of the executable. > The start address of that image is available from `GetModuleHandle(0)`. > Happy hacking! :) Hacking alone won't cut the mustard on this occasion, I need divine inspiration. ...so I went to a life drawing class and wrote poems as the loader trying to resolve symbols: http://www.virjacode.com/download/hack_no_mustard.jpg |
Andrey Tarasevich <andreytarasevich@hotmail.com>: Mar 08 01:08PM -0800 On 03/08/23 10:29 AM, Pawel Por wrote: >>> I expect the Dog::Dog(Dog&&) to be called (sorry for confusion) >> But it _is_ called. Here's the output I get from your code > It is the std::move that forces the move constructor to be called. Precisely. Exactly as it should be. A _named_ reference is always an lvalue. If you want to call a move constructor on that reference, you have "unname" that reference. That's exactly what `std::move` does. > For me it looks like the argument is passed by lvalue reference to the MyList<T>::push_front(T&&) function. I still don't understand what you are trying to say here. On the receiving side (i.e. inside the function), there's no tangible difference between an argument passed by lvalue reference and an argument passed by rvalue reference. I don't understand how you managed to differentiate between the two. > I expect the Dog's move constructor to be called when passing an argument to MyList<T>::push_front(T&&) This does not make any sense at all. Argument of `push_front` is a direct-bound reference. Direct binding of a reference is just... binding a reference, nothing more. It never calls any constructors. It never does anything more than just binding of a reference. -- Best regards, Andrey |
Andrey Tarasevich <andreytarasevich@hotmail.com>: Mar 08 02:40PM -0800 On 03/08/23 1:08 PM, Andrey Tarasevich wrote: > A _named_ reference is always an lvalue. If you want to call a move > constructor on that reference, you have "unname" that reference. That's > exactly what `std::move` does. To clarify this a bit: `std::move` does not call any constructors. And `std::move` does not "force" any constructors to be called. All it does is it "unnames" a reference, i.e. it turns an lvalue into an xvalue. Everything else is a completely separate consequence of that, which happens later, _after_ `std::move`. Overload resolution sees an xvalue argument and chooses move constructor for this initialization. -- Best regards, Andrey |
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page. To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
No comments:
Post a Comment