- Google Groups (was Re: differential reference counting...) - 5 Updates
- good reference on threads - 1 Update
- Why does vector::reserve() not grow exponentially ? - 13 Updates
- Is this really necessary - 1 Update
- Overloading classes with concepts - 2 Updates
- Windows-API- / lambda- / TLS-trick - 3 Updates
| David Brown <david.brown@hesbynett.no>: Jun 10 09:44AM +0200 On 09/06/2021 23:10, Real Troll wrote: > On 09/06/2021 20:23, Öö Tiib wrote: >> Censoring Internet. :D Smells like North Korea. Did U.S. have Communist >> coup d'état ? <snip> Please don't try to start political wars here. This is an international group, not an American group, and it is for C++, not a politics group. Comments about the group's removal from Google Groups, and what (if anything) can be done to reverse that are on topic. General discussions about censorship, for or against, are not. If you want to talk politics in a technical group, go to sci.electronics.design. It is a discussion group for politics, religion, etc., with an occasional thread on electronics. But put on your asbestos underwear first - some of the regulars there are really unpleasant characters. |
| Keith Thompson <Keith.S.Thompson+u@gmail.com>: Jun 10 07:56AM -0700 > <snip> > Please don't try to start political wars here. This is an international > group, not an American group, and it is for C++, not a politics group. The name "Real Troll" should be a clue that this person is not going to pay attention to complaints. The solution is left as an exercise for your killfile. [snip] -- 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 */ |
| Real Troll <real.troll@trolls.com>: Jun 10 05:13PM On 10/06/2021 08:44, David Brown wrote: > <snip> > Please don't try to start political wars here. This is an international > group, not an American group, and it is for C++, not a politics group. Please don't attribute anything to people when they didn't post what you attributed here. Attention to detail is a must in these newsgroups. If you want to carelessly accuse people than there are other newsgroups such as " misc.survivalism ". |
| Real Troll <real.troll@trolls.com>: Jun 10 05:27PM On 10/06/2021 15:56, Keith Thompson wrote: > The solution is left as an exercise for > your killfile. Can you kill file me too, please? I promise to offend you. All drama queens find me offensive. |
| "Öö Tiib" <ootiib@hot.ee>: Jun 10 03:17PM -0700 On Thursday, 10 June 2021 at 10:44:43 UTC+3, David Brown wrote: > religion, etc., with an occasional thread on electronics. But put on > your asbestos underwear first - some of the regulars there are really > unpleasant characters. Estonia was still part of Communist country when I first reached Usenet using modem, phone, and calling to number of KTH Royal Institute of Technology in Sweden that also involved some tricks that weren't legal by local legislature. So it is symbolic for me and attempts to censor it are also symbolic for me and discussing it is not Real Troll's fault but mine. |
| Lynn McGuire <lynnmcguire5@gmail.com>: Jun 10 04:59PM -0500 Is there a good reference on threads ? I would like to delegate the writing of our binary file to a background thread if possible. Our Win32 Windows desktop program is mostly MFC with about 450,000 lines of C++ code. I do suspect that this is not doable, due to the nature of the data being used for dialogs and such. Thanks, Lynn |
| Bonita Montero <Bonita.Montero@gmail.com>: Jun 10 12:18PM +0200 vector is specified to have a amortized constant overhead for inserting new elements. Because of that ::emplace_back() et al grow the capacity exponentiallly if necessarsy (2x for libstdc++, 1.5x for MSVC). But why does this not apply for vector::reserve() ? It could simply handle the reservations in a way that the increase which should be made is below the next exponential step, the given size doesn't count but the next anticipated step. That would be the most logical way for me to handle this issue. |
| Bo Persson <bo@bo-persson.se>: Jun 10 01:21PM +0200 On 2021-06-10 at 12:18, Bonita Montero wrote: > the next exponential step, the given size doesn't count but the next > anticipated step. That would be the most logical way for me to handle > this issue. I believe the idea is that you use reserve() when you have a good idea of what the final size is likely to be. I wouldn't want the implementation to allocate 50-100% additional space just in case the vector would continue to grow. Presumably, when calling reserve() I know that it will not. |
| Paavo Helde <myfirstname@osa.pri.ee>: Jun 10 02:37PM +0300 10.06.2021 13:18 Bonita Montero kirjutas: > new elements. Because of that ::emplace_back() et al grow the capacity > exponentiallly if necessarsy (2x for libstdc++, 1.5x for MSVC). But why > does this not apply for vector::reserve() ? Because reserve() is only needed for the case when the default exponential growth is not appropriate for some reason. If so, only the programmer can know how it's not appropriate and how the buffer should grow. So there would be little point to double-guess it and do something else automatically. > reservations in a way that the increase which should be made is below > the next exponential step, the given size doesn't count but the next > anticipated step. I'm not sure I understand this sentence. > That would be the most logical way for me to handle > this issue. What issue? |
| Bonita Montero <Bonita.Montero@gmail.com>: Jun 10 03:44PM +0200 > Because reserve() is only needed for the case when the default > exponential growth is not appropriate for some reason. ... The standard says: "After reserve(), capacity() is _greater or equal_ to the argumentof reserve if reallocation happens ..." So the standard gives the vector-implementation the freedom to grow beyond the size you supply with resize(). I think that's because the vector has to satisfy the amortized constant inserts. |
| David Brown <david.brown@hesbynett.no>: Jun 10 04:39PM +0200 On 10/06/2021 15:44, Bonita Montero wrote: > So the standard gives the vector-implementation the freedom to grow > beyond the size you supply with resize(). I think that's because the > vector has to satisfy the amortized constant inserts. No, that would make no sense. It is simply to allow the implementation to round up the capacity a bit if that suits the memory allocator - perhaps it allocates in lumps of 4K, or cache aligned sizes, or something else that means when you ask for space for 19 elements it might give you 24 elements. You use "reserve" when you know how your vector will grow, because it is more efficient to jump to the right size than grow exponentially. If you know you are going to store 1000 elements, you reserve space for 1000 (and don't care if the implementation sets the actual capacity to 1024). That is far faster than starting with 1 element and doubling 10 times, or scaling by 1.5 in 17 steps. |
| Bonita Montero <Bonita.Montero@gmail.com>: Jun 10 04:47PM +0200 > No, that would make no sense. It is simply to allow the implementation > to round up the capacity a bit if that suits the memory allocator - ... There are no rounding memory-allocators. You say the allocator you want size = n * sizeof(type) memory and it gives you the memory and the allocator-API doesn't give you the opportunity to get the size actually allocated. So you're wrong. |
| Bonita Montero <Bonita.Montero@gmail.com>: Jun 10 04:51PM +0200 That's the API: https://en.cppreference.com/w/cpp/memory/allocator/allocate Where do you get the opportunity to get the size of the actually logically or physically allocated memory ? |
| MrSpook_sw@08_cl170xu11o4f8xcg45.co.uk: Jun 10 03:25PM On Thu, 10 Jun 2021 16:39:13 +0200 >perhaps it allocates in lumps of 4K, or cache aligned sizes, or >something else that means when you ask for space for 19 elements it >might give you 24 elements. I always thought vector was a bit of a mess with reserve(), resize(), capacity() and size(). Having reserve() that allocates the array slots but not the objects in them so allowing a valid [] access into the reserved but uninitialised indexes which then gives indefined behaviour with non simple types is IMO something that should be flagged as Use With Extreme Caution. |
| Bonita Montero <Bonita.Montero@gmail.com>: Jun 10 06:18PM +0200 > not the objects in them so allowing a valid [] access into the reserved but > uninitialised indexes which then gives indefined behaviour with non simple > types is IMO something that should be flagged as Use With Extreme Caution. That's not what we're talking about. The discussion is about how much reserve() actually allocates, not whether you can access objects behind size() but within capacity(). |
| Paavo Helde <myfirstname@osa.pri.ee>: Jun 10 10:40PM +0300 > not the objects in them so allowing a valid [] access into the reserved but > uninitialised indexes which then gives indefined behaviour with non simple > types is IMO something that should be flagged as Use With Extreme Caution. Do you realize that calling reserve() and capacity() is fully optional? If you do not like them, just don't use these functions. And from where did you get the idea that accessing the vector beyond its size is valid for POD types? It's definitely UB and I bet there are debugging implementations which abort the program when they detect this (aborting the program is a perfect example of UB). |
| Bo Persson <bo@bo-persson.se>: Jun 10 10:00PM +0200 On 2021-06-10 at 16:47, Bonita Montero wrote: > want size = n * sizeof(type) memory and it gives you the memory and > the allocator-API doesn't give you the opportunity to get the size > actually allocated. So you're wrong. A standard library for a specific system will just *know* that the memory allocator is pooled and works in certain chunks. For example, if you ask for size = 1 * sizeof(char), you will never get a single byte. You will get 16 bytes. It is then just rational for reserve(1) to result in capacity == 16. |
| Bonita Montero <Bonita.Montero@gmail.com>: Jun 10 10:09PM +0200 > A standard library for a specific system will just *know* that the > memory allocator is pooled and works in certain chunks. This is the requirement for a container-compliant allocator: https://en.cppreference.com/w/cpp/named_req/Allocator Where's the interface that supplies the container the real size of an allocated memory-block ? |
| "Alf P. Steinbach" <alf.p.steinbach@gmail.com>: Jun 10 10:35PM +0200 On 10 Jun 2021 21:40, Paavo Helde wrote: > size is valid for POD types? It's definitely UB and I bet there are > debugging implementations which abort the program when they detect this > (aborting the program is a perfect example of UB). Depends what the guy meant. After a `.reserve` there is a guaranteed contiguous buffer of `.capacity` size. With a vector size of at least 1 one can obtain a raw pointer to it via `data`, and index that pointer. You'd need the legendary perverse implementation with phat pointers, to detect that. - Alf |
| Tim Rentsch <tr.17687@z991.linuxsc.com>: Jun 10 11:29AM -0700 > size_t variable or copying this memory range somewhere. At best you > could copy a tail of the DS segment and the head of the ES segment > somewhere, but why not vice versa? Yes, as a practical matter no actual C++ implementation is going to accommodate objects that cross a segment boundary. My question though was about what the C++ standard allows for pointers into a single struct object (of the contiguous variety). I know that C does allow pointer arithmetic for such pointers (ie, character pointers), but my efforts to discover whether the C++ standard allows it have not been successful. |
| Bonita Montero <Bonita.Montero@gmail.com>: Jun 10 06:45PM +0200 I can have multiple overloads of a function for multiple concept -types: #include <concepts> using namespace std; template<floating_point Fp> void f( Fp fp ) { } template<integral Int> void f( Int i ) { } But how can I do that with structs / classes - so I would have multiple specializations of a class for different concept-types. |
| Bonita Montero <Bonita.Montero@gmail.com>: Jun 10 06:49PM +0200 Oh, I got it: template<typename T> struct S { }; template<integral Int> struct S<Int> { }; template<floating_point Fp> struct S<Fp> { }; |
| Bonita Montero <Bonita.Montero@gmail.com>: Jun 10 04:31AM +0200 > Well, there's no such guarantee in the standard. I'm dealing with Windows-compilers, so the standard doesn't count. > But for 64-bit Windows programming you should be safe: 1 calling > convention to rule them all. With 32-bit Windows the calling-operator is individually compiled for each call if you have different calling-conventions. |
| Bonita Montero <Bonita.Montero@gmail.com>: Jun 10 04:47AM +0200 >> Well, there's no such guarantee in the standard. > I'm dealing with Windows-compilers, so the standard doesn't count. Here, test it yourself on Windows 32 Bit: #include <iostream> using namespace std; int main() { thread_local int volatile i = 0; auto lambda = []( int add ) { i += add; }; void (__stdcall *volatile fs)( int ) = lambda; void (__fastcall *volatile ff)( int ) = lambda; fs( 123 ); ff( 456 ); cout << (void *)fs << endl; cout << (void *)ff << endl; } The lambda-function is compiled twice here. |
| Bonita Montero <Bonita.Montero@gmail.com>: Jun 10 11:38AM +0200 > cout << (void *)ff << endl; > } > The lambda-function is compiled twice here. Unfortunately that doesn't work with clang-cl, the clang-variant that claims to be mostly MSVC-compatible. I found this incompati- bility documented from 2018 on the clang-devel mailinglist. I'm asking why this hasn't been fixed yet - compiling the lamdda with multiple calling-conventions shouldn't be a big deal. |
| 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