Thursday, December 13, 2018

Digest for comp.lang.c++@googlegroups.com - 25 updates in 4 topics

Lynn McGuire <lynnmcguire5@gmail.com>: Dec 12 06:56PM -0600

On 12/12/2018 2:48 PM, JiiPee wrote:
> when resizing to zero. So I guess its undefined what happens to capacity
> after deleting elements?
 
> Or any alternative good way implementing this?
 
There is std::array but you would have to implement your own add and
delete methods.
 
Lynn
leigh.v.johnston@googlemail.com: Dec 13 01:46AM -0800

On Thursday, December 13, 2018 at 12:56:44 AM UTC, Lynn McGuire wrote:
 
> There is std::array but you would have to implement your own add and
> delete methods.
 
> Lynn
 
std::array doesn't work as all its elements are CONSTRUCTED even if the array is LOGICALLY empty.
 
neolib::vecarray
 
/Leigh
"Chris M. Thomasson" <invalid_chris_thomasson@invalid.invalid>: Dec 13 01:59AM -0800


>> Lynn
 
> std::array doesn't work as all its elements are CONSTRUCTED even if the array is LOGICALLY empty.
 
> neolib::vecarray
 
;^)
Andrea Venturoli <ml.diespammer@netfence.it>: Dec 13 12:03PM +0100

On 12/12/18 11:46 PM, JiiPee wrote:
 
> but reserve would do re-allocation.
 
Only if newsize>capacity().
 
 
 
> So clear() would first delete me memory
 
No, you have it wrong here: it calls elements' destructors, but doesn't
free memory (and does not alter capacity()).
 
 
 
> and reserve would allocate again.
 
Again, only if you reserve() to a bigger size.
If you call reserve() with the old size, it does nothing.
 
 
 
> And this is what I would like to prevent...
 
Just reserve() as soon as the vector is created and be sure to never
insert/push_back more elements than you reserved for.
 
 
 
 
> I would like to keep the original allocated memory even
> after clear().
 
This is what always happens.
JiiPee <no@notvalid.com>: Dec 13 11:29AM

On 12/12/2018 23:23, Alf P. Steinbach wrote:
 
> Deleting items from a vector will not cause it to reallocate.
 
Are you sure? Because the standard says about clear():
"
 
/expression:/|a.clear()|
 
/return type:/|void|
/Assertion/note pre-/post-condition:/Destroys all elements in a.
Invalidates all references, pointers, and iterators referring to the
elements of a and may invalidate the past-the-end iterator.
 
/post:/a.empty() returns true.
 
/Complexity:/Linear.
 
"
 
So it does not mention anything about reallocation, so does this mean
its undefined whether reallocation happens or not? If it does not talk
about reallocation issue I would think thats compiler implementation
specific then? So up to compiler how they do it?
JiiPee <no@notvalid.com>: Dec 13 11:31AM

On 13/12/2018 11:03, Andrea Venturoli wrote:
> On 12/12/18 11:46 PM, JiiPee wrote:
 
>> but reserve would do re-allocation.
 
> Only if newsize>capacity().
 
Does standard promise this?
 
 
>> So clear() would first delete me memory
 
> No, you have it wrong here: it calls elements' destructors, but
> doesn't free memory (and does not alter capacity()).
 
but again, where in the standard it promises this:
 
/"expression:/|a.clear()|
 
/return type:/|void|
/Assertion/note pre-/post-condition:/Destroys all elements in a.
Invalidates all references, pointers, and iterators referring to the
elements of a and may invalidate the past-the-end iterator.
 
/post:/a.empty() returns true.
 
/Complexity:/Linear."
 
 
It does not seem to talk anything about this issue...so we dont know?
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Dec 13 01:03PM +0100

On 13.12.2018 12:29, JiiPee wrote:
> its undefined whether reallocation happens or not? If it does not talk
> about reallocation issue I would think thats compiler implementation
> specific then? So up to compiler how they do it?
 
Consider
 
const size_t x = sizeof( int );
 
The standard doesn't say that an invocation of sizeof shall not output
the message "Ha ha, you're foiled!".
 
