$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
Subject: Re: [boost] Interest in StaticVector - fixed capacity vector
From: Andrew Hundt (athundt_at_[hidden])
Date: 2011-10-11 12:22:40
>
>
> BOOST_THROW_EXCEPTION can be set to call a user defined function
> boost_throw_exception, I am unaware of BOOST_THROW_EXCEPTION calling
> exit(). The real issue is that even setting BOOST_NO_EXCEPTION and
> BOOST_EXCEPTION_DISABLE, the user of a library is still required to
> defined the boost_throw_exception function EVEN if the user checks that
> calls are valid, i.e. the user performs their own capacitycheck and
> rangecheck prior to calling.
I can understand the desire to reduce the constant calls to capacitycheck, I
need to give this some thought. This seems like a design choices that is
common enough to have a convention. Is anyone aware of one?
> This means that you cannot compile up a
> library including StaticVector without exceptions without defining
> boost_throw_exception, even though because you check conditions prior to
> calling functions. This pollutes the library unnecessarily, and means
> users of a library that uses StaticVector have to provide a function
> that is not used (boost_throw_exception) or that if they have defined it
> for their own needs then it is somewhat concerning that an imported
> library may appear to want to call it. Both of these are bad, and the
> same issue exists inside boost::function.
Calls to boost::throw_exception also exists in boost.array. I'm not sure
defining boost::throw_exception is an overly onerous requirement for when
exceptions are disabled, and it seems to be a somewhat widely used
convention within boost.
> To resolve this it would be
> useful to have an extension to the interface in some form to allow a
> pushing and popping action to occur without a range/capacity check
> function that can throw, but I would like to propose that an assert is
> called instead.
Since my goal is to provide a mix of the functionality in boost.array and
std::vector, I have matched their interface whenever possible. I don't find
it unreasonable to call BOOST_THROW_EXCEPTION, because it is done in
boost.array. Actually, they call boost::throw_exception, but my
understanding is that the end effect is comparable.
> To maintain safety the checking functions could return
> success/failure, and the calling functions maintain the object's state
> invariants based upon the return code.
>
> Alternatively the push/pop functions could also return bool signifying
> success/failure.
>
The definition of push_back for std::vector is:
void push_back ( const T& x );
which is why I chose to go with the same interface.
>
> In looking at this I also note that there is a StaticVector( Iter begin,
> Iter end ) that calls capacitycheck(). This then potentially throws, is
> this truly desirable in a constructor? I see in a number of places where
> the StaticVector is essentially copying from another unknown storage
> class that could be larger than the StatcVector that it also could
> throw, did you consider merely copying all that could be copied? i.e.
> the first N objects are copied. I can't think if that would be better or
> worse?
Am I correct that insert(pos,first,last) can achieve that purpose? Nasty,
difficult to find bugs would occur if someone makes an error and only the
first N objects are copied silently when they expect all objects to be
copied. Scott Meyers' wonderful Effective C++ third edition, Item 18 "make
interfaces easy to use correctly and hard to use incorrectly" provides a
good explanation of this type of choice.
> Ps. As an aside the capacity check function could be static.
>
>
You are correct, capacitycheck should be static. Thanks for finding that.
Thanks for the time and consideration you have given the implementation.
Cheers!
Andrew Hundt