Skip to content

Commit de51b31

Browse files
authored
Merge pull request #4987 from ntrel/appender-docs
Improve docs for Appender, RefAppender
2 parents c0b6660 + a17204a commit de51b31

File tree

1 file changed

+57
-69
lines changed

1 file changed

+57
-69
lines changed

std/array.d

Lines changed: 57 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -2645,15 +2645,18 @@ body
26452645

26462646
/**
26472647
Implements an output range that appends data to an array. This is
2648-
recommended over $(D a ~= data) when appending many elements because it is more
2649-
efficient.
2648+
recommended over $(D array ~= data) when appending many elements because it is more
2649+
efficient. `Appender` maintains its own array metadata locally, so it can avoid
2650+
global locking for each append where $(LREF capacity) is non-zero.
2651+
See_Also: $(LREF appender)
26502652
*/
26512653
struct Appender(A)
26522654
if (isDynamicArray!A)
26532655
{
26542656
import core.memory : GC;
26552657

26562658
private alias T = ElementEncodingType!A;
2659+
26572660
private struct Data
26582661
{
26592662
size_t capacity;
@@ -2664,12 +2667,12 @@ if (isDynamicArray!A)
26642667
private Data* _data;
26652668

26662669
/**
2667-
* Construct an appender with a given array. Note that this does not copy the
2668-
* data. If the array has a larger capacity as determined by arr.capacity,
2670+
* Constructs an `Appender` with a given array. Note that this does not copy the
2671+
* data. If the array has a larger capacity as determined by `arr.capacity`,
26692672
* it will be used by the appender. After initializing an appender on an array,
26702673
* appending to the original array will reallocate.
26712674
*/
2672-
this(T[] arr) @trusted pure nothrow
2675+
this(A arr) @trusted pure nothrow
26732676
{
26742677
// initialize to a given array.
26752678
_data = new Data;
@@ -2694,7 +2697,7 @@ if (isDynamicArray!A)
26942697

26952698
/**
26962699
* Reserve at least newCapacity elements for appending. Note that more elements
2697-
* may be reserved than requested. If newCapacity <= capacity, then nothing is
2700+
* may be reserved than requested. If `newCapacity <= capacity`, then nothing is
26982701
* done.
26992702
*/
27002703
void reserve(size_t newCapacity) @safe pure nothrow
@@ -2723,7 +2726,7 @@ if (isDynamicArray!A)
27232726
/**
27242727
* Returns the managed array.
27252728
*/
2726-
@property inout(T)[] data() inout @trusted pure nothrow
2729+
@property inout(ElementEncodingType!A)[] data() inout @trusted pure nothrow
27272730
{
27282731
/* @trusted operation:
27292732
* casting Unqual!T[] to inout(T)[]
@@ -2815,7 +2818,7 @@ if (isDynamicArray!A)
28152818
}
28162819

28172820
/**
2818-
* Appends one item to the managed array.
2821+
* Appends `item` to the managed array.
28192822
*/
28202823
void put(U)(U item) if (canPutItem!U)
28212824
{
@@ -2888,7 +2891,7 @@ if (isDynamicArray!A)
28882891
alias UT = Unqual!T;
28892892

28902893
static if (is(typeof(_data.arr[] = items[])) &&
2891-
!hasElaborateAssign!(Unqual!T) && isAssignable!(UT, ElementEncodingType!Range))
2894+
!hasElaborateAssign!UT && isAssignable!(UT, ElementEncodingType!Range))
28922895
{
28932896
bigData[len .. newlen] = items[];
28942897
}
@@ -2917,25 +2920,14 @@ if (isDynamicArray!A)
29172920
}
29182921

29192922
/**
2920-
* Appends one item to the managed array.
2921-
*/
2922-
void opOpAssign(string op : "~", U)(U item) if (canPutItem!U)
2923-
{
2924-
put(item);
2925-
}
2926-
2927-
// Const fixing hack.
2928-
void opOpAssign(string op : "~", Range)(Range items) if (canPutConstRange!Range)
2929-
{
2930-
put(items);
2931-
}
2932-
2933-
/**
2934-
* Appends an entire range to the managed array.
2923+
* Appends `rhs` to the managed array.
2924+
* Params:
2925+
* rhs = Element or range.
29352926
*/
2936-
void opOpAssign(string op : "~", Range)(Range items) if (canPutRange!Range)
2927+
void opOpAssign(string op : "~", U)(U rhs)
2928+
if (__traits(compiles, put(rhs)))
29372929
{
2938-
put(items);
2930+
put(rhs);
29392931
}
29402932

29412933
// only allow overwriting data on non-immutable and non-const data
@@ -2945,7 +2937,7 @@ if (isDynamicArray!A)
29452937
* Clears the managed array. This allows the elements of the array to be reused
29462938
* for appending.
29472939
*
2948-
* Note that clear is disabled for immutable or const element types, due to the
2940+
* Note: clear is disabled for immutable or const element types, due to the
29492941
* possibility that $(D Appender) might overwrite immutable data.
29502942
*/
29512943
void clear() @trusted pure nothrow
@@ -2960,6 +2952,7 @@ if (isDynamicArray!A)
29602952
* Shrinks the managed array to the given length.
29612953
*
29622954
* Throws: $(D Exception) if newlength is greater than the current array length.
2955+
* Note: shrinkTo is disabled for immutable or const element types.
29632956
*/
29642957
void shrinkTo(size_t newlength) @trusted pure
29652958
{
@@ -3027,68 +3020,63 @@ private size_t appenderNewCapacity(size_t TSizeOf)(size_t curLen, size_t reqLen)
30273020
}
30283021

30293022
/**
3030-
* An appender that can update an array in-place. It forwards all calls to an
3031-
* underlying appender implementation. Any calls made to the appender also update
3032-
* the pointer to the original array passed in.
3023+
* A version of $(LREF Appender) that can update an array in-place.
3024+
* It forwards all calls to an underlying appender implementation.
3025+
* Any calls made to the appender also update the pointer to the
3026+
* original array passed in.
3027+
*
3028+
* Tip: Use the `arrayPtr` overload of $(LREF appender) for construction with type-inference.
30333029
*/
30343030
struct RefAppender(A)
30353031
if (isDynamicArray!A)
30363032
{
30373033
private
30383034
{
3039-
alias T = ElementEncodingType!A;
30403035
Appender!A impl;
3041-
T[] *arr;
3036+
A* arr;
30423037
}
30433038

30443039
/**
3045-
* Construct a ref appender with a given array reference. This does not copy the
3046-
* data. If the array has a larger capacity as determined by arr.capacity, it
3047-
* will be used by the appender. $(D RefAppender) assumes that arr is a non-null
3048-
* value.
3040+
* Constructs a `RefAppender` with a given array reference. This does not copy the
3041+
* data. If the array has a larger capacity as determined by `arr.capacity`, it
3042+
* will be used by the appender.
3043+
*
3044+
* Note: Do not use built-in appending (i.e. `~=`) on the original array
3045+
* until you are done with the appender, because subsequent calls to the appender
3046+
* will reallocate the array data without those appends.
30493047
*
3050-
* Note, do not use builtin appending (i.e. ~=) on the original array passed in
3051-
* until you are done with the appender, because calls to the appender override
3052-
* those appends.
3048+
* Params:
3049+
* arr = Pointer to an array. Must not be _null.
30533050
*/
3054-
this(T[] *arr)
3051+
this(A* arr)
30553052
{
30563053
impl = Appender!A(*arr);
30573054
this.arr = arr;
30583055
}
30593056

3060-
void opDispatch(string fn, Args...)(Args args) if (is(typeof(mixin("impl." ~ fn ~ "(args)"))))
3057+
/** Wraps remaining `Appender` methods such as $(LREF put).
3058+
* Params:
3059+
* fn = Method name to call.
3060+
* args = Arguments to pass to the method.
3061+
*/
3062+
void opDispatch(string fn, Args...)(Args args)
3063+
if (__traits(compiles, (Appender!A a) => mixin("a." ~ fn ~ "(args)")))
30613064
{
30623065
// we do it this way because we can't cache a void return
30633066
scope(exit) *this.arr = impl.data;
30643067
mixin("return impl." ~ fn ~ "(args);");
30653068
}
30663069

3067-
private alias AppenderType = Appender!A;
3068-
30693070
/**
3070-
* Appends one item to the managed array.
3071-
*/
3072-
void opOpAssign(string op : "~", U)(U item) if (AppenderType.canPutItem!U)
3073-
{
3074-
scope(exit) *this.arr = impl.data;
3075-
impl.put(item);
3076-
}
3077-
3078-
// Const fixing hack.
3079-
void opOpAssign(string op : "~", Range)(Range items) if (AppenderType.canPutConstRange!Range)
3080-
{
3081-
scope(exit) *this.arr = impl.data;
3082-
impl.put(items);
3083-
}
3084-
3085-
/**
3086-
* Appends an entire range to the managed array.
3071+
* Appends `rhs` to the managed array.
3072+
* Params:
3073+
* rhs = Element or range.
30873074
*/
3088-
void opOpAssign(string op : "~", Range)(Range items) if (AppenderType.canPutRange!Range)
3075+
void opOpAssign(string op : "~", U)(U rhs)
3076+
if (__traits(compiles, (Appender!A a){ a.put(rhs); }))
30893077
{
30903078
scope(exit) *this.arr = impl.data;
3091-
impl.put(items);
3079+
impl.put(rhs);
30923080
}
30933081

30943082
/**
@@ -3104,15 +3092,15 @@ if (isDynamicArray!A)
31043092
/**
31053093
* Returns the managed array.
31063094
*/
3107-
@property inout(T)[] data() inout
3095+
@property inout(ElementEncodingType!A)[] data() inout
31083096
{
31093097
return impl.data;
31103098
}
31113099
}
31123100

31133101
/++
3114-
Convenience function that returns an $(D Appender!A) object initialized
3115-
with $(D array).
3102+
Convenience function that returns an $(LREF Appender) instance,
3103+
optionally initialized with $(D array).
31163104
+/
31173105
Appender!A appender(A)()
31183106
if (isDynamicArray!A)
@@ -3486,13 +3474,13 @@ Appender!(E[]) appender(A : E[], E)(auto ref A array)
34863474
}
34873475

34883476
/++
3489-
Convenience function that returns a $(D RefAppender!A) object initialized
3490-
with $(D array). Don't use null for the $(D array) pointer, use the other
3477+
Convenience function that returns a $(LREF RefAppender) instance initialized
3478+
with `arrayPtr`. Don't use null for the array pointer, use the other
34913479
version of $(D appender) instead.
34923480
+/
3493-
RefAppender!(E[]) appender(A : E[]*, E)(A array)
3481+
RefAppender!(E[]) appender(P : E[]*, E)(P arrayPtr)
34943482
{
3495-
return RefAppender!(E[])(array);
3483+
return RefAppender!(E[])(arrayPtr);
34963484
}
34973485

34983486
@system unittest

0 commit comments

Comments
 (0)