But you can rely on no such message appearing, because the convention is
that what the standard doesn't explicitly (or sometimes implicitly)
allow, just isn't allowed.
 
By the way this is a nice illustration that Stack Overflow is now, for
some years, the largest Herb Schildt zone on the internets; information
that you can use to /find/ reliable information, or that you can /test/
yourself, but that you absolutely should not rely on directly by default
without at least reasoning about it, checking that it makes sense.
 
Namely, I reasoned that for best educational effect I should merely
point you in the direction of a search engine like Google's, but then
I'd best try it myself first, and then I ended up at the Stack Overflow
q/a <url:
https://stackoverflow.com/questions/6882799/does-clearing-a-vector-affect-its-capacity>,
which tells you that you can rely on it in practice but that "That isn't
mandated by the standard". Which is total bollocks. So much
disinformation and FUD. It pains me.
 
 
Cheers & hth.,
 
- Alf
Andrea Venturoli <ml.diespammer@netfence.it>: Dec 13 01:48PM +0100

On 12/13/18 12:31 PM, JiiPee wrote:
 
>>> but reserve would do re-allocation.
 
>> Only if newsize>capacity().
 
> Does standard promise this?
 
I don't have access to the standard, so I won't say so for sure.
 
All the "standard libraries" I've used work this way.
 
 
 
The closest I can get to the standard is:
https://en.cppreference.com/w/cpp/container/vector/clear
which says capacity() is unchaged.
 
There you'll also find a pointer to an interesting discussion.
If I had access to the standard, I could check the hypotheses myself,
but I believe them to stand.
Bo Persson <bop@gmb.dk>: Dec 13 02:00PM +0100

On 2018-12-13 12:31, JiiPee wrote:
 
> /post:/a.empty() returns true.
 
> /Complexity:/Linear."
 
> It does not seem to talk anything about this issue...so we dont know?
 
The guarantees are found in the description of reserve(). There it says:
 
"After reserve(), capacity() is greater or equal to the argument of
reserve if reallocation happens; and equal to the previous value of
capacity() otherwise."
 
and
 
"No reallocation shall take place during insertions that happen after a
call to reserve() until the time when an insertion would make the size
of the vector greater than the value of capacity()."
 
 
So, after a call to reserve() the clear() function is not allowed to
shrink the capacity.
Paavo Helde <myfirstname@osa.pri.ee>: Dec 13 03:33PM +0200

On 13.12.2018 15:00, Bo Persson wrote:
 
> "No reallocation shall take place during insertions that happen after a
> call to reserve() until the time when an insertion would make the size
> of the vector greater than the value of capacity()."
 
Note that this speaks of *insertions*, while clear() is not an insertion.
 
If this paragraph was meant to apply to other operations as well, it
should have been phrased something like that:
 
"No reallocation shall take place during further member function calls,
with the exception of shrink_to_fit(), ...
 
I'm not claiming that clear() is allowed to reallocate the buffer, just
pointing out this does not follow from this paragraph.
James Kuyper <jameskuyper@alumni.caltech.edu>: Dec 13 08:34AM -0500

On 12/13/18 07:03, Alf P. Steinbach wrote:
 
> But you can rely on no such message appearing, because the convention is
> that what the standard doesn't explicitly (or sometimes implicitly)
> allow, just isn't allowed.
 
As a general rule, any container member function for which the standard
says "Invalidates all references, pointers, and iterators referring to
the elements of a ..." implies that a reallocation is allowed - a
reallocation is the only thing that would necessitate invalidating them.
 
The standard's description of reserve() guarantees that "No reallocation
shall take place during insertions that happen after a call to reserve()
until the time when an insertion would make the size of the vector
greater than the value of capacity()." (23.3.6.3p6).
Note that there is no mention of deletions, and it would have trivially
been feasible to change it to say "insertions or deletions". That fact
that this was not done implies that no such guarantees apply to
deletions. Or, alternatively, they could have replaced the "during ..."
clause with "unless shrink_to_fit() or resize() are called", which would
have been an even stronger restriction.
JiiPee <no@notvalid.com>: Dec 13 01:53PM

