libc++: First cut at <dynarray>

Richard Smith richard at
Mon Sep 9 15:57:30 PDT 2013

On Mon, Sep 9, 2013 at 3:32 PM, Marshall Clow <mclow.lists at> wrote:

> On Sep 9, 2013, at 11:59 AM, Richard Smith <richard at> wrote:
> On Mon, Sep 9, 2013 at 9:06 AM, Marshall Clow <mclow.lists at>
>  wrote:
>> <dynarray> See
>> Open Issues:
>> 1) This includes <tuple> because that's where __uses_alloc_ctor lives.
>> I'm thinking that __uses_alloc_ctor should be hoisted into a common header.
>> Maybe __functional_base.
>> 2) This includes a general implementation of user-allocator construction
>> (named __user_alloc_construct). This should probably be hoisted as well;
>> and possibly the code in scoped_allocator can be reworked to use it (if it
>> simplifies things).
>> 3) There's no support for stack allocations at present; that requires
>> compiler support. I'm working with some people on getting that into clang.
>> 4) There's an awful lot of duplication in the (many, many) constructors.
> It's not obvious to me that the behavior of max_size is correct.
> What do you suggest it return?
> It returns the current size of the array - and that's the max size that
> array can be.
> [ This is the same behavior as std::array, btw ]

It's not obvious to me =)

The choices seem to either be that max_size() returns size() (the largest
size for that *instance*), or that it returns the largest size that will
not throw std::bad_array_length (the largest size for that *type*). It
seems somewhat pointless to me to even have such a member, though. What's
it for? (What generic code that operates on containers would care?)

For std::array, the case seems much clearer-cut, since the largest size for
an instance is the same as the largest size for the type.

Here's the closest I've been able to find to a use case:

bool destructive_resize_dynarray(std::dynarray<int> &arr, size_type n) {
  if (n >= arr.max_size()) return false;

  new (&arr) std::dynarray<int>;
  return true;

> To my reading, __allocate is required to throw std::bad_array_length if
> the multiplication overflows.
> Yes. Nice catch.
> This led me down a bit of a rathole, b/c libc++ hasn't implemented
> std::bad_array_length yet.
> I'll have a (separate) patch for that up in a bit.
> Your reinterpret_casts from void* to (const) _Tp* could be static_casts.
> Fixed.
> The constructor overloads look... horribly broken. This won't work:
>   std::dynarray<long> arr(20, 0);
> ... because it picks the (size_t, const _Alloc&) constructor, not the
> (size_t, const value_type&) constructor. Is there an LWG issue for that?
> No, actually, it picks the right version; but I've added that exact case
> to the test suite.

It picks this constructor: dynarray(size_t, const _Alloc&), with
_Alloc=int, which is a better match than the intended dynarray(size_t,
const long&). This:

int main() {
  std::dynarray<long> dl(20, 3);
  return dl[0];

returns 0, not 3. (The "allocator" argument 3 is *silently ignored* because
'long' doesn't have an allocator-taking constructor.)

> I wouldn't mind some SFINAE here for the "Allocator" routines, though.
> I need a good "is_allocator" template metafunction.
> Thanks for the review.
> -- Marshall
> Marshall Clow     Idio Software   <mailto:mclow.lists at<mclow.lists at>
> >
> A.D. 1517: Martin Luther nails his 95 Theses to the church door and is
> promptly moderated down to (-1, Flamebait).
>         -- Yu Suzuki
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the cfe-commits mailing list