Friday, June 4, 2021

Digest for comp.lang.c++@googlegroups.com - 13 updates in 3 topics

MrSpook_ujp@3p26kggzpvpn2h.gov.uk: Jun 04 07:43AM

On Thu, 3 Jun 2021 17:49:40 +0000 (UTC)
 
>It's not even the first time. You keep doing this again and again,
>most often completely unpromted out of the blue, in response to completely
>innocuous posts, for completely unknown reasons. Why?
 
You're a fine one to talk.
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jun 04 10:22AM +0100

On Thu, 3 Jun 2021 20:18:05 +0300
> 03.06.2021 18:06 James Kuyper kirjutas:
[snip]
> daunting, and the benefits seem pretty meager (satisfying one angry
> Bonita Montero somewhere on the internet; everybody else is happy with
> vec.data()+vec.size()).
 
They shouldn't have been happy with that. It says something about the
state of the C++ language standard that until C++20, although
std::vector::data() was said to return "A pointer such that [data(),
data() + size()) is a valid range", actually applying pointer
arithmetic to the result of std::vector::data() as in 'vec.data() +
vec.size()' gave undefined behaviour - undefined bahaviour arising from
the use of pointer arithmetic on a pointer not pointing within (or one
past the end of) an array object.
 
No one seems to have noticed until P0593 arrived on the scene, which
also pointed out that use of the standard's std::uninitialized_*()
functions also generated undefined behaviour, for the same reason.
Paavo Helde <myfirstname@osa.pri.ee>: Jun 04 02:19PM +0300

04.06.2021 12:22 Chris Vine kirjutas:
 
> No one seems to have noticed until P0593 arrived on the scene, which
> also pointed out that use of the standard's std::uninitialized_*()
> functions also generated undefined behaviour, for the same reason.
 
You mean, an array encapsulated by a std::vector might not be an array?
 
At least https://en.cppreference.com/w/cpp/container/vector/data says:
"Returns pointer to the underlying array serving as element storage."
This wording would make vec.data()+vec.size() legal. Alas, the standard
indeed uses a different wording.
 
P0593 seems to be more worried about how it is even possible to
implement std::vector, this is a bit different topic.
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jun 04 01:07PM +0100

On Fri, 4 Jun 2021 14:19:44 +0300
> indeed uses a different wording.
 
> P0593 seems to be more worried about how it is even possible to
> implement std::vector, this is a bit different topic.
 
std::vector does not encapsulate an array. std::vector constructs
objects in memory dynamically allocated by malloc, operator new or some
custom allocator.
 
[expr.add]/4 on pointer arithmetic is clear:
 
"When an expression J that has integral type is added to or subtracted
from an expression P of pointer type, the result has the type of P.
 
— If P evaluates to a null pointer value and J evaluates to 0, the
result is a null pointer value.
 
— Otherwise, if P points to an array element i of an array object x
with n elements, the expressions P + J and J + P (where J has the
value j) point to the (possibly-hypothetical) array element i + j of
x if 0 ≤ i + j ≤ n and the expression P - J points to the
(possibly-hypothetical) array element i − j of x if 0 ≤ i − j ≤ n.
 
— Otherwise, the behavior is undefined."
 
"Array" here means a C-style array, although std::array would do as
that allocates its storage in a C-style array. std::vector does not.
 
If you compile 'vec.data()+vec.size()' with the -std=c++20 flag, the
expression is valid (but not otherwise), and that is presumably what
cppreference.com is thinking of. In C++20 an array is an implicit
lifetime type which is separate from the sub-objects (the elements) it
contains - the latter may or may not be implicit lifetime types. In
C++20 an array always is, and it will spring into life automatically if
necessary to give the code defined behaviour. 'vec.data()+vec.size()'
creates an array implicitly. Prior to that the allocated storage
concerned is in super-position, being of both array and non-array type
at the same time (Shroedinger's Array).
 
As you say, in C++17 it is impossible to implement your own equivalent
of std::vector with defined behaviour, and much else besides. In C++20
it is at least now possible to build your own vector type and
associated allocators with something approaching defined behaviour.
You can also used std::uninitialized_copy() with defined behaviour.
To be honest, I regard this as a pretty major fail for C++: it turned
out that the C++ standard committee did not understand its own standard
on fairly fundamental points.
James Kuyper <jameskuyper@alumni.caltech.edu>: Jun 04 10:40AM -0400

On 6/3/21 1:18 PM, Paavo Helde wrote:
...
> So in C++ one just cannot "cancel" &* as the result would be of a wrong
> type.
 
It could be the right type if the return type of the relevant
operator&() overload is the same as the iterator type.
Paavo Helde <myfirstname@osa.pri.ee>: Jun 04 07:28PM +0300

04.06.2021 17:40 James Kuyper kirjutas:
>> type.
 
> It could be the right type if the return type of the relevant
> operator&() overload is the same as the iterator type.
 
In general, it cannot be. Imagine:
 
class A {
std::vector<A>::iterator operator&() {
// magic here???
}
};
 
An object in C++ does not know if and in which vector it might reside
(unless specifically told so, resulting in some pretty convoluted
design), and so it cannot construct a correct iterator to itself.
 
Even if it were the "right type" this would not solve the OP's problem
as she specifically wanted to get a pointer, not an iterator.
James Kuyper <jameskuyper@alumni.caltech.edu>: Jun 04 01:04PM -0400

On 6/4/21 12:28 PM, Paavo Helde wrote:
> design), and so it cannot construct a correct iterator to itself.
 
> Even if it were the "right type" this would not solve the OP's problem
> as she specifically wanted to get a pointer, not an iterator.
 
