[ptr_container] Transferring the Last Element from a ptr_vector
I have two functions which swap elements between ptr_vectors. The first
compiles and apparently works correctly.
typedef boost::ptr_vector<Gene> GeneVectType;
GeneVectType geneVect;
void Gene::swapGene(Gene* other) {
geneVect.transfer(geneVect.end(), other->geneVect.begin(),
other->geneVect);
other->geneVect.transfer(other->geneVect.end(), geneVect.begin(),
geneVect);
}
Occasionally I must reverse the swap with this unswap function.
void Gene::unswapGene(Gene* other) {
// The line below is line 560 referred to in the error message.
geneVect.transfer(geneVect.begin(), other->geneVect.rbegin(),
other->geneVect);
other->geneVect.transfer(other->geneVect.begin(), geneVect.rbegin(),
geneVect);
}
This function should take the last element from each container and transfer
it to the beginning of the other container. The unswapGene function will not
compile. Here's the compiler message.
C:\Boost SVN\trunk\boost/range/const_iterator.hpp(37) : error C2039:
'const_iterator' : is not a member of 'boost::reverse_iterator<Iterator>'
with [Iterator=boost::void_ptr_iterator
Charles Brockman skrev:
I have two functions which swap elements between ptr_vectors. The first compiles and apparently works correctly.
typedef boost::ptr_vector<Gene> GeneVectType; GeneVectType geneVect;
void Gene::swapGene(Gene* other) { geneVect.transfer(geneVect.end(), other->geneVect.begin(), other->geneVect); other->geneVect.transfer(other->geneVect.end(), geneVect.begin(), geneVect); }
Occasionally I must reverse the swap with this unswap function.
void Gene::unswapGene(Gene* other) { // The line below is line 560 referred to in the error message. geneVect.transfer(geneVect.begin(), other->geneVect.rbegin(), other->geneVect); other->geneVect.transfer(other->geneVect.begin(), geneVect.rbegin(), geneVect); }
You can't use reverse iterators in transfer. HTH -Thorsten
Thorsten Ottosen wrote:
You can't use reverse iterators in transfer.
Thank you, Thorsten. I'll create an iterator to the last element and use that in the transfer. GeneVectType::iterator othEndIter = other->geneVect.end(); --othEndIter; geneVect.transfer(geneVect.begin(), othEndIter, other->geneVect); -- Charles
Charles Brockman wrote:
Thorsten Ottosen wrote:
You can't use reverse iterators in transfer.
Thank you, Thorsten. I'll create an iterator to the last element and use that in the transfer.
GeneVectType::iterator othEndIter = other->geneVect.end(); --othEndIter; geneVect.transfer(geneVect.begin(), othEndIter, other->geneVect);
Um -- I'm under the impression that decrementing the iterator returned by end() is discouraged. There are containers for which that definitely would not work. I'm guessing that he would recommend something like other->geneVect.rbegin().base() instead -- presuming you've already ensured that other->geneVect isn't empty.
Nat Goodspeed wrote:
I'm guessing that he would recommend something like other->geneVect.rbegin().base() instead ...
The geneVect.rbegin().base() form compiles but when run blows up in my face with a "vector iterator not dereferencable" error. -- Charles
AMDG Nat Goodspeed wrote:
Charles Brockman wrote:
Thorsten Ottosen wrote:
You can't use reverse iterators in transfer.
Thank you, Thorsten. I'll create an iterator to the last element and use that in the transfer.
GeneVectType::iterator othEndIter = other->geneVect.end(); --othEndIter; geneVect.transfer(geneVect.begin(), othEndIter, other->geneVect);
Um -- I'm under the impression that decrementing the iterator returned by end() is discouraged. There are containers for which that definitely would not work.
It should work for any container that supports bidirectional iterators.
I'm guessing that he would recommend something like other->geneVect.rbegin().base() instead -- presuming you've already ensured that other->geneVect isn't empty.
other->geneVect.rbegin().base() is equivalent to other->getVect.end(). In Christ, Steven Watanabe
2009/9/9 Steven Watanabe
Nat Goodspeed wrote:
Um -- I'm under the impression that decrementing the iterator returned by end() is discouraged. There are containers for which that definitely would not work.
It should work for any container that supports bidirectional iterators.
...except std::vector, iirc.
AMDG Scott McMurray wrote:
2009/9/9 Steven Watanabe
: Nat Goodspeed wrote:
Um -- I'm under the impression that decrementing the iterator returned by end() is discouraged. There are containers for which that definitely would not work.
It should work for any container that supports bidirectional iterators.
...except std::vector, iirc.
The ability to decrement any bidirectional iterator except begin() is required by the standard. All Bidirectional iterators /must/ support this, including the iterators of std::vector. (See 24.1.4, Table 75) In Christ, Steven Watanabe
2009/9/9 Steven Watanabe
Scott McMurray wrote:
2009/9/9 Steven Watanabe
: Nat Goodspeed wrote:
Um -- I'm under the impression that decrementing the iterator returned by end() is discouraged. There are containers for which that definitely would not work.
It should work for any container that supports bidirectional iterators.
...except std::vector, iirc.
The ability to decrement any bidirectional iterator except begin() is required by the standard. All Bidirectional iterators /must/ support this, including the iterators of std::vector. (See 24.1.4, Table 75)
Sorry, I didn't give enough context. My understanding is that Nat was referring to using "--container.end()" to get an iterator to the last element in a container, which works for every bidi container but vector. I see no reason why decrementing a normal lvalue iterator would be "discouraged", as as you say, it's a fundamental bidi iterator operation.
Steven Watanabe wrote:
The ability to decrement any bidirectional iterator except begin() is required by the standard. All Bidirectional iterators /must/ support this, including the iterators of std::vector. (See 24.1.4, Table 75)
I guess I was conflating the case of (iterator returned by a bidirectional container's end()) with (end-marker iterator obtained by default-constructing certain types of iterators). I'm glad to learn that you can reliably decrement the iterator returned by end(), providing it's not equal to the iterator returned by begin().
Um -- I'm under the impression that decrementing the iterator returned by end() is discouraged. There are containers for which that definitely would not work.
I'm guessing that he would recommend something like other->geneVect.rbegin().base() instead -- presuming you've already ensured that other->geneVect isn't empty.
Nat, you would be half right only if GeneVectType::iterator were a forward_iterator, but a ptr_sequence_adapter is always reversible, so the iterator must be bidirectional. Internally, the boost::reverse_iterator you propose also has to decrement, so it doesn't work any better. Additionally, your proposed solution crashes because other->geneVect.rbegin().base() returns in fact other->geneVect.end(). Only *other->geneVect.rbegin() returns *(other->geneVect.end()-1). Regards Sebastian -- Sebastian Theophil . stheophil@think-cell.com Software Engineer think-cell Software GmbH . Invalidenstr. 34 . 10115 Berlin, Germany http://www.think-cell.com . phone +49-30-666473-10 . toll-free (US) +1-800-891-8091 Directors: Dr. Markus Hannebauer, Dr. Arno Schoedl . Amtsgericht Berlin-Charlottenburg, HRB 85229
Sebastian Theophil wrote:
Internally, the boost::reverse_iterator you propose also has to decrement, so it doesn't work any better. Additionally, your proposed solution crashes because other->geneVect.rbegin().base() returns in fact other->geneVect.end(). Only *other->geneVect.rbegin() returns *(other->geneVect.end()-1).
Thanks, Steven and Sebastian. I've learned something today.
participants (6)
-
Charles Brockman
-
Nat Goodspeed
-
Scott McMurray
-
Sebastian Theophil
-
Steven Watanabe
-
Thorsten Ottosen