M
mike3
Hi.
I just found out that the iterators used by std::vector<> are not
required to perform boundschecking, even as a debug mode! So then what
do I do? I'd like to have it available as a debug, even if not in a
release version.
For example, consider the piece of code at the end of this message.
Should I use a boundscheck in there to check whether or not the ranges
specified are in-bounds or out-of-bounds? But if I do, then it makes
that seemingly nice piece of code real messy and I don't like it so
much.
Would it be a good idea therefore to perhaps build some sort of "safe
iterator" class that duplicates the functionality of iterator (in
fact, encapsulating an iterator inside it), but includes the
boundschecking for debug builds (otherwise, the safe iterator becomes
an ordinary iterator for maximum performance.)?
--- Code snippet:
/* Add two RawDigit sections.
* Parameters:
* a: First RawDigit.
* b: Second RawDigit.
* rstart: Starting digit of section of this to use.
* rend: Ending digit of section of this to use.
* astart: Starting digit of section of a to use.
* aend: Ending digit of section of a to use.
* bstart: Starting digit of section of b to use.
* bend: Ending digit of section of b to use.
*
* Returns: carry.
*
* Operation: *this = a + b.
*/
Digit RawDigit::Add(const RawDigit &a, const RawDigit &b,
std::size_t rstart, std::size_t rend,
std::size_t astart, std::size_t aend,
std::size_t bstart, std::size_t bend)
{
/* Get lengths */
std::size_t rLength(rend - rstart + 1);
std::size_t aLength(aend - astart + 1);
std::size_t bLength(bend - bstart + 1);
/* Set up iterators */
DigitIterator ri(digits.begin() + rstart);
c_DigitIterator ai(a.digits.begin() + astart);
c_DigitIterator bi(b.digits.begin() + bstart);
/* Make b the shortest operand */
if(aLength < bLength)
return(Add(b, a, rstart, rend, bstart, bend, astart, aend));
/* Now do the first part of the addition, involving both a and b
*/
Digit carry(0);
for(std::size_t i(0);i<bLength && i<rLength;++i,++ri,++ai,++bi)
*ri = DigitAdd(*ai, *bi, &carry);
/* Now do the second part of the addition, involving only a,
* if necessary.
*/
for(std::size_t i(bLength);i<aLength && i<rLength;++i,++ri,++ai)
*ri = DigitAdd(*ai, 0, &carry);
/* Now do the third and final part of the addition, which
* just pads the result with zeroes and propagates the carry,
* if necessary.
*/
for(std::size_t i(aLength);i<rLength;++i,++ri)
{
*ri = carry;
carry = 0;
}
/* Done! */
return(carry);
}
---
I just found out that the iterators used by std::vector<> are not
required to perform boundschecking, even as a debug mode! So then what
do I do? I'd like to have it available as a debug, even if not in a
release version.
For example, consider the piece of code at the end of this message.
Should I use a boundscheck in there to check whether or not the ranges
specified are in-bounds or out-of-bounds? But if I do, then it makes
that seemingly nice piece of code real messy and I don't like it so
much.
Would it be a good idea therefore to perhaps build some sort of "safe
iterator" class that duplicates the functionality of iterator (in
fact, encapsulating an iterator inside it), but includes the
boundschecking for debug builds (otherwise, the safe iterator becomes
an ordinary iterator for maximum performance.)?
--- Code snippet:
/* Add two RawDigit sections.
* Parameters:
* a: First RawDigit.
* b: Second RawDigit.
* rstart: Starting digit of section of this to use.
* rend: Ending digit of section of this to use.
* astart: Starting digit of section of a to use.
* aend: Ending digit of section of a to use.
* bstart: Starting digit of section of b to use.
* bend: Ending digit of section of b to use.
*
* Returns: carry.
*
* Operation: *this = a + b.
*/
Digit RawDigit::Add(const RawDigit &a, const RawDigit &b,
std::size_t rstart, std::size_t rend,
std::size_t astart, std::size_t aend,
std::size_t bstart, std::size_t bend)
{
/* Get lengths */
std::size_t rLength(rend - rstart + 1);
std::size_t aLength(aend - astart + 1);
std::size_t bLength(bend - bstart + 1);
/* Set up iterators */
DigitIterator ri(digits.begin() + rstart);
c_DigitIterator ai(a.digits.begin() + astart);
c_DigitIterator bi(b.digits.begin() + bstart);
/* Make b the shortest operand */
if(aLength < bLength)
return(Add(b, a, rstart, rend, bstart, bend, astart, aend));
/* Now do the first part of the addition, involving both a and b
*/
Digit carry(0);
for(std::size_t i(0);i<bLength && i<rLength;++i,++ri,++ai,++bi)
*ri = DigitAdd(*ai, *bi, &carry);
/* Now do the second part of the addition, involving only a,
* if necessary.
*/
for(std::size_t i(bLength);i<aLength && i<rLength;++i,++ri,++ai)
*ri = DigitAdd(*ai, 0, &carry);
/* Now do the third and final part of the addition, which
* just pads the result with zeroes and propagates the carry,
* if necessary.
*/
for(std::size_t i(aLength);i<rLength;++i,++ri)
{
*ri = carry;
carry = 0;
}
/* Done! */
return(carry);
}
---