- newbie question: insert a vector to itself at end - 8 Updates
- newbie question: insert a vector to itself at end - 2 Updates
- Now what? - 3 Updates
- [Jesus Loves You] The Truth - 2 Updates
- A "Quantum" is so TINY, photons push it around, randomly. - 1 Update
- neos - 1 Update
anhongleetcode@gmail.com: May 10 11:49PM -0700 Recently I found this is not working.... I am trying to insert a vector itself to its end. Here people even complains that v.push_back(p.front()) won't work! https://www.reddit.com/r/cpp/comments/vog1p/a_commonly_unknown_stdvector_pitfall/ I tried, the v.push_back(v.front()) for my gcc8 works. But the following code doesn't Experts, why this is implemented as NOT WORKING? It's for me as can't understand. Thanks, Anhong #include <vector> #include <string> int main() { std::vector<std::string> v { "1", "2", "3", }; v.push_back(v.front()); for(int i = 0; i < 2; ++i){ v.insert(v.end(), v.begin(), v.begin() + 3); } return 0; } |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: May 11 09:37AM +0200 > I am trying to insert a vector itself to its end. > Here people even complains that v.push_back(p.front()) won't work! > https://www.reddit.com/r/cpp/comments/vog1p/a_commonly_unknown_stdvector_pitfall/ That's incorrect, as also noted by Stephan T. Lavavej (the person in charge of STL maintenance at Microsoft) in a comment there. > } > return 0; > } Works for me with both Visual C++ 2017 and MinGW g++ 8.2 compilers. And I don't see any practical reason why it shouldn't work, since the vector code can easily detect copying from self and ensure a sufficiently large new buffer if necessary. Can you provide an example, with the compiler version & invocation, where it doesn't work according to your expectations? Cheers!, - Alf |
Bonita Montero <Bonita.Montero@gmail.com>: May 11 10:07AM +0200 > Works for me with both Visual C++ 2017 and MinGW g++ 8.2 compilers. LOL. |
Manfred <noname@invalid.add>: May 11 07:31PM +0200 On 5/11/19 9:37 AM, Alf P. Steinbach wrote: >> https://www.reddit.com/r/cpp/comments/vog1p/a_commonly_unknown_stdvector_pitfall/ > That's incorrect, as also noted by Stephan T. Lavavej (the person in > charge of STL maintenance at Microsoft) in a comment there. The comments refers to: http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#526 Which says: "vector::insert(iter, value) is required to work because the standard doesn't give permission for it not to work." Which is obvious if value is an actual value, and 23.2.3 p4 describes a.insert(p,t) where "t denotes an lvalue or a const rvalue of X::value_type" (p3), but: 23.3.6.1 says the signature of front is: const_reference front() const; 23.3.6.5 specifies: iterator insert(const_iterator position, const T& x); that takes a const reference, and specifies: "Causes reallocation if the new size is greater than the old capacity" (p1) and 23.3.6.3 (vector capacity) clarifies that: "Reallocation invalidates all the references, pointers, and iterators referring to the elements in the sequence" (p6) So, I am most probably missing something, because to me there is some unclarity between "lvalue or const rvalue of X:value_type" of 23.2.3 (requirements for sequence containers) and "const reference to T" of 23.3.6 (vector member signatures). Anyway, since defect 526 has been closed as "not a defect" by the committee, it can probably be trusted to work, and in fact it works for gcc 8.3 >> return 0; >> } > Works for me with both Visual C++ 2017 and MinGW g++ 8.2 compilers. It doesn't work with gcc 8.3 > And I don't see any practical reason why it shouldn't work, since the > vector code can easily detect copying from self and ensure a > sufficiently large new buffer if necessary. No, 23.2.3 p4 clearly states the pre-condition for a.insert(p, i, j) "i and j are not iterators into a." And in fact i and j are invalidated by insert if a reallocation occurs. |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: May 11 10:49PM +0200 On 11.05.2019 19:31, Manfred wrote: >>> } >> Works for me with both Visual C++ 2017 and MinGW g++ 8.2 compilers. > It doesn't work with gcc 8.3 Oh. > No, 23.2.3 p4 clearly states the pre-condition for > a.insert(p, i, j) > "i and j are not iterators into a." I overlooked that one, thanks! In C++17 it's in table 87 in §25.2.3/4, a.k.a. §sequence.reqmts/4. Thinking about it, it's probably due to the design where the iterators are general /input iterators/, which I didn't notice either. So one could define some custom stream like iterators that read from a vector, and try to use those to insert into the same vector, and wham bang. It seems the wording covers that, by excluding "iterators into a". I didn't think of that. But now that I do, I still don't see any practical reason for it. One could change the design to have the general input iterator based insert called `insert_input`, add a random iterator based `insert`, and allow the former to be optimized by deferring to the latter when iterator traits say the iterators are actually random access. The random iterator based `insert` can easily check for self-referencing iterators by using `std::less` (say, because total ordering) on the item pointers. Then the no-self-ref requirement would be only on `insert_input`. > And in fact i and j are invalidated by insert if a reallocation occurs. Yes but as I see it, considering not just how conceptually easy this is to implement (though it would be some coding work to do it) but that at least two such implementations apparently exist, that's irrelevant. The iterators are then valid before the operation, and invalid after, but that's all that one can say. One cannot conclude anything about the operation's success or well-defined-ness from that, as I see it. Cheers!, - Alf |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: May 12 12:25AM +0200 On 11.05.2019 22:49, Alf P. Steinbach wrote: > based `insert` can easily check for self-referencing iterators by using > `std::less` (say, because total ordering) on the item pointers. > Then the no-self-ref requirement would be only on `insert_input`. Here's how I envision a `std::vector` design without the self reference trap, like (the just sufficient for the OP's example) `my::Vec` below: ----------------------------------------------------------------------- #include <vector> #include <string> #include <functional> // std::(less_or_equal) #include <iterator> // std::iterator_traits #include <memory> // std::addressof #include <type_traits> // std::is_same_v #include <utility> // std::(enable_if_t, move) namespace my{ using std::addressof, std::move, std::random_access_iterator_tag; template< bool condition > using Enable_if_ = std::enable_if_t<condition>; template< class A, class B > constexpr bool is_same_type_ = std::is_same_v<A, B>; template< class T > using It_category_ = typename std::iterator_traits<T>::iterator_category; template< class Item > class Vec: private std::vector<Item> { using Base = std::vector<Item>; public: using iterator = typename Base::iterator; using const_iterator = typename Base::const_iterator; using Index = typename Base::difference_type; using Base::begin; using Base::cbegin; using Base::data; using Base::end; using Base::front; using Base::push_back; using Base::reserve; using Base::size; template< class Rnd_it, class = Enable_if_<is_same_type_< It_category_<Rnd_it>, random_access_iterator_tag auto insert( const const_iterator position, const Rnd_it first, const Rnd_it last ) -> iterator { const Index i_position = position - cbegin(); iterator pos = begin() + i_position; if( first == last ) { return pos; } const auto p_first = addressof( *first ); constexpr auto less_or_equal = std::less_equal<const Item*>(); if( less_or_equal( data(), p_first ) and less_or_equal( p_first, data() + size() ) ) { Vec copies( first, last ); reserve( size() + (last - first) ); for( Item& item: copies ) { pos = Base::insert( pos, move( item ) ); } return pos; } return Base::insert( position, first, last ); } template< class Input_it> auto insert_input( const const_iterator position, const Input_it first, const Input_it last ) -> iterator { using Rnd_tag = random_access_iterator_tag; if constexpr( is_same_type_<It_category_<Input_it>, Rnd_tag> ) { return insert( position, first, last ); } else { return Base::insert( position, first, last ); } } using Base::Base; }; } // namespace my auto main() -> int { my::Vec<std::string> v { "1", "2", "3", }; v.push_back(v.front()); for( int i = 0; i < 2; ++i ) { v.insert( v.end(), v.begin(), v.begin() + 3 ); } return v.size(); } ----------------------------------------------------------------------- > [snip] Cheers!, - Alf |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: May 12 12:53AM +0200 On 12.05.2019 00:25, Alf P. Steinbach wrote: > [code with a 2 little bugs] Strange that I should introduce bugs in something so simple. But then it's late in the day, and I'm an old man (sort of). So it's not guaranteed that this fixed code is entirely bug-free either. #include <assert.h> #include <vector> #include <string> #include <functional> // std::(less_or_equal) #include <iterator> // std::iterator_traits #include <memory> // std::addressof #include <type_traits> // std::is_same_v #include <utility> // std::(enable_if_t, move) namespace my{ using std::addressof, std::move, std::random_access_iterator_tag; template< bool condition > using Enable_if_ = std::enable_if_t<condition>; template< class A, class B > constexpr bool is_same_type_ = std::is_same_v<A, B>; template< class T > using It_category_ = typename std::iterator_traits<T>::iterator_category; template< class Item > class Vec: private std::vector<Item> { using Base = std::vector<Item>; public: using iterator = typename Base::iterator; using const_iterator = typename Base::const_iterator; using Index = typename Base::difference_type; using Base::begin; using Base::cbegin; using Base::data; using Base::end; using Base::front; using Base::push_back; using Base::reserve; using Base::size; template< class Rnd_it, class = Enable_if_<is_same_type_< It_category_<Rnd_it>, random_access_iterator_tag auto insert( const const_iterator position, const Rnd_it first, const Rnd_it last ) -> iterator { const Index i_position = position - cbegin(); if( first == last ) { return begin() + i_position; } const auto p_first = addressof( *first ); constexpr auto less_or_equal = std::less_equal<const Item*>(); if( less_or_equal( data(), p_first ) and less_or_equal( p_first, data() + size() ) ) { Vec copies( first, last ); reserve( size() + (last - first) ); iterator pos = begin() + i_position; for( Item& item: copies ) { Base::insert( pos, move( item ) ); ++pos; } return pos; } return Base::insert( position, first, last ); } template< class Input_it> auto insert_input( const const_iterator position, const Input_it first, const Input_it last ) -> iterator { using Rnd_tag = random_access_iterator_tag; if constexpr( is_same_type_<It_category_<Input_it>, Rnd_tag> ) { return insert( position, first, last ); } else { return Base::insert( position, first, last ); } } using Base::Base; }; } // namespace my auto main() -> int { my::Vec<std::string> v { "1", "2", "3", }; v.push_back(v.front()); for( int i = 0; i < 2; ++i ) { v.insert( v.end(), v.begin(), v.begin() + 3 ); } return v.size(); } Cheers!, - Alf |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: May 12 01:01AM +0200 On 12.05.2019 00:53, Alf P. Steinbach wrote: > Strange that I should introduce bugs in something so simple. But then > it's late in the day, and I'm an old man (sort of). So it's not > guaranteed that this fixed code is entirely bug-free either. Yup, just two seconds after pressing "Send" in Thunderbird, I noticed that an assignment was missing. for( Item& item: copies ) { pos = Base::insert( pos, move( item ) ); ++pos; } So. Cheers!, - ALf |
ram@zedat.fu-berlin.de (Stefan Ram): May 11 07:20PM >I am trying to insert a vector itself to its end. This would yield a circular vector! First, tell the printer to not really print the expansion: (setf *print-circle* t) . With the helper function (defun circular! (items) (setf (cdr (last items)) items)) we can then observe that (circular! (list 1 2 3)) effectively is ( 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 ... ) . |
ram@zedat.fu-berlin.de (Stefan Ram): May 11 10:41PM >(circular! (list 1 2 3)) >( 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 ... ) Lurkers told my in e-mail that this is not C++. So, here is my attempt to use a circular list in C++ using std-containers. The code "works" but I don't know whether this behaviour is guaranteed by the standard or just showing under my implementation! main.cpp #include <iostream> #include <list> int main() { ::std::list< int >l; l.push_back( 2 ); l.push_back( 4 ); l.push_front( 7 ); int c {}; for( auto i = l.begin();; ++i ) { if( i != l.end() )::std::cout << *i << '\n'; if( c++ > 20 )break; }} transcript 7 2 4 7 2 4 7 2 4 7 2 4 7 2 4 7 2 |
woodbrian77@gmail.com: May 10 10:28PM -0700 Shalom What's your opinion of this on-line code generator https://github.com/Ebenezer-group/onwards ? I think the need for quality software will increase as time goes on. So I've been working on the code generator and trying to improve it. I believe I've been making progress, but I'll let you be the judge: https://github.com/Ebenezer-group/onwards/blob/master/src/cmw/tiers/genz.cc https://github.com/Ebenezer-group/onwards/blob/master/src/cmw/tiers/cmwA.cc These are my repo topics: cross-platform hosted middleware network programming on-line service protocols services three-tier architecture cpp-library code generation client-server messaging command-line tool organic disruptive-technology Archimedes Jerusalem c-plus-plus What do you think needs work? Thanks in advance. Brian Ebenezer Enteprises - Enjoying programming again. http://webEbenezer.net |
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: May 11 11:58AM +0100 > Shalom > What's your opinion of this on-line code generator > https://github.com/Ebenezer-group/onwards You mean please look at my thinly disguised spam advert for my software and website links to let you I am a misogynist homophobic bigot? You are transparent, m8. /Flibble -- "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," Bryne 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." |
woodbrian77@gmail.com: May 11 06:43AM -0700 On Saturday, May 11, 2019 at 5:58:57 AM UTC-5, Mr Flibble wrote: > You mean please look at my thinly disguised spam advert for my software > and website links to let you I am a misogynist homophobic bigot? You are > transparent, m8. Some people tried to label the Apostle Paul the same way. History concluded differently. I'm proud to live in St. Paul, Minnesota. There's also St. Peter, Minnesota, St. Michael, Minnesota, Bethel, Minnesota (Bethel means House of G-d in Hebrew). I will venture to guess that you have not read "The Right Side of History. How Reason and Moral Purpose Made the West Great" by Ben Shapiro. https://www.harpercollins.com/9780062857903/the-right-side-of-history/ You are kind of out of the loop here I'm afraid. Best wishes. |
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: May 11 03:55AM -0700 Go to church this Sunday and experience God's grace, His forgiveness, His towering love for you deep down. https://mobile.twitter.com/KraigDay5/status/1127099958946140160 His love for you will overpower your troubles. All of them. You can go to sleep at night knowing whose you are, and what your future holds -- regardless of your Earthly circumstances. His arms are open wide to embrace you with forgiveness for your sin, and to give you eternal life in love and peace and joy and happiness. It will free your mind like nothing else. This is a true witness. Love has a name. His name is Jesus. Trust Him. He will never let you down. -- Rick C. Hodgin |
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: May 11 12:00PM +0100 On 11/05/2019 11:55, Rick C. Hodgin wrote: > Love has a name. > His name is Jesus. > Trust Him. He will never let you down. Nonsense. A) Your bible is false. B) Your god the existence of which is predicated on your bible being true is, given (A), also false. /Flibble -- "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," Bryne 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." |
Jeff-Relf.Me @.@: May 10 09:02PM -0700 |
Bonita Montero <Bonita.Montero@gmail.com>: May 10 09:30PM +0200 > (ARM64 store exclusive) are made available as individual intrinsics > since the code sequence between the LDEX and STREX must not, for > example, include stores for proper operations. Then the code around this intrinsics has to be suitable. |
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