I've never attempted implementing any of the standard containers (not
because I couldn't, but just to avoid reinventing the wheel), so I might
be missing some important detail (possibly one introduced by recent
updates - I'm sill more somewhat shaky in my understanding of some of
the features introduced after C++ 2003). However, it seems to me that it
should be possible to implement std::vector<T> with the iterator type
being T*, in which case that wouldn't be a problem. If that's not
feasible, could you explain what's problematic about it?
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jun 04 01:30PM -0700

On 6/4/2021 10:04 AM, James Kuyper wrote:
> be missing some important detail (possibly one introduced by recent
> updates - I'm sill more somewhat shaky in my understanding of some of
> the features introduced after C++ 2003).
 
I always thought that implementing standard containers in a C++ course
would be fun. The teacher says something like: We are going to implement
several std containers under the namespace std_course. Imvvho, it would
be an interesting and worth while exercise.
 
Paavo Helde <myfirstname@osa.pri.ee>: Jun 04 11:45PM +0300

04.06.2021 20:04 James Kuyper kirjutas:
> the features introduced after C++ 2003). However, it seems to me that it
> should be possible to implement std::vector<T> with the iterator type
> being T*,
 
Indeed, there have been implentations where iterator type was T*.
However, for now the major C++ implementations have abandoned this idea,
both for more type safety (to avoid accidental conversion from pointers
to iterators) and for supporting different levels of iterator debugging
(catching out-of-range iterators, stale iterators, dereferencing
non-dereferencable iterators like vec.end(), etc).
 
> in which case that wouldn't be a problem.
 
There is no problem. There is no need to dereference non-dereferencable
iterators.
 
> If that's not
> feasible, could you explain what's problematic about it?
 
Apparently there is a perceived problem of misusing iterators and a
desire to provide iterator safety checks and debugging aids. This would
not be possible if iterators were just plain pointers.
 
A demo: this program reports a run-time error "Error: attempt to advance
a [...] iterator 10 steps, which falls outside its valid range." when
compiled with right options.
 
> cat test1.cpp
#include <vector>
#include <algorithm>
 
int main() {
std::vector<int> v = {3,2,1,5,2,5,3};
std::sort(v.begin(), v.begin()+10);
}
 
> g++ test1.cpp -D_GLIBCXX_DEBUG
> ./a.exe
/usr/lib/gcc/x86_64-pc-cygwin/10/include/c++/debug/safe_iterator.h:906:
In function:
__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<int*,
std::__cxx1998::vector<int, std::allocator<int> > >,
std::__debug::vector<int>, std::random_access_iterator_tag>::_Self
__gnu_debug::operator+(const _Self&,
__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<int*,
std::__cxx1998::vector<int, std::allocator<int> > >,
std::__debug::vector<int>,
std::random_access_iterator_tag>::difference_type)
 
Error: attempt to advance a dereferenceable (start-of-sequence) iterator 10
steps, which falls outside its valid range.
 
Objects involved in the operation:
iterator @ 0x0xffffcbc0 {
type = __gnu_cxx::__normal_iterator<int*,
std::__cxx1998::vector<int, std::allocator<int> > > (mutable iterator);
state = dereferenceable (start-of-sequence);
references sequence with type 'std::__debug::vector<int,
std::allocator<int> >' @ 0x0xffffcb30
}
Aborted (core dumped)
gazelle@shell.xmission.com (Kenny McCormack): Jun 04 05:47PM

In article <s9a740$r21$3@gioia.aioe.org>,
>In comp.lang.c++ Rick C. Hodgin <rick.c.hodgin@gmail.com> wrote:
>> I reject the Solar System Assembly Line theory on that basis.
 
>And we needed to know this why, exactly?
 
I don't know about you, but it was certainly keeping *ME* up nights
worrying about whether or not Rick was buying into this "theory".
 
--
You know politics has really been turned upside down when you have someone in the
government with a last name of Cheney (Liz, Senator from Wyoming) who is the voice of
reason.
"Öö Tiib" <ootiib@hot.ee>: Jun 03 04:27PM -0700

On Friday, 4 June 2021 at 01:24:23 UTC+3, Scott Lurndal wrote:
> >But standard library functions are often not inlined unless they are
> >completely replaced by built-ins that have the same semantics. I'm not
 
> As of GCC 4.8, 'div' wasn't ever inlined, even with -O3.
 
Maybe with -flto it does?
scott@slp53.sl.home (Scott Lurndal): Jun 04 12:36AM

>> >completely replaced by built-ins that have the same semantics. I'm not
 
>> As of GCC 4.8, 'div' wasn't ever inlined, even with -O3.
 
>Maybe with -flto it does?
 
Perhaps, but gcc generally documents all the functions that will
be inlined in their texinfo documentation, and div is not included
in the list of math functions that automatically get builtin status
at least in GCC 4.8. Since they're up to GCC11 now, they may have
added it to the list.
 
However, if the compiler recognizes cases where both the quotient
and remainder are used and generates a single divide instruction,
there doesn't seem much need for div at all.
David Brown <david.brown@hesbynett.no>: Jun 04 08:46AM +0200

On 04/06/2021 02:36, Scott Lurndal wrote:
> in the list of math functions that automatically get builtin status
> at least in GCC 4.8. Since they're up to GCC11 now, they may have
> added it to the list.
 
It has not (because of the weakly specified "div_t" struct that is
determined by the library implementation and not the standards or the
compiler).
 
<https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html>
 
> However, if the compiler recognizes cases where both the quotient
> and remainder are used and generates a single divide instruction,
> there doesn't seem much need for div at all.
 
Exactly my point - as far as I can tell, "div" is a hangover from weak
or limited compilers from long ago.
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: