- A way around _HAS_ITERATOR_DEBUGGING - 9 Updates
- Solar System Assembly Line - 1 Update
- recovering from std::bad_alloc in std::string reserve - 3 Updates
| 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:
Post a Comment