On 13/12/2018 12:03, Alf P. Steinbach wrote:
> which tells you that you can rely on it in practice but that "That
> isn't mandated by the standard". Which is total bollocks. So much
> disinformation and FUD. It pains me.
 
ye I found that site as well
scott@slp53.sl.home (Scott Lurndal): Dec 13 01:55PM


>> Or any alternative good way implementing this?
 
>There is std::array but you would have to implement your own add and
>delete methods.
 
If the size is fixed, just use a plain old C array.
JiiPee <no@notvalid.com>: Dec 13 01:56PM

On 13/12/2018 13:33, Paavo Helde wrote:
> should have been phrased something like that:
 
> "No reallocation shall take place during further member function
> calls, with the exception of shrink_to_fit(), ...
 
logically yes
 
 
> I'm not claiming that clear() is allowed to reallocate the buffer,
> just pointing out this does not follow from this paragraph.
 
so how it is?
JiiPee <no@notvalid.com>: Dec 13 01:58PM

On 13/12/2018 13:55, Scott Lurndal wrote:
>> There is std::array but you would have to implement your own add and
>> delete methods.
> If the size is fixed, just use a plain old C array.
 
 
why not std::array? its a better version of c array? nothing to lose ,
only to get more, isnt it?
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Dec 13 03:17PM +0100

On 13.12.2018 14:34, James Kuyper wrote:
> says "Invalidates all references, pointers, and iterators referring to
> the elements of a ..." implies that a reallocation is allowed - a
> reallocation is the only thing that would necessitate invalidating them.
 
No, that's a misunderstanding.
 
For example, after clearing a vector all items have been destroyed.
That's very much "invalidate". You can't access items within the
capacity but beyond the current size.
 
 
> been feasible to change it to say "insertions or deletions". That fact
> that this was not done implies that no such guarantees apply to
> deletions.
 
No, that's a misunderstanding.
 
Insertions and `shrink_to_fit` are the only operations, apart from
`reserve` itself, that can possibly cause a reallocation. With that in
mind the quoted language describes what advantage calling `reserve`
gives you: that no reallocation will happen until... There is no
possible advantage associated with removing items, no need to describe
that, because that does not affect the capacity.
 
Similarly, `reserve` has no advantage associated with multiplying
integers, so there's no mention of that either.
 
 
> Or, alternatively, they could have replaced the "during ..."
> clause with "unless shrink_to_fit() or resize() are called", which would
> have been an even stronger restriction.
 
Yes, but there's no need.
 
This is not a defect. It's how the standard works. It does not mention
all the things that are disallowed: only what it says is allowed, is.
 
 
Cheers & hth.,
 
- Alf
"Öö Tiib" <ootiib@hot.ee>: Dec 13 06:22AM -0800

On Wednesday, 12 December 2018 22:49:04 UTC+2, JiiPee wrote:
> when resizing to zero. So I guess its undefined what happens to capacity
> after deleting elements?
 
> Or any alternative good way implementing this?
 
boost::container::static_vector
"Öö Tiib" <ootiib@hot.ee>: Dec 13 06:46AM -0800

On Thursday, 13 December 2018 16:17:27 UTC+2, Alf P. Steinbach wrote:
> gives you: that no reallocation will happen until... There is no
> possible advantage associated with removing items, no need to describe
> that, because that does not affect the capacity.
 
