Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.

Commit 6dd113d

Browse files
authored
Merge pull request #2708 from TurkeyMan/std_vector
std::vector fixes merged-on-behalf-of: Nicholas Wilson <thewilsonator@users.noreply.github.com>
2 parents 54aef83 + 8891e79 commit 6dd113d

File tree

3 files changed

+158
-45
lines changed

3 files changed

+158
-45
lines changed

src/core/stdcpp/vector.d

Lines changed: 50 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,6 @@ extern(D):
5050
///
5151
alias const_pointer = const(T)*;
5252

53-
///
54-
alias as_array this;
55-
5653
/// MSVC allocates on default initialisation in debug, which can't be modelled by D `struct`
5754
@disable this();
5855

@@ -62,27 +59,52 @@ extern(D):
6259
alias opDollar = length;
6360

6461
///
65-
ref inout(T) front() inout pure nothrow @safe @nogc { return this[0]; }
62+
size_t[2] opSlice(size_t dim : 0)(size_t start, size_t end) const pure nothrow @safe @nogc { return [start, end]; }
63+
64+
///
65+
ref inout(T) opIndex(size_t index) inout pure nothrow @safe @nogc { return as_array[index]; }
66+
///
67+
inout(T)[] opIndex(size_t[2] slice) inout pure nothrow @safe @nogc { return as_array[slice[0] .. slice[1]]; }
6668
///
67-
ref inout(T) back() inout pure nothrow @safe @nogc { return this[$-1]; }
69+
inout(T)[] opIndex() inout pure nothrow @safe @nogc { return as_array(); }
6870

71+
///
72+
ref vector opAssign(U)(auto ref vector!(U, Alloc) s) { opAssign(s.as_array); return this; }
73+
///
74+
ref vector opAssign(T[] array)
75+
{
76+
clear();
77+
reserve(array.length);
78+
insert(0, array);
79+
return this;
80+
}
6981

70-
// WIP...
82+
///
83+
void opIndexAssign()(auto ref T val, size_t index) { as_array[index] = val; }
84+
///
85+
void opIndexAssign()(auto ref T val, size_t[2] slice) { as_array[slice[0] .. slice[1]] = val; }
86+
///
87+
void opIndexAssign(T[] val, size_t[2] slice) { as_array[slice[0] .. slice[1]] = val[]; }
88+
///
89+
void opIndexAssign()(auto ref T val) { as_array[] = val; }
90+
///
91+
void opIndexAssign(T[] val) { as_array[] = val[]; }
7192

72-
// this(size_type count);
73-
// this(size_type count, ref const(value_type) val);
74-
// this(size_type count, ref const(value_type) val, ref const(allocator_type) al);
75-
// this(ref const(vector) x);
76-
// this(iterator first, iterator last);
77-
// this(iterator first, iterator last, ref const(allocator_type) al = defaultAlloc);
78-
// this(const_iterator first, const_iterator last);
79-
// this(const_iterator first, const_iterator last, ref const(allocator_type) al = defaultAlloc);
80-
// this(T[] arr) { this(arr.ptr, arr.ptr + arr.length); }
81-
// this(T[] arr, ref const(allocator_type) al = defaultAlloc) { this(arr.ptr, arr.ptr + arr.length); }
82-
// this(const(T)[] arr) { this(arr.ptr, arr.ptr + arr.length); }
83-
// this(const(T)[] arr, ref const(allocator_type) al = defaultAlloc) { this(arr.ptr, arr.ptr + arr.length); }
93+
///
94+
void opIndexOpAssign(string op)(auto ref T val, size_t index) { mixin("as_array[index] " ~ op ~ "= val;"); }
95+
///
96+
void opIndexOpAssign(string op)(auto ref T val, size_t[2] slice) { mixin("as_array[slice[0] .. slice[1]] " ~ op ~ "= val;"); }
97+
///
98+
void opIndexOpAssign(string op)(T[] val, size_t[2] slice) { mixin("as_array[slice[0] .. slice[1]] " ~ op ~ "= val[];"); }
99+
///
100+
void opIndexOpAssign(string op)(auto ref T val) { mixin("as_array[] " ~ op ~ "= val;"); }
101+
///
102+
void opIndexOpAssign(string op)(T[] val) { mixin("as_array[] " ~ op ~ "= val[];"); }
84103

85-
// ref vector opAssign(ref const(vector) s);
104+
///
105+
ref inout(T) front() inout pure nothrow @safe @nogc { return as_array[0]; }
106+
///
107+
ref inout(T) back() inout pure nothrow @safe @nogc { return as_array[$-1]; }
86108

87109
///
88110
ref vector opOpAssign(string op : "~")(auto ref T item) { push_back(forward!item); return this; }
@@ -109,7 +131,7 @@ extern(D):
109131
///
110132
this(DefaultConstruct) @nogc { _Alloc_proxy(); }
111133
///
112-
this(size_t count)
134+
this()(size_t count)
113135
{
114136
_Alloc_proxy();
115137
_Buy(count);
@@ -125,7 +147,7 @@ extern(D):
125147
_Get_data()._Mylast = _Ufill(_Get_data()._Myfirst, count, val);
126148
}
127149
///
128-
this(T[] array)
150+
this()(T[] array)
129151
{
130152
_Alloc_proxy();
131153
_Buy(array.length);
@@ -209,16 +231,17 @@ extern(D):
209231
}
210232

211233
///
212-
void clear() nothrow
234+
void clear()
213235
{
214236
_Base._Orphan_all();
215237
_Destroy(_Get_data()._Myfirst, _Get_data()._Mylast);
216238
_Get_data()._Mylast = _Get_data()._Myfirst;
217239
}
218240

219241
///
220-
void resize(const size_type newsize)
242+
void resize()(const size_type newsize)
221243
{
244+
static assert(is(typeof({static T i;})), T.stringof ~ ".this() is annotated with @disable.");
222245
_Resize(newsize, (pointer _Dest, size_type _Count) => _Udefault(_Dest, _Count));
223246
}
224247

@@ -267,7 +290,7 @@ extern(D):
267290
// nothing to do, avoid invalidating iterators
268291
}
269292
else if (_Count > _Unused_capacity())
270-
{ // reallocate
293+
{ // reallocate
271294
const size_type _Oldsize = size();
272295

273296
// if (_Count > max_size() - _Oldsize)
@@ -306,7 +329,7 @@ extern(D):
306329
_Change_array(_Newvec, _Newsize, _Newcapacity);
307330
}
308331
else
309-
{ // Attempt to provide the strong guarantee for EmplaceConstructible failure.
332+
{ // Attempt to provide the strong guarantee for EmplaceConstructible failure.
310333
// If we encounter copy/move construction/assignment failure, provide the basic guarantee.
311334
// (For one-at-back, this provides the strong guarantee.)
312335

@@ -347,7 +370,7 @@ extern(D):
347370
}
348371
}
349372
else
350-
{ // affected elements don't overlap before/after
373+
{ // affected elements don't overlap before/after
351374
pointer _Relocated = _Where + _Count;
352375
_Get_data()._Mylast = _Utransfer!true(_Where, _Oldlast, _Relocated);
353376
_Destroy(_Where, _Oldlast);
@@ -650,7 +673,7 @@ extern(D):
650673
_Backout._Emplace_back(val);
651674
return _Backout._Release();
652675
}
653-
pointer _Udefault(pointer _Dest, size_t _Count)
676+
pointer _Udefault()(pointer _Dest, size_t _Count)
654677
{
655678
// TODO: if zero init, then fast-path to zeromem
656679
auto _Backout = _Uninitialized_backout(_Dest);
@@ -716,10 +739,6 @@ extern(D):
716739
{
717740
static assert(false, "C++ runtime not supported");
718741
}
719-
720-
private:
721-
// HACK: because no rvalue->ref
722-
__gshared static immutable allocator_type defaultAlloc;
723742
}
724743

725744

test/stdcpp/src/vector.cpp

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,60 @@
11
#include <vector>
22

3+
extern int vectorTest_numAllocated;
4+
5+
struct NotPOD
6+
{
7+
NotPOD() = delete;
8+
NotPOD(int a)
9+
{
10+
for (int i = 0; i < 5; ++i)
11+
x[i] = a + i + 1;
12+
wasInit = true;
13+
++vectorTest_numAllocated;
14+
}
15+
NotPOD(const NotPOD& rh)
16+
{
17+
for (int i = 0; i < 5; ++i)
18+
x[i] = rh.x[i];
19+
wasInit = rh.wasInit;
20+
if (rh.wasInit)
21+
++vectorTest_numAllocated;
22+
}
23+
NotPOD(NotPOD&& rh)
24+
{
25+
for (int i = 0; i < 5; ++i)
26+
x[i] = rh.x[i];
27+
wasInit = rh.wasInit;
28+
rh.wasInit = false;
29+
}
30+
~NotPOD()
31+
{
32+
if (wasInit)
33+
--vectorTest_numAllocated;
34+
}
35+
36+
int x[5];
37+
bool wasInit;
38+
};
39+
340
int fromC_val(std::vector<int>);
441
int fromC_ref(const std::vector<int>&);
42+
int fromC_nonPod_val(std::vector<NotPOD>);
543

6-
int sumOfElements_ref(const std::vector<int>& arr)
44+
int sumOfElements_ref(const std::vector<int>& vec)
745
{
846
int r = 0;
9-
for (std::size_t i = 0; i < arr.size(); ++i)
10-
r += arr[i];
47+
for (std::size_t i = 0; i < vec.size(); ++i)
48+
r += vec[i];
1149
return r;
1250
}
1351

14-
int sumOfElements_val(std::vector<int> arr)
52+
int sumOfElements_val(std::vector<int> vec)
53+
{
54+
return sumOfElements_ref(vec) + fromC_ref(vec) + fromC_val(vec);
55+
}
56+
57+
int nonPod_val(std::vector<NotPOD> vec)
1558
{
16-
return sumOfElements_ref(arr) + fromC_ref(arr) + fromC_val(arr);
59+
return vec.size() == 3 && vec[2].x[0] == 4 && fromC_nonPod_val(vec);
1760
}

test/stdcpp/src/vector_test.d

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
import core.stdcpp.vector;
22

3-
struct CustomInit
4-
{
5-
int x = 10;
6-
}
7-
83
unittest
94
{
105
// test vector a bit
@@ -46,25 +41,76 @@ unittest
4641
vec = vector!int([1, 2, 3, 4]);
4742
vec2 = vec;
4843
assert(vec2[] == [1, 2, 3, 4]);
44+
vec = [1, 2, 3];
45+
assert(vec[] == [1, 2, 3]);
46+
vec[] = 0;
47+
assert(vec[] == [0, 0, 0]);
4948

5049
vec2.emplace(1, 10);
51-
vec2.emplace(3, 20);
50+
vec2.emplace(3, 0);
51+
vec2[3] = 20;
52+
vec2[4 .. 6] = [8, 9];
53+
vec2[1] *= 10;
5254
vec2[4 .. 6] *= 10;
53-
assert(vec2[] == [1, 10, 2, 20, 30, 40]);
55+
vec2[3 .. 5] *= [10, 100];
56+
vec2[] *= 2;
57+
vec2[] *= [10, 1, 10, 1, 1, 2];
58+
assert(vec2[] == [20, 200, 40, 400, 16000, 360]);
5459

5560
// test local instantiations...
5661
// there's no vector<float> instantiation in C++
5762
vector!CustomInit vec3 = vector!CustomInit(1);
5863
vec3.push_back(CustomInit(1));
5964
assert(vec3[0].x == 10 && vec3[1].x == 1);
65+
66+
// test out a non-pod type...
67+
{
68+
auto vec4 = vector!NotPOD(2, NotPOD(2));
69+
vec4.push_back(NotPOD(3));
70+
assert(nonPod_val(vec4) == 1);
71+
}
72+
assert(vectorTest_numAllocated == 0);
73+
}
74+
75+
struct CustomInit
76+
{
77+
int x = 10;
6078
}
6179

6280

6381
extern(C++):
6482

83+
__gshared int vectorTest_numAllocated = 0;
84+
85+
struct NotPOD
86+
{
87+
this() @disable;
88+
this(int a)
89+
{
90+
x[] = [a+1, a+2, a+3, a+4, a+5];
91+
wasInit = true;
92+
++vectorTest_numAllocated;
93+
}
94+
this(this)
95+
{
96+
if (wasInit)
97+
++vectorTest_numAllocated;
98+
}
99+
~this()
100+
{
101+
if (wasInit)
102+
--vectorTest_numAllocated;
103+
}
104+
105+
int[5] x = [1, 2, 3, 4, 5];
106+
bool wasInit;
107+
}
108+
65109
// test the ABI for calls to C++
66110
int sumOfElements_val(vector!int vec);
67111
int sumOfElements_ref(ref const(vector!int) vec);
112+
int nonPod_val(vector!NotPOD vec);
113+
68114

69115
// test the ABI for calls from C++
70116
int fromC_val(vector!int vec)
@@ -74,7 +120,7 @@ int fromC_val(vector!int vec)
74120
assert(vec.back == 5);
75121

76122
int r;
77-
foreach (e; vec)
123+
foreach (e; vec[])
78124
r += e;
79125

80126
assert(r == 15);
@@ -84,7 +130,12 @@ int fromC_val(vector!int vec)
84130
int fromC_ref(ref const(vector!int) vec)
85131
{
86132
int r;
87-
foreach (e; vec)
133+
foreach (e; vec[])
88134
r += e;
89135
return r;
90136
}
137+
138+
int fromC_nonPod_val(vector!NotPOD vec)
139+
{
140+
return vec.size() == 3 && vec[1].x[4] == 7;
141+
}

0 commit comments

Comments
 (0)