- Is this undefined behavior? - 11 Updates
- HELP: Need good reference book on C++ - 2 Updates
- "C++20: The Unspoken Features" By Michele Caini - 2 Updates
- Augments and variable length data forms - 2 Updates
- [OT] Re: Saint Paul, Minnesota user group - 1 Update
- Fake switch or fake loop only to break - 1 Update
- [Jesus Loves You] Tag for filtering - 2 Updates
- having the same method but with a different argument data type - 2 Updates
- Prick - 1 Update
- ::errno - 1 Update
Scott Newman <scott69@gmail.com>: Jun 16 05:12PM +0200 Am 15.06.2020 um 09:03 schrieb Chris M. Thomasson: > return reinterpret_cast<char*>(this + 1); > } > }; Don't care for the spec. It works with any compiler and it will work with any compiler that will ever exist. |
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jun 17 12:24AM +0100 On Tue, 16 Jun 2020 16:11:31 -0700 > So, basically, I need to use placement new and explicit dtor via > calling the dtor ~Type(). Then it becomes a "real object" in C++. I > thought that POD would be different in a sense. Yes, although you don't actually need to call the destructor because your types are trivial. But there are other issues with your code which I have alluded to in other posts. I should use 'new unsigned char[...]' instead of std::malloc, placement new your 'header' struct into it and (as you do at present) cast the buffer part to char* if you really want char* instead of unsigned char* for the buffer. As I have indicated in those posts I think that cast is valid but you never know with C++17/20: if the committee don't understand the rules who are we to say. As I have also mentioned in other posts I agree with your sentiments about PODs/trivial types. That seems to me to be another fail in the standard. It ought to be valid in my view, but it isn't. |
Scott Newman <scott69@gmail.com>: Jun 17 09:06AM +0200 >> Not in this case. > What do you mean? The compiler is *always* allowed to do whatever it wants > if something is UB. There's no UB with what Chris does initially. |
Manfred <noname@add.invalid>: Jun 17 03:27PM +0200 On 6/17/2020 12:39 AM, Chris M. Thomasson wrote: >> Would would one need to cast the return value of malloc to (X*)? > Why would one need to cast the return value? void* can do it as is, > right? In pure C... In C yes, in C++ a type cast is required. A static_cast would suffice. This is why in my other posts I wonder why such a type cast could not be enough (at least for PODs) to overcome the issue about object creation and lifetime that is described in the proposal. Instead of going down some contrived path like requiring malloc to "look into the future" and such. |
Manfred <noname@add.invalid>: Jun 17 03:35PM +0200 On 6/17/2020 1:11 AM, Chris M. Thomasson wrote: > Touche! So, basically, I need to use placement new and explicit dtor via > calling the dtor ~Type(). Then it becomes a "real object" in C++. I > thought that POD would be different in a sense. If you look at the quote from Bjarne's "The C++ Programming Language" that I posted earlier you see that he himself does not require using placement new for malloc on a type with no constructor like this. Apparently, for some reason, the standard landed somewhere else. |
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jun 15 04:04PM -0700 On 6/15/2020 3:52 PM, Chris M. Thomasson wrote: >> to over-engineer it if you never intend to use it in a larger program. > raii would not hurt here, imagine that the code is as it is. Well, we > can wrap it up. Imvho, its a nice convenient feature of C++. For some reason this reminds me of some of my older memory allocators where the header was aligned on a large boundary. I could do it two ways. One was round down to get at the header, and another experiment rounded down then subtracted the size of the header. Take a cache line allocator, if the header fits in a cache line, then it can be the first element in an array of lines. |
Scott Newman <scott69@gmail.com>: Jun 15 07:42PM +0200 > (assuming a non-empty vector). > The latter form will abort the program with some existing C++ > implementations, so it's not only a formal difference. That's not what we were discussing. It's just this: > return reinterpret_cast<char*>(this) + sizeof(*this); vs. > return reinterpret_cast<char*>(this + 1); Even if you use C-style casts in the latter case there won't be ever any implementation which would misbehave here. Your code-experiments are esoterics. |
James Kuyper <jameskuyper@alumni.caltech.edu>: Jun 21 01:09AM -0400 On 6/20/20 11:50 AM, Manfred wrote: > I am no expert on this point, rather I am curious: does the standard say > something explicit (if so, a pointer would be appreciated) about > converting iterations into a recursive function, ... No. > ... or is this "permission" > merely based on the lack of prohibition under the umbrella of the "as > if" rule? In the context of C or C++, "observable behavior" is a special piece of jargon defined by the relevant standard - that definition is not "behavior which is observable". When that phrase is used by someone who understands that definition, it is always in reference to the as-if rule, because the relevant standard uses that term only in the context of that rule. > time) than iterative ones, so the source code may have well defined > behavior in the iterative form, but run into UB in the recursive form > due to resource exhaustion. A program that exceeds an implementation's limit may not be successfully processed (See 4.1p2 and Annex B). However, the standard sets no minimum value on any of those limits (the values shown in Annex B are merely recommendations and guidelines). It also fails to impose any limits on how much memory any particular piece of code may require. Therefore, any program might exceed those limits, whether a loop is handled iteratively or recursively. It's entirely a matter of QoI whether an implementation decides to implement any code in any manner that doesn't exceed it's own limits. During one memorable discussion, the person I was talking with was actually complained about the supposed "misinterpretation" of the standard as allowing an optimization that greatly reduced the likelihood of resource exhaustion (though he never acknowledged the truth of the claim that it would have had that effect - he just ignored that assertion completely). >> observable behavior (in this case, none). It would be hard to convince >> anybody to use such a compiler - but that's what QoI is about. > Alf mentioned resource usage, not just time. My comment was about all such resources, I just used time as an example. > ... In this case running out of > stack space is a typical risk to be managed, which does not apply to > iterative loops. Any program, even "int main(void) {}", may be implemented in such a fashion as to exceed an implementation's resource limits. It's only a matter of QoI whether or not that actually happens. |
Juha Nieminen <nospam@thanks.invalid>: Jun 21 01:54PM > you won't find malloc() or free() in kernel code you wouldn't find any of the > STL or shared pointers or virtual functions or frankly anything that makes C++ > useful. Actually many of the utilities provided by the C++ standard library can be very useful even if you are required to avoid dynamic memory allocation. For example, std::unique_ptr is *not* restricted to simply manage dynamically allocated memory for you. It can perfectly well (and relatively easily) be used to manage other resources as well. For example, you can use a `std::unique_ptr` to automatically close a FILE* that you have std::fopen()'ed, when the pointer goes out of scope. No dynamic memory allocation involved here (unless std::fopen() itself does). Also, in fact, all the dynamic data containers provided by the standard library can be used without them calling the default 'new'. You can provide them with your own allocator, if you so wish. This allocator could manage memory in a static array, for example. There may be situations where this could be useful. There's also, of course, a huge amount of utilities in the standard library that are not related to dynamic memory allocation, such as the utilities in <algorithm> and many of the other headers. It is perfectly possible to get a lot of benefit from C++ without having to go to dynamic memory allocation and virtual functions. |
"Öö Tiib" <ootiib@hot.ee>: Jun 21 09:59AM -0700 On Sunday, 21 June 2020 16:54:43 UTC+3, Juha Nieminen wrote: > a FILE* that you have std::fopen()'ed, when the pointer goes out > of scope. No dynamic memory allocation involved here (unless > std::fopen() itself does). That is generally good example but it coincides with one thing that most programs handle lousily. If file was fopened for writing then the very rare cases when fclose can fail are likely quite important to handle properly. Unhandled failure may mean that users did lose their data. That problem does not magically disappear when fclose is abstracted away into deleter of unique_ptr. |
Jorgen Grahn <grahn+nntp@snipabacken.se>: Jun 21 06:02PM On Sun, 2020-06-21, Öö Tiib wrote: > On Sunday, 21 June 2020 16:54:43 UTC+3, Juha Nieminen wrote: ... > to handle properly. Unhandled failure may mean that users did lose > their data. That problem does not magically disappear when > fclose is abstracted away into deleter of unique_ptr. And it doesn't disappear if you use a std::fstream. (Not that I always handle the error myself.) /Jorgen -- // Jorgen Grahn <grahn@ Oo o. . . \X/ snipabacken.se> O o . |
mehrdad <m-ghassempoory@ntlworld.com>: Jun 21 06:05PM +0100 I used to be a programmer. I had a good working knowledge of C++, but I have not been programming for the last 10-12 years. In my retirement I decided to catch up with the changes in the language. I need a good reference book on C++ which covers everything (preferably) up to C++ 17. I do have the C++17 book by N.M. Josuttis, but it seems to be like an update document rather than a reference book. What I DO NOT need is a book that tries to teach programming using C++. Any ideas? |
"Öö Tiib" <ootiib@hot.ee>: Jun 21 10:38AM -0700 On Sunday, 21 June 2020 20:06:00 UTC+3, mehrdad wrote: > I do have the C++17 book by N.M. Josuttis, but it seems to be like an > update document rather than a reference book. What I DO NOT need is a > book that tries to teach programming using C++. Any ideas? To get update what C++11/C++14 added perhaps buy that pdf from Scott Meyers <https://www.artima.com/shop/overview_of_the_new_cpp> Update to C++17 you already have you said. About reference I think <https://en.cppreference.com/w/> is really good reference (when there is internet access). Most of the good books try to teach deeper tricks how to use one or other feature of C++ conveniently, but that you said you do not need in full caps. |
woodbrian77@gmail.com: Jun 20 04:56PM -0700 On Thursday, June 18, 2020 at 9:02:31 PM UTC-5, Lynn McGuire wrote: > published." > "The C++ community is really excited about C++20. It looks like a > groundbreaking update similar to C++11. I like span, but have yet to determine how coroutines would be helpful to me. I'm going to stick with 2017 C++ for my open source code for now. Brian Ebenezer Enterprises - Enjoying programming again. https://webEbenezer.net |
Juha Nieminen <nospam@thanks.invalid>: Jun 21 02:08PM > I like span, but have yet to determine how coroutines > would be helpful to me. I'm going to stick with 2017 > C++ for my open source code for now. Coroutines are a very hard beast to understand, even for a very experienced programmers. Both how they work, how they are used, and what they are useful for, can be really obscure (and sometimes hard to explain). Here's one practical real-life example of where coroutines can be useful: Suppose you have a compressed file format decompressor. Quite often you don't want to decompress the entire input file at once into RAM, because the decompressed data can be enormous in size (too large to even fit in RAM at once), and thus you want to decompress and process it in chunks. For example, you might want to decompress and hande 1 MB of (decompressed) data at a time. You might even want, for efficiency, to have a 1 MB static C-style array into which you decompress the data to to be handled. In other words, decompress data from the input file into the 1 MB array, and when the array gets full, handle that data, and then continue decompressing more data into the same array, starting from the beginning. But this poses a problem: Most likely when you are decompressing the data from the input file, it won't come in nice 1 MB chunks. At some point something in the compressed input will probably produce a chunk of data that would overflow the array. It won't fit in the remaining space in the array. In other words, you would need to stop decompressing the current compressed block at the exact moment when the 1 MB array gets full, call the routine that consumes the array, and then continue from where you left off, writing the rest of the decompressed block to the beginning of the array. In order to be able to do this, you need to store the state of the decompressor in full. It needs to be able to stop, jump somewhere else, and then continue exactly from where it stopped. This is certainly possible with current C++, but it can become complicated. You need to not only store all the state of the decompressor inside something (usually a class or struct), but to also design your decompressor code so that it can continue exactly from where it stopped (which, depending on the complexity of the compressed file format, can become quite complicated). This is where coroutines step in to help, as they automatize the vast majority of that: At any point in your decompressor code you can "yield", which jumps back to whatever called the decompressor, and when that's done, it can return to the exact point where you yielded, and the decompressor can continue as if nothing had happened. The entire state at that point in the code is restored automatically. This simplifies *significantly* this kind of situation, requiring the programmer to do significantly less work to achieve this. The state is stored automatically, and the routine can easily continue from wherever there's a "yield", no matter where it is in the code, or how many yield points there may be. Even if there's a dozen points in the decompressor where the target buffer may get full, it doesn't matter. The next time the execution returns to it, it will continue from that point. |
Bart <bc@freeuk.com>: Jun 13 12:01PM +0100 > variable length nature of the flexible structure. The compiler > would inject code to compute properly based on the runtime obser- > vation of the dynamics of the particular instance. This for a new language? There are a few other approaches that might be better. But first, what exactly is the structure above - is the char data held directly inside the struct? That's going to be awkward where you have two of them. How does it work exactly: do first/lastNameLength need to be determined at the same time, and struct size calculated for both (sizeof(int)*2 + firstlength+lastlength, +2 if zero-terminated), and then there are fixed? How do the lengths get into the struct? What happens when you pass a var_char to a function, does it somehow include its length, or do you need the length passed explicitly? Also, how does an access such as X.lastNameLength or X.lastname know the offsets of those members, if they will depend on the X.firstNameLength? If you say the compiler will sort it out, then I can gave a dozen examples where it will have its work cut out to determine not only how to do something, but what it even means. I mentioned other ways, but since this is C++, why not just use its 'string' type? It includes its length, the two strings can be created at different times, and there's no extra housekeeping for the lengths. But the string data will be on the heap. If it's necessary for the string data to be part of the struct, how important is it that the struct is the exact size of the combined strings? Having a fixed capacity is much easier, if these names will be of a limited length. There are also schemes where you allocate a fixed size in-place string, but provide a mechanism for longer strings too, which are stored elsewhere via a pointer. (Something like this is done in COFF files' symbol tables.) > Chris Thomasson, I wanted to get your input. I forgot this bit. Please ignore the above... |
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jun 14 05:53PM -0700 > { > augment SList* data; // Changes void* to SList* > }; [...] At first glance maybe something like: ________________________ #include <iostream> struct SWhatever { void* data; }; struct SFoo { SFoo(int data_) : data(data_) { std::cout << this << "::SFoo::SFoo(" << data << ")\n"; } ~SFoo() { std::cout << this << "::SFoo::~SFoo(" << data << ")\n"; } int data; void bar() { std::cout << this << "::SFoo::bar(" << data << ")\n"; } }; struct SWhateverShim { SWhatever whatever; SWhateverShim(SWhatever const& whatever_) : whatever(whatever_) {} SFoo* get() const { return static_cast<SFoo*>(whatever.data); } SFoo* operator ->() const { return get(); } }; int main() { { SWhatever wever; wever.data = reinterpret_cast<void*>(new SFoo(123)); SWhateverShim shim(wever); shim->bar(); delete shim.get(); } return 0; } ________________________ Is that helpful at all Rick? |
Cholo Lennon <chololennon@hotmail.com>: Jun 16 04:16PM -0300 > Wuhan virus and checking temperatures. I'm happy > to report that I don't have any symptoms at this > time and hope to keep it that way. "Wuham virus"? :-O the virus has a name. Maybe, using your bias, we should use "the state where police kill non-white people" instead of Minnesota, or even better... Killersota... (yes, I have plenty of biased/stupid "names") -- Cholo Lennon Bs.As. ARG |
David Brown <david.brown@hesbynett.no>: Jun 16 09:14AM +0200 On 15/06/2020 23:44, Frederick Gotham wrote: > } > } > } How about : if (cond1 && cond2 && cond3 && cond4) { DoSomething(); } > if ( !cond3 ) return; > if ( !cond4 ) return; > Do Something(); That's good for some kind of tests. In particular, tests on the parameters of a function followed by early exits are a popular style. (Not everyone likes it - some people feel functions should only ever have one exit.) There is no single "best" method - it will depend on the code as well as any style preferences or requirements for the project and team. > Do Something(); > Label_At_End: > ; That's also a common idiom. It's not one I like - I don't find use for gotos in my own code. But some people do. > if ( !cond4 ) break; > Do Something(); > } That would be a code review fail right away - it's an unnecessarily ugly hack and an abuse of switch. Your "do {} while (false);" is much less bad (omitting the "default:"). > Do Something(); > } while (false); > Does anyone else use fake switches and fake loops like this just to exploit the 'break' keyword? I've never felt the need. |
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Jun 13 02:26AM +0100 > always praying for them, always helping them, showing them the love > and patience of God alive inside you. > You cast things upon me which are not me or mine. You are a bigot; and based on what you have just said: a two faced bigot, the worst kind. /Flibble -- "Snakes didn't evolve, instead talking snakes with legs changed into snakes." - Rick C. Hodgin "You won't burn in hell. But be nice anyway." – Ricky Gervais "I see Atheists are fighting and killing each other again, over who doesn't believe in any God the most. Oh, no..wait.. that never happens." – Ricky Gervais "Suppose it's all true, and you walk up to the pearly gates, and are confronted by God," Byrne asked on his show The Meaning of Life. "What will Stephen Fry say to him, her, or it?" "I'd say, bone cancer in children? What's that about?" Fry replied. "How dare you? How dare you create a world to which there is such misery that is not our fault. It's not right, it's utterly, utterly evil." "Why should I respect a capricious, mean-minded, stupid God who creates a world that is so full of injustice and pain. That's what I would say." |
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Jun 13 01:49AM +0100 > same: A hardware and software stack written from scratch, given over > to God explicitly, through prayer and sanctification. > CPU, OS kernel, drivers, apps. A usable system for daily use. Yeah, Terry would be proud. Two peas in a pod, growing in a field off Bigot Lane. /Flibble -- "Snakes didn't evolve, instead talking snakes with legs changed into snakes." - Rick C. Hodgin "You won't burn in hell. But be nice anyway." – Ricky Gervais "I see Atheists are fighting and killing each other again, over who doesn't believe in any God the most. Oh, no..wait.. that never happens." – Ricky Gervais "Suppose it's all true, and you walk up to the pearly gates, and are confronted by God," Byrne asked on his show The Meaning of Life. "What will Stephen Fry say to him, her, or it?" "I'd say, bone cancer in children? What's that about?" Fry replied. "How dare you? How dare you create a world to which there is such misery that is not our fault. It's not right, it's utterly, utterly evil." "Why should I respect a capricious, mean-minded, stupid God who creates a world that is so full of injustice and pain. That's what I would say." |
Bonita Montero <Bonita.Montero@gmail.com>: Jun 16 09:02PM +0200 >> (and the other data types) into a single method ? > Try std::variant<...>. > But that's less performant. How about this: #include <variant> #include <vector> #include <string> using namespace std; struct DataItem { int aAvalueInt; double aValueDouble; vector<int> aValueIntArray; vector<string> aValueStringArray; }; using var_t = variant<int, double, vector<int>, vector<string>>; void f( var_t &var, DataItem &di ) { enum { INT, DOUBLE, VEC_INT, VEC_STR }; switch( var.index() ) { case INT: di.aAvalueInt = get<INT>( var ); break; case DOUBLE: di.aValueDouble = get<DOUBLE>( var ); break; case VEC_INT: di.aValueIntArray = get<VEC_INT>( var ); break; case VEC_STR: di.aValueStringArray = get<VEC_STR>( var ); break; } } Compile it with C++17 enabled. |
Lynn McGuire <lynnmcguire5@gmail.com>: Jun 16 01:39PM -0500 Hi, Is there a way to have the same method but with a different argument data type for a single argument ? For instance, the following methods that I have greatly simplified: class DataItem : public ObjPtr { int aAvalueInt; double aValueDouble; std::vector <int> aValueIntArray; std::vector <std::string> aValueStringArray; } ObjPtr * DataItem::store(int aValue) { // do some stuff aValueInt = aValue; // do some stuff return this; } ObjPtr * DataItem::store (double aValue) { // do some stuff aValueDouble = aValue; // do some stuff return this; } ObjPtr * DataItem::store (std::vector <int> aValue) { // do some stuff aValueIntArray = aValue; // do some stuff return this; } ObjPtr * DataItem::store (std::vector <std::string> aValue) { // do some stuff aValueStringArray = aValue; // do some stuff return this; } Is there some way to combine all of these methods (and the other data types) into a single method ? Thanks ! Lynn |
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jun 14 05:34PM -0700 On 6/14/2020 4:58 PM, Mr Flibble wrote: > Apparently you shouldn't prick your sausages. I've been doing it wrong > all these years. If you prick them, then all of the juices will most likely leak out during the cooking process: they will probably dry out. |
Keith Thompson <Keith.S.Thompson+u@gmail.com>: Jun 13 11:16PM -0700 > Keith Thompson wrote: [...] > more like 1988 if you believe to Wikipedia. I recall first learning about it > circa 1993. Back then, any reference to UNIX would elicit a quip "which UNIX?" > from one shrewd friend of mine. In fact Wikipedia is where I got that information. I blame the standard that puts the '8' and '9' keys next to each other on my keyboard. (Yes, I meant to type 1988.) -- Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com Working, but not speaking, for Philips Healthcare void Void(void) { Void(); } /* The recursive call of the void */ |
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