I trust std::vector::assign can also reallocate, otherwise it
does not make sense. About deletions there AFAIK are some
other requirements that imply that those won't reallocate.
For example std::vector::erase and std::vector::pop_back
have to leave the iterators and references up to point of
deletion valid (so can't reallocate) and std::vector::clear
has to leave capacity same (so it also can't reallocate).
Andrea Venturoli <ml.diespammer@netfence.it>: Dec 13 03:47PM +0100

On 12/13/18 2:34 PM, James Kuyper wrote:
 
> until the time when an insertion would make the size of the vector
> greater than the value of capacity()." (23.3.6.3p6).
> Note that there is no mention of deletions,
 
As I said, I don't have access to the standard right now...
 
Doesn't it say elsewhere that reallocation of a vector can only take
place during insertions?
Or, specularly, that deletions don't cause reallocations?
 
Both are "common sense", I believe...
jameskuyper@alumni.caltech.edu: Dec 13 08:29AM -0800

On Thursday, December 13, 2018 at 9:48:00 AM UTC-5, Andrea Venturoli wrote:
 
> As I said, I don't have access to the standard right now...
 
> Doesn't it say elsewhere that reallocation of a vector can only take
> place during insertions?
 
No.
 
> Or, specularly, that deletions don't cause reallocations?
 
erase() can only invalidate things that refer to positions after the element being erased, which effectively prohibits reallocation. However, clear() invalidated all pointers, references, and iterators; it could, therefore, reallocate so long as it doesn't change capacity().
Actually, I can't find as many statements about what can and cannot change the value returned by capacity() as I thought there were. I'm can't find anything that actually guarantees that capacity() will remain unchanged - by anything.
aitor.folgoso@googlemail.com: Dec 13 12:43AM -0800

Hi,
 
I'm trying to call a function from another template function but removing the last argument passed.
 
I need it because I've made a delegate implementation where one function call another one and works fine, but the problems is when the destination function has fewer arguments than the emitter function.
 
Is there any way the remove the last argument(s) from a parameter pack?
 
example:
 
template<typename... Args>
void invoke(string otherVariable, Args... args)
{
// call it but without the last argument
destinationFunction(args...);
}
 
void destinationFunction(string s, int val, bool status)
{
std::cout << s << " val:" << val << " status:" << status;
}
 
int main()
{
invoke("text", 1, true, 2);
 
// invoke should call destinationFunction but without the argument "2"
}
 
Can someone help me?
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Dec 13 12:48PM +0100

> {
> invoke("text", 1, true, 2);
 
> // invoke should call destinationFunction but without the argument "2"
 
The presence of an unused last argument is IMO a design odour.
 
But given that the problem needs to be solved anyway, I would probably
use an `index_list` with tuple `tie` and `get`.
 
A C++03 style solution could be to reason that it's easy to omit the
first argument of an argument pack, and that one can reverse an argument
pack recursively, but then C++03 didn't have argument packs.
 
Cheers & hth.,
 
- Alf
User <aitor.folgoso@googlemail.com>: Dec 13 06:18AM -0800

Hi,
 
the presence of unused argument isn't a design decision, but working with delegates. A function of the type EmitterFunc(int, bool, int) can be connected to a function with the prototype ReceptorFunction(int, bool).
 
Thanks for your suggestion of tuple and get. But I still don't know how to remove the last element of the list. Is there an easy way to remove the nth element of the argument list and still call the destination function?
 
Thanks again!
"Chris M. Thomasson" <invalid_chris_thomasson@invalid.invalid>: Dec 12 07:56PM -0800

On 12/7/2018 3:57 PM, Chris M. Thomasson wrote:
> here because a producer can suddenly morph into a consumer.
 
> Fwiw, I should have some running example code up tonight or sometime
> tomorrow.
 
Before I post my code, this queue keeps an upper bound on in flight
messages. There can be very interesting inter-thread exchanges.
Actually, this thing wants more threads!
Jorgen Grahn <grahn+nntp@snipabacken.se>: Dec 12 11:58PM

On Wed, 2018-12-12, David Brown wrote:
> On 12/12/18 11:44, Alf P. Steinbach wrote:
...
 
> with include guards - certainly no problems that were not part of a
> bigger issue (such as a project having more than one include file of the
> same name, from different directories).
 
IMO, same include file name in different directories is a good policy.
protocols/foo/encoder.h is a better name than
prococols/foo/foo_protocol_encoder.h.
 
But include guards should be named after more than just the file name.
If someone on the project has bad habits in that respect (a quick grep
will tell) it's time to educate him/her. It's also easy in most cases
to add a build step which fails the build on duplicate guards.
 
I can't remember when I've had issues with this, but it probably
happened once or twice over the years. I.e., an unsignificant problem
from my point of view. I probably wasted more time reading this
thread.
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
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: