1 /** 2 Implementation of dynamic array `Vector` (similar to c++ `std::vector` and `folly::small_vector`). 3 4 License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 5 Authors: Adam Búš 6 */ 7 module btl.vector; 8 9 import std.traits : Unqual, Unconst, isSomeChar, isSomeString, CopyTypeQualifiers; 10 import std.meta : AliasSeq; 11 import std.traits : Select; 12 13 import btl.traits.common; 14 import btl.traits.range; 15 import btl.lifetime; 16 17 import btl.internal.traits; 18 import btl.internal.allocator; 19 import btl.internal.gc; 20 21 import btl.vector.storage; 22 23 24 /** 25 Type used in forward constructors. 26 */ 27 alias Forward = btl.traits.common.Forward; 28 29 30 /** 31 Default allcoator for `Vector`. 32 */ 33 public alias DefaultAllocator = Mallocator; 34 35 36 /** 37 True if `T` is a `Vector` or implicitly converts to one, otherwise false. 38 */ 39 template isVector(T...) 40 if(T.length == 1){ 41 enum bool isVector = is(Unqual!(T[0]) == Vector!Args, Args...); 42 } 43 44 45 /** 46 `Vector`s are sequence containers representing arrays that can change in size. 47 48 Just like arrays, vectors use contiguous storage locations for their elements, which means that their elements can also be accessed using offsets on regular pointers to its elements, and just as efficiently as in arrays. But unlike arrays, their size can change dynamically, with their storage being handled automatically by the container. 49 50 Instead, vector containers may allocate some extra storage to accommodate for possible growth, and thus the container may have an actual capacity greater than the storage strictly needed to contain its elements (i.e., its size). Libraries can implement different strategies for growth to balance between memory usage and reallocations, but in any case, reallocations should only happen at logarithmically growing intervals of size so that the insertion of individual elements at the end of the vector can be provided with amortized constant time complexity (see push_back). 51 52 Therefore, compared to arrays, vectors consume more memory in exchange for the ability to manage storage and grow dynamically in an efficient way. 53 54 `Vector` can have preallocated (stack) space for `N` elements. 55 56 Template parameters: 57 58 `_Type` = element type. 59 60 `N` Number of preallocated space for elements. 61 62 `_Allocator` Type of the allocator object used to define the storage allocation model. By default `DefaultAllocator` is used. 63 64 65 @safe: 66 67 * Inserting element to `Vector` pointer is @safe if constructor of element is @safe (assumption is that constructor doesn't leak `this` pointer). 68 69 * `Vector` assume that deallocation with custom allocator is @safe if allocation is @safe even if method `deallcoate` is @system. 70 71 * Methods returning reference/pointer/slice (`front()`, `back()`, `ptr()`, `elements()`, `opSlice()`, ...) to vector elements are all @system because increasing capacity of vector can realocate all elements to new memory location and invalidate external references to old location. 72 73 74 `scope` and -dip1000: 75 76 * `Vector` assume that managed object have global lifetime (scope can be ignored). 77 78 * Functions for inserting elements to vector have non `scope` parameters (global lifetime). 79 */ 80 template Vector( 81 _Type, 82 size_t N = 0, 83 _Allocator = DefaultAllocator, 84 bool _supportGC = shouldAddGCRange!_Type 85 ){ 86 87 import core.lifetime : emplace, forward, move; 88 import std.range : empty, front, popFront, ElementEncodingType, hasLength; 89 import std.traits : Unqual, hasElaborateDestructor, hasIndirections, isDynamicArray; 90 91 alias Storage = .Storage!(_Type, N, _allowHeap); 92 93 enum bool _hasStatelessAllocator = isStatelessAllocator!_Allocator; 94 enum bool _allowHeap = !is(immutable _Allocator == immutable void); 95 96 struct Vector{ 97 98 /** 99 True if allocator doesn't have state. 100 */ 101 public alias hasStatelessAllocator = _hasStatelessAllocator; 102 103 104 105 /** 106 Type of elements. 107 */ 108 public alias ElementType = _Type; 109 110 111 112 /** 113 Type of reference to elements. 114 */ 115 public alias ElementReferenceType = ElementReferenceTypeImpl!_Type; 116 117 118 119 /** 120 Type of the allocator object used to define the storage allocation model. By default `DefaultAllocator` is used. 121 */ 122 public alias AllocatorType = _Allocator; 123 124 125 126 /** 127 */ 128 public alias supportGC = _supportGC; 129 130 131 132 /** 133 Allow heap (`false` only if `Allcoator` is void) 134 */ 135 public alias allowHeap = _allowHeap; 136 137 138 139 /** 140 Maximal capacity of vector, in terms of number of elements. 141 */ 142 public alias maximalCapacity = Storage.maximalCapacity; 143 144 145 146 /** 147 Minimal capacity of vector, in terms of number of elements. 148 149 Examples: 150 -------------------- 151 Vector!(int, 10) vec; 152 assert(vec.capacity == typeof(vec).minimalCapacity); 153 assert(vec.capacity == 10); 154 -------------------- 155 */ 156 public alias minimalCapacity = Storage.minimalCapacity; 157 158 159 160 /** 161 Returns copy of allocator. 162 */ 163 public @property CopyTypeQualifiers!(This, AllocatorType) allocator(this This)()scope{ 164 static if(allowHeap) 165 return *(()@trusted => &this._allocator )(); 166 else 167 return; 168 } 169 170 171 172 /** 173 Returns whether the vector is empty (i.e. whether its length is 0). 174 175 Examples: 176 -------------------- 177 Vector!(int, 10) vec; 178 assert(vec.empty); 179 180 vec.append(42); 181 assert(!vec.empty); 182 -------------------- 183 */ 184 public @property bool empty()const scope pure nothrow @safe @nogc{ 185 return (this.length == 0); 186 } 187 188 189 190 /** 191 Returns whether the vector is full (i.e. whether its length is equal to maximalCapacity). 192 193 Examples: 194 -------------------- 195 Vector!(int, 4, void) vec; //FixedVector 196 assert(vec.empty); 197 assert(vec.maximalCapacity == vec.minimalCapacity); 198 199 vec.resize(vec.maximalCapacity); 200 assert(vec.full); 201 -------------------- 202 */ 203 public @property bool full()const scope pure nothrow @safe @nogc{ 204 return (this.length == maximalCapacity); 205 } 206 207 208 209 /** 210 Returns the length of the vector, in terms of number of elements. 211 212 This is the number of actual elements that conform the contents of the `Vector`, which is not necessarily equal to its storage capacity. 213 214 Examples: 215 -------------------- 216 Vector!(int, 10) vec = null; 217 assert(vec.length == 0); 218 219 vec.append(42); 220 assert(vec.length == 1); 221 222 vec.append(123); 223 assert(vec.length == 2); 224 225 vec.clear(); 226 assert(vec.length == 0); 227 -------------------- 228 */ 229 public @property size_t length()const scope pure nothrow @safe @nogc{ 230 return this.storage.length; 231 } 232 233 234 235 /** 236 Returns the size of the storage space currently allocated for the `Vector`. 237 238 This capacity is not necessarily equal to the vector length. It can be equal or greater, with the extra space allowing the object to optimize its operations when new elements are added to the `Vector`. 239 240 Notice that this capacity does not suppose a limit on the length of the `Vector`. When this capacity is exhausted and more is needed, it is automatically expanded by the object (reallocating it storage space). 241 242 The capacity of a `Vector` can be altered any time the object is modified, even if this modification implies a reduction in size. 243 244 The capacity of a `Vector` can be explicitly altered by calling member `reserve`. 245 246 Examples: 247 -------------------- 248 Vector!(int, 10) vec; 249 assert(vec.capacity == typeof(vec).minimalCapacity); 250 251 vec.reserve(vec.capacity * 2); 252 assert(vec.capacity > typeof(vec).minimalCapacity); 253 -------------------- 254 */ 255 public @property size_t capacity()const scope pure nothrow @trusted @nogc{ 256 return this.storage.capacity; 257 } 258 259 260 261 /** 262 Return pointer to the first element. 263 264 The pointer returned may be invalidated by further calls to other member functions that modify the object. 265 266 Examples: 267 -------------------- 268 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3); 269 270 assert(vec.ptr[0 .. 3] == [1, 2, 3]); 271 -------------------- 272 */ 273 public @property inout(ElementType)* ptr()inout return pure nothrow @system @nogc{ 274 return this.storage.ptr; 275 } 276 277 278 279 /** 280 */ 281 public @property inout(ElementType)* begin()inout return pure nothrow @system @nogc{ 282 return this.ptr; 283 } 284 285 286 287 /** 288 */ 289 public @property const(ElementType)* cbegin()const return pure nothrow @system @nogc{ 290 return this.ptr; 291 } 292 293 294 295 /** 296 */ 297 public @property inout(ElementType)* end()inout return pure nothrow @system @nogc{ 298 return (this.ptr + this.length); 299 } 300 301 302 303 /** 304 */ 305 public @property const(ElementType)* cend()const return pure nothrow @system @nogc{ 306 return (this.ptr + this.length); 307 } 308 309 310 311 /** 312 Return slice of all elements (same as `opSlice()`). 313 314 The slice returned may be invalidated by further calls to other member functions that modify the object. 315 316 Examples: 317 -------------------- 318 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3); 319 320 int[] slice = vec.elements; 321 assert(slice.length == vec.length); 322 assert(slice.ptr is vec.ptr); 323 324 vec.reserve(vec.capacity * 2); 325 assert(slice.length == vec.length); 326 // slice contains dangling pointer! 327 -------------------- 328 */ 329 public @property inout(ElementType)[] elements()inout return pure nothrow @system @nogc{ 330 return this.storage.elements; 331 } 332 333 334 335 /** 336 Return `true` if vector is small (capacity == minimalCapacity) 337 */ 338 public @property bool small()const scope pure nothrow @safe @nogc{ 339 return !this.storage.external; 340 } 341 342 343 344 /** 345 Destroys the `Vector` object. 346 347 This deallocates all the storage capacity allocated by the `Vector` using its allocator. 348 */ 349 public ~this()scope{ 350 this._release_impl(); 351 } 352 353 354 355 /** 356 Constructs a empty `Vector` with allocator `a`. 357 358 Examples: 359 -------------------- 360 { 361 Vector!(int, 6) vec = DefaultAllocator.init; 362 assert(vec.empty); 363 } 364 -------------------- 365 366 */ 367 static if(allowHeap) 368 public this(AllocatorType a)scope pure nothrow @safe @nogc{ 369 static if(!hasStatelessAllocator) 370 this._allocator = forward!a; 371 } 372 373 374 375 /** 376 Constructs a empty `Vector` 377 378 Examples: 379 -------------------- 380 { 381 Vector!(int, 6) vec = null; 382 assert(vec.empty); 383 } 384 -------------------- 385 386 */ 387 public this(typeof(null) nil, Forward = Forward.init)scope pure nothrow @safe @nogc{ 388 } 389 390 391 392 /** 393 Constructs a `Vector` object from other vector. 394 395 Parameters: 396 `rhs` other vector of `Vector` type. 397 398 `allocator` optional allocator parameter. 399 400 Examples: 401 -------------------- 402 { 403 Vector!(int, 6) vec = null; 404 assert(vec.empty); 405 } 406 407 { 408 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2); 409 assert(vec == [1, 2]); 410 } 411 412 { 413 auto tmp = Vector!(int, 6).build(1, 2); 414 Vector!(int, 6) vec = tmp; 415 assert(vec == [1, 2]); 416 } 417 418 419 { 420 Vector!(int, 6) vec = Vector!(int, 4).build(1, 2); 421 assert(vec == [1, 2]); 422 } 423 424 { 425 auto tmp = Vector!(int, 4).build(1, 2); 426 Vector!(int, 6) vec = tmp; 427 assert(vec == [1, 2]); 428 } 429 430 { 431 int[3] tmp = [1, 2, 3]; 432 Vector!(int, 6) vec = tmp[]; 433 assert(vec == [1, 2, 3]); 434 } 435 436 { 437 struct Range{ 438 int i; 439 440 bool empty()(){return i == 0;} 441 int front()(){return i;} 442 void popFront()(){i -= 1;} 443 //size_t length(); //no length 444 } 445 446 Vector!(int, 6) vec = Range(3); 447 assert(vec == [3, 2, 1]); 448 } 449 -------------------- 450 */ 451 public this(Rhs, this This)(scope auto ref Rhs rhs)scope 452 if( isVector!Rhs 453 && isConstructable!(Rhs, This) 454 && (isRef!Rhs || !is(immutable This == immutable Rhs)) 455 ){ 456 this(forward!rhs, Forward.init); 457 } 458 459 460 461 /** 462 Forward constructor. 463 */ 464 public this(Rhs, this This)(scope auto ref Rhs rhs, Forward)scope 465 if(isVector!Rhs && isConstructable!(Rhs, This)){ 466 467 //move: 468 static if(isMoveConstructable!(rhs, This)){ 469 if(rhs.storage.external){ 470 //heap -> heap: 471 if(minimalCapacity <= Rhs.minimalCapacity || minimalCapacity < rhs.length){ 472 static if(!hasStatelessAllocator) 473 this._allocator = move(rhs._allocator); 474 475 this.storage.length = rhs.storage.length; 476 this.storage.heap = rhs.storage.heap; 477 rhs.storage.reset(); 478 479 assert(this.storage.external); 480 } 481 //heap -> inline: 482 else{ 483 assert(minimalCapacity >= rhs.length); 484 485 static if(!hasStatelessAllocator) 486 this._allocator = rhs._allocator; 487 488 assert(rhs.length <= minimalCapacity); //this.reserve(rhs.length); 489 490 if(rhs.length){ 491 moveEmplaceRangeImpl!false( 492 (()@trusted => this.storage.inline.ptr )(), 493 (()@trusted => rhs.storage.heap.ptr )(), 494 rhs.length 495 ); 496 497 this.storage.length = rhs.storage.length; 498 } 499 500 assert(!this.storage.external); 501 } 502 } 503 else{ 504 static if(!hasStatelessAllocator) 505 this._allocator = move(rhs._allocator); 506 507 //inline -> inline: 508 if(minimalCapacity >= Rhs.minimalCapacity || minimalCapacity >= rhs.length){ 509 510 if(rhs.length){ 511 moveEmplaceRangeImpl!false( 512 (()@trusted => this.storage.inline.ptr )(), 513 (()@trusted => rhs.storage.inline.ptr )(), 514 rhs.length 515 ); 516 517 this.storage.length = rhs.storage.length; 518 rhs.storage.reset(); 519 } 520 521 assert(!this.storage.external); 522 } 523 //inline -> heap 524 else{ 525 this.reserve(rhs.length); 526 assert(rhs.length); 527 528 moveEmplaceRangeImpl!false( 529 (()@trusted => this.storage.heap.ptr )(), 530 (()@trusted => rhs.storage.inline.ptr )(), 531 rhs.length 532 ); 533 534 this.storage.length = rhs.storage.length; 535 assert(this.storage.external); 536 } 537 } 538 } 539 //move elements: 540 else static if(!isRef!rhs && isMoveConstructableElement!(GetElementType!Rhs, ElementType)){ 541 static if(!hasStatelessAllocator) 542 this._allocator = rhs._allocator; 543 544 auto range = rhs.storage.elements; 545 const size_t new_length = range.length; 546 547 this.downsize(new_length); 548 this.reserve(new_length); 549 550 const size_t old_length = this.length; 551 552 //move asign elements from range 553 moveAssignRange(this.storage.elements[0 .. min(old_range, new_range)], range); 554 555 //move elements from range 556 if(old_length < new_length){ 557 moveEmplaceRangeImpl!false( 558 (()@trusted => this.storage.ptr + old_length)(), 559 (()@trusted => range.ptr )(), 560 (new_length - old_length) 561 ); 562 } 563 564 this.length = new_length; 565 } 566 //copy: 567 else{ 568 static if(hasStatelessAllocator){ 569 this(rhs.storage.elements); 570 } 571 else{ 572 this(rhs.storage.elements, rhs.allocator); 573 } 574 } 575 } 576 577 578 579 /** 580 Constructs a `Vector` object from range of elements. 581 582 Parameters: 583 `range` input reange of `ElementType` elements. 584 585 `allocator` optional allocator parameter. 586 587 Examples: 588 -------------------- 589 import std.range : iota; 590 { 591 Vector!(int, 6) vec = iota(0, 5); 592 assert(vec == [0, 1, 2, 3, 4]); 593 } 594 -------------------- 595 */ 596 public this(R, this This)(R range, Forward = Forward.init)scope 597 if(isBtlInputRange!R && is(ElementEncodingType!R : GetElementType!This)){ 598 this._init_from_range(forward!range); 599 } 600 601 /// ditto 602 static if(allowHeap) 603 public this(R, this This)(R range, AllocatorType allcoator)return 604 if(isBtlInputRange!R && is(ElementEncodingType!R : GetElementType!This)){ 605 static if(!hasStatelessAllocator) 606 this._allocator = forward!allcoator; 607 608 this._init_from_range(forward!range); 609 } 610 611 private void _init_from_range(R, this This)(R range)scope 612 if(isBtlInputRange!R && is(ElementEncodingType!R : GetElementType!This)){ 613 auto self = (()@trusted => (cast(Unqual!This*)&this) )(); 614 615 static if(hasLength!R){ 616 const size_t length = range.length; 617 618 self.reserve(length); 619 620 { 621 auto elms = ()@trusted{ 622 return cast(GetElementType!This[])self.ptr[0 .. length]; 623 }(); 624 625 size_t emplaced = 0; 626 scope(failure){ 627 self.storage.length = emplaced; 628 } 629 630 emplaceElements(emplaced, elms, forward!range); 631 } 632 633 self.storage.length = length; 634 } 635 else{ 636 this.append(forward!range); 637 } 638 } 639 640 641 642 /** 643 Copy constructors 644 */ 645 static foreach(alias From; AliasSeq!( 646 typeof(this), 647 const typeof(this), 648 immutable typeof(this), 649 )){ 650 651 static if(hasCopyConstructor!(From, typeof(this))) 652 this(scope ref From rhs)scope{this(rhs, Forward.init);} 653 else 654 @disable this(scope ref From rhs)scope pure nothrow @safe; 655 656 static if(hasCopyConstructor!(From, const typeof(this))) 657 this(scope ref From rhs)const scope{this(rhs, Forward.init);} 658 else 659 @disable this(scope ref From rhs)const scope pure nothrow @safe; 660 661 static if(hasCopyConstructor!(From, immutable typeof(this))) 662 this(scope ref From rhs)immutable scope{this(rhs, Forward.init);} 663 else 664 @disable this(scope ref From rhs)immutable scope pure nothrow @safe; 665 666 static if(hasCopyConstructor!(From, shared typeof(this))) 667 this(scope ref From rhs)shared scope{this(rhs, Forward.init);} 668 else 669 @disable this(scope ref From rhs)shared scope pure nothrow @safe; 670 671 static if(hasCopyConstructor!(From, const shared typeof(this))) 672 this(scope ref From rhs)const shared scope{this(rhs, Forward.init);} 673 else 674 @disable this(scope ref From rhs)const shared scope pure nothrow @safe; 675 } 676 677 678 679 /** 680 Assigns a new value `rhs` to the vector, replacing its current contents. 681 682 Parameter `rhs` can by type of `null`, `Vector` or input range of ElementType elements. 683 684 Examples: 685 -------------------- 686 { 687 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3); 688 assert(!vec.empty); 689 690 vec = null; 691 assert(vec.empty); 692 693 vec = Vector!(int, 42).build(3, 2, 1); 694 assert(vec == [3, 2, 1]); 695 696 vec = Vector!(int, 2).build(4, 2); 697 assert(vec == [4, 2]); 698 } 699 700 { 701 int[3] tmp = [1, 2, 3]; 702 Vector!(int, 6) vec = tmp[]; 703 assert(vec == [1, 2, 3]); 704 } 705 706 { 707 struct Range{ 708 int i; 709 710 bool empty()(){return i == 0;} 711 int front()(){return i;} 712 void popFront()(){i -= 1;} 713 //size_t length(); //no length 714 } 715 716 Vector!(int, 6) vec = Range(3); 717 assert(vec == [3, 2, 1]); 718 } 719 -------------------- 720 */ 721 public void opAssign()(typeof(null) rhs)scope{ 722 this.clear(); 723 } 724 725 /// ditto 726 public void opAssign(R)(R range)scope 727 if(isBtlInputRange!R && is(ElementEncodingType!R : ElementType)){ 728 static if(hasLength!R){ 729 const size_t new_length = range.length; 730 731 this.downsize(new_length); 732 this.reserve(new_length); 733 734 const size_t old_length = this.length; 735 736 //asign elements from range 737 copyAssignRange(this.storage.elements[0 .. min(old_length, range.length)], range); 738 739 //emplace elements from range 740 if(old_length < new_length){ 741 auto elms = this.storage.allocatedElements[old_length .. new_length]; 742 //ElementType[] elms = (()@trusted => this.ptr[old_length .. new_length] )(); 743 size_t emplaced = 0; 744 745 scope(failure) 746 this.storage.length = (old_length + emplaced); 747 748 emplaceElements(emplaced, elms, forward!range); 749 } 750 751 this.storage.length = new_length; 752 } 753 else{ 754 const size_t old_length = this.length; 755 756 for(size_t i; i < this.length && !range.empty; ++i, range.popFront){ 757 copyEmplaceImpl(this.storage.elements[i], range.front); 758 } 759 760 while(!range.empty){ 761 this.append(range.front); 762 range.popFront; 763 } 764 765 } 766 } 767 768 /// ditto 769 public void opAssign(Rhs)(scope auto ref Rhs rhs)scope 770 if(isVector!Rhs && isAssignable!(Rhs, typeof(this)) ){ 771 ///move: 772 static if(isMoveAssignable!(rhs, typeof(this))){ 773 774 if(rhs.storage.external){ 775 // heap -> heap 776 if(minimalCapacity <= Rhs.minimalCapacity || minimalCapacity < rhs.length){ 777 static if(!hasStatelessAllocator) 778 this._allocator = move(rhs._allocator); 779 780 this.release(); 781 782 this.storage.length = rhs.storage.length; 783 this.storage.heap = rhs.storage.heap; 784 rhs.storage.reset(); 785 return; 786 } 787 } 788 } 789 790 static if(!isRef!rhs 791 && isMoveAssignableElement!(GetElementType!Rhs, ElementType) 792 ){ 793 auto range = rhs.storage.elements; 794 const size_t new_length = range.length; 795 796 this.downsize(new_length); 797 this.reserve(new_length); 798 799 const size_t old_length = this.length; 800 801 802 //move asign elements from range 803 moveAssignRange(this.storage.elements, range); 804 805 //move elements from range 806 if(old_length < new_length){ 807 808 moveEmplaceRangeImpl!false( 809 (()@trusted => this.ptr + old_length)(), 810 (()@trusted => range.ptr )(), 811 (new_length - old_length) 812 ); 813 } 814 815 this.storage.length = new_length; 816 } 817 else{ 818 this.opAssign(rhs.storage.elements); 819 } 820 821 822 } 823 824 825 826 /** 827 Move the last element of the vector, effectively reducing its length by 1. 828 829 Return erased element. 830 831 Examples: 832 -------------------- 833 Vector!(int, 6) vec = Vector!(int, 6).build(10, 20, 30); 834 assert(vec.length == 3); 835 836 assert(vec.popBack == 30); 837 assert(vec.length == 2); 838 839 assert(vec.popBack == 20); 840 assert(vec.length == 1); 841 842 assert(vec.popBack == 10); 843 assert(vec.empty); 844 845 assert(vec.popBack == int.init); 846 assert(vec.empty); 847 -------------------- 848 */ 849 public auto popBack(T = Unqual!ElementType)()scope nothrow 850 if(is(T == Unqual!ElementType) || is(T == void)){ 851 852 if(this.length == 0){ 853 static if(is(T == void)) 854 return; 855 else 856 return ElementType.init; 857 } 858 859 return _pop_back_impl!T(); 860 } 861 862 /// ditto 863 public auto popBack(T : Unqual!ElementType = Unqual!ElementType)(ElementType def = ElementType.init)scope nothrow{ 864 return (this.length == 0) 865 ? move(def) 866 : _pop_back_impl!T(); 867 } 868 869 private auto _pop_back_impl(T)()scope nothrow 870 if(is(T == Unqual!ElementType) || is(T == void)){ 871 assert(this.length != 0); 872 873 const size_t new_length = (this.length - 1); 874 this.storage.length = new_length; 875 876 static if(!is(T == void)){ 877 ElementType* ptr = (()@trusted => this.ptr + new_length )(); 878 ElementType result = move(*ptr); 879 880 ///TODO can be destruct ignored for moved element? 881 ///destructImpl!false(*ptr); //destroyElement(*ptr); 882 883 return move(result); 884 } 885 886 } 887 888 889 890 /** 891 Move the element at position `pos` out of vector, effectively reducing its length by 1. 892 893 Return erased element. 894 895 If `pos` is invalid then return `def` or `ElementType.init`. 896 897 Examples: 898 -------------------- 899 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3, 4, 5); 900 assert(vec.length == 5); 901 902 assert(vec.pop(0) == 1); 903 assert(vec == [2, 3, 4, 5]); 904 905 assert(vec.pop(3) == 5); 906 assert(vec == [2, 3, 4]); 907 908 assert(vec.pop(1) == 3); 909 assert(vec == [2, 4]); 910 -------------------- 911 */ 912 public ElementType pop()(const size_t pos, ElementType def = ElementType.init)scope nothrow{ 913 const size_t old_length = this.length; 914 915 if(pos >= old_length) 916 return move(def); 917 918 const size_t top = (pos + 1); 919 920 ElementType* elm = (()@trusted => this.ptr + pos )(); 921 ElementType result = move(*elm); 922 923 ///TODO can be destruct ignored for moved element? 924 ///destructImpl!false(*elm); //destroyElement(*elm); 925 926 if(top < old_length){ 927 moveEmplaceRangeImpl( 928 elm, 929 (()@trusted => elm + 1 )(), 930 (old_length - top) 931 ); 932 } 933 934 this.storage.length = (old_length - 1); 935 return move(result); 936 } 937 938 939 940 /** 941 Erases the contents of the `Vector`, which becomes an empty vector (with a length of 0 elements). 942 943 Doesn't change capacity of vector. 944 945 Examples: 946 -------------------- 947 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3); 948 949 vec.reserve(vec.capacity * 2); 950 assert(vec.length == 3); 951 952 const size_t cap = vec.capacity; 953 vec.clear(); 954 assert(vec.capacity == cap); 955 -------------------- 956 */ 957 public void clear()()scope nothrow{ 958 destructRangeImpl!false(this.storage.elements); 959 this.storage.length = 0; 960 } 961 962 963 964 /** 965 Erases and deallocate the contents of the `Vector`, which becomes an empty vector (with a length of 0 elements). 966 967 Examples: 968 -------------------- 969 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3); 970 971 vec.reserve(vec.capacity * 2); 972 assert(vec.length == 3); 973 974 const size_t cap = vec.capacity; 975 vec.clear(); 976 assert(vec.capacity == cap); 977 978 vec.release(); 979 assert(vec.capacity < cap); 980 assert(vec.capacity == typeof(vec).minimalCapacity); 981 -------------------- 982 */ 983 public void release()()scope nothrow{ 984 this._release_impl(); 985 this.storage.reset(); 986 } 987 988 private void _release_impl()scope nothrow{ 989 const bool is_external = this.storage.external; 990 991 destructRangeImpl!false(this.storage.elements); 992 993 static if(allowHeap) 994 if(is_external){ 995 996 static if(minimalCapacity == 0){ 997 const size_t cap = this.storage.heap.capacity; 998 if(cap == 0) 999 return; 1000 1001 } 1002 1003 this._deallocate_heap(this.storage.heap); 1004 } 1005 } 1006 1007 1008 1009 /** 1010 Returns true if memory referenced by `p` is owned by vector. 1011 1012 Examples: 1013 -------------------- 1014 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3, 4, 5, 6); 1015 1016 { 1017 assert(vec.owns(vec.ptr + 3)); 1018 assert(!vec.owns(cast(int*)null)); 1019 assert(!vec.owns(vec.ptr + 100)); 1020 } 1021 1022 { 1023 assert(vec.owns(&vec[$-1])); 1024 assert(!vec.owns(cast(long*)&vec[$-1])); 1025 } 1026 -------------------- 1027 */ 1028 public bool owns(T)(scope const T* p)scope const pure nothrow @trusted @nogc{ 1029 return (cast(const void*)this.ptr <= cast(const void*)p) 1030 && (cast(const void*)(p + 1) <= cast(const void*)(this.ptr + length)); 1031 } 1032 1033 1034 1035 /** 1036 Returns true if element referenced by `p` is owned by vector. 1037 Similar to owns but check if p has right alignment. 1038 1039 Examples: 1040 -------------------- 1041 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3, 4, 5, 6); 1042 1043 { 1044 assert(vec.ownsElement(vec.ptr + 3)); 1045 assert(!vec.ownsElement(cast(int*)null)); 1046 assert(!vec.ownsElement(vec.ptr + 100)); 1047 } 1048 1049 { 1050 const int* p = cast(int*)((cast(byte*)vec.ptr) + 1); 1051 assert(vec.owns(p)); 1052 assert(!vec.ownsElement(p)); 1053 } 1054 -------------------- 1055 */ 1056 public bool ownsElement(scope const ElementType* p)scope const pure nothrow @trusted @nogc{ 1057 return this.owns(p) 1058 && (cast(size_t)this.ptr % ElementType.sizeof) == (cast(size_t)p % ElementType.sizeof) ; 1059 } 1060 1061 1062 1063 /** 1064 Requests that the vector capacity be adapted to a planned change in size to a length of up to `n` elements. 1065 1066 If `n` is greater than the current vector capacity, the function causes the container to increase its capacity to `n` elements (or greater). 1067 1068 In all other cases, it do nothing. 1069 1070 This function has no effect on the vector length and cannot alter its content. 1071 1072 Examples: 1073 -------------------- 1074 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3); 1075 assert(vec.capacity == typeof(vec).minimalCapacity); 1076 1077 const size_t cap = (vec.capacity * 2); 1078 vec.reserve(cap); 1079 assert(vec.capacity > typeof(vec).minimalCapacity); 1080 assert(vec.capacity >= cap); 1081 -------------------- 1082 */ 1083 public void reserve()(const size_t n)scope nothrow{ 1084 1085 void _reserve_inline(const size_t n)scope nothrow{ 1086 static if(minimalCapacity > 0) 1087 assert(!this.storage.external); 1088 1089 enum size_t old_capacity = Storage.Inline.capacity; //(()@trusted => this.storage.inline.capacity )(); 1090 1091 if(n <= old_capacity) 1092 return; 1093 1094 const size_t new_capacity = _grow_capacity(old_capacity, n); 1095 1096 1097 Storage.Heap heap; // = this._heap_storage_ptr(); //(()@trusted => &this.storage.heap() )(); 1098 auto inline_elements = (()@trusted => this.storage.inline.elements(this.length) )(); 1099 1100 this._allocate_heap(heap, new_capacity); 1101 1102 moveEmplaceRangeImpl!false( 1103 (()@trusted => heap.ptr )(), 1104 (()@trusted => this.storage.inline.ptr )(), 1105 this.length 1106 ); 1107 1108 //this.storage.external = true; 1109 this.storage.heap = heap; 1110 } 1111 1112 void _reserve_heap(const size_t n)scope nothrow{ 1113 assert(this.storage.external); 1114 1115 const old_capacity = this.storage.heap.capacity; //(()@trusted => this.storage.heap.capacity )(); 1116 1117 if(n <= old_capacity) 1118 return; 1119 1120 const new_capacity = _grow_capacity(old_capacity , n); 1121 1122 if(minimalCapacity > 0 || old_capacity > 0){ 1123 this._reallocate_heap(this.storage.heap, new_capacity, this.length); 1124 } 1125 else{ 1126 this._allocate_heap(this.storage.heap, new_capacity); 1127 } 1128 } 1129 1130 return this.storage.external 1131 ? _reserve_heap(n) 1132 : _reserve_inline(n); 1133 } 1134 1135 1136 1137 /** 1138 Resizes the vector to a length of `n` elements. 1139 1140 If `n` is smaller than the current vector length, the current value is shortened to its first `n` character, removing the characters beyond the nth. 1141 1142 If `n` is greater than the current vector length, the current content is extended by inserting at the end as many elements as needed to reach a size of `n`. 1143 1144 If `args` are specified, the new elements are emplaced with parameters `args`, otherwise, they are `ElementType.init`. 1145 1146 Examples: 1147 -------------------- 1148 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3); 1149 1150 vec.resize(5, 0); 1151 assert(vec == [1, 2, 3, 0, 0]); 1152 1153 vec.resize(2); 1154 assert(vec == [1, 2]); 1155 -------------------- 1156 */ 1157 public void resize(Args...)(const size_t n, auto ref Args args)scope{ 1158 const size_t old_length = this.length; 1159 1160 if(old_length > n){ 1161 1162 ElementType[] slice = (()@trusted => this.ptr[n .. old_length] )(); 1163 destructRangeImpl!false(slice); 1164 this.storage.length = n; 1165 } 1166 else if(old_length < n){ 1167 this.reserve(n); 1168 1169 ElementType[] elms = ()@trusted{ 1170 return this.storage.allocatedElements[old_length .. n]; 1171 }(); 1172 size_t emplaced = 0; 1173 1174 scope(failure){ 1175 this.storage.length = (old_length + emplaced); 1176 } 1177 1178 emplaceElementsArgs(emplaced, elms, forward!args); 1179 1180 this.storage.length = n; 1181 } 1182 1183 } 1184 1185 1186 1187 /** 1188 Downsizes the vector to a length of `n` elements. 1189 1190 If `n` is smaller than the current vector length, the current value is shortened to its first `n` character, removing the characters beyond the nth. 1191 1192 If `n` is greater than the current vector length, then nothing happend. 1193 1194 Examples: 1195 -------------------- 1196 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3); 1197 1198 vec.downsize(5); 1199 assert(vec == [1, 2, 3]); 1200 1201 vec.downsize(2); 1202 assert(vec == [1, 2]); 1203 -------------------- 1204 */ 1205 public void downsize()(const size_t n)scope nothrow{ 1206 const size_t old_length = this.length; 1207 1208 if(old_length > n){ 1209 1210 ElementType[] slice = (()@trusted => this.ptr[n .. old_length] )(); 1211 destructRangeImpl!false(slice); 1212 this.storage.length = n; 1213 } 1214 } 1215 1216 1217 1218 /** 1219 Upsize the vector to a length of `n` elements. 1220 1221 If `n` is smaller than the current vector length, then nothing happend. 1222 1223 If `n` is greater than the current vector length, the current content is extended by inserting at the end as many elements as needed to reach a size of `n`. 1224 1225 If `args` are specified, the new elements are emplaced with parameters `args`, otherwise, they are `ElementType.init`. 1226 1227 Examples: 1228 -------------------- 1229 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3); 1230 1231 vec.upsize(5, 0); 1232 assert(vec == [1, 2, 3, 0, 0]); 1233 1234 vec.upsize(2); 1235 assert(vec == [1, 2, 3, 0, 0]); 1236 -------------------- 1237 */ 1238 public void upsize(Args...)(const size_t n, auto ref Args args)scope @safe{ 1239 const size_t old_length = this.length; 1240 1241 if(old_length < n){ 1242 this.reserve(n); 1243 1244 ElementType[] elms = ()@trusted{ 1245 return this.storage.allocatedElements[old_length .. n]; 1246 }(); 1247 1248 size_t emplaced = 0; 1249 scope(failure){ 1250 this.storage.length = (old_length + emplaced); 1251 } 1252 1253 emplaceElementsArgs(emplaced, elms, forward!args); 1254 this.storage.length = n; 1255 } 1256 } 1257 1258 1259 1260 /** 1261 Requests the `Vector` to reduce its capacity to fit its length. 1262 1263 The request is non-binding. 1264 1265 This function has no effect on the vector length and cannot alter its content. 1266 1267 Examples: 1268 -------------------- 1269 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3); 1270 1271 assert(vec.capacity == typeof(vec).minimalCapacity); 1272 1273 vec.reserve(vec.capacity * 2); 1274 assert(vec.capacity > typeof(vec).minimalCapacity); 1275 1276 vec.shrinkToFit(); 1277 assert(vec.capacity == typeof(vec).minimalCapacity); 1278 -------------------- 1279 */ 1280 public void shrinkToFit(const bool reallocate = true)scope{ 1281 if(!this.storage.external) 1282 return; 1283 1284 static if(allowHeap){ 1285 const size_t old_capacity = this.storage.heap.capacity; 1286 const size_t length = this.length; 1287 1288 if(length <= minimalCapacity){ 1289 Storage.Heap hs_data = this.storage.heap; 1290 1291 this.storage.external = false; 1292 assert(this.capacity == minimalCapacity); 1293 1294 if(minimalCapacity > 0 && length != 0) 1295 moveEmplaceRangeImpl!false( 1296 (()@trusted => this.storage.inline.ptr )(), 1297 (()@trusted => hs_data.ptr )(), 1298 length 1299 ); 1300 1301 this.storage.external = false; 1302 assert(this.capacity == minimalCapacity); 1303 1304 this._deallocate_heap(hs_data); 1305 } 1306 else{ 1307 if(reallocate && length < old_capacity){ 1308 this._reallocate_heap!true(this.storage.heap, length, length); 1309 } 1310 } 1311 } 1312 else{ 1313 assert(0, "no impl"); 1314 } 1315 1316 } 1317 1318 1319 1320 /** 1321 Operator `~=` and `+=` is same as append 1322 */ 1323 public template opOpAssign(string op) 1324 if(op == "~" || op == "+"){ 1325 alias opOpAssign = append; 1326 } 1327 1328 1329 1330 /** 1331 Same as operator `in` 1332 1333 Examples: 1334 -------------------- 1335 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3); 1336 1337 assert(vec.contains(1)); 1338 assert(!vec.contains(42L)); 1339 -------------------- 1340 */ 1341 public bool contains(Elm)(scope auto ref Elm elm)scope const{ 1342 foreach(ref e; this.storage.elements){ 1343 if(e == elm) 1344 return true; 1345 } 1346 1347 return false; 1348 } 1349 1350 1351 1352 /** 1353 Operator `in` 1354 1355 1356 Examples: 1357 -------------------- 1358 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3); 1359 1360 assert(1 in vec); 1361 assert(42L !in vec); 1362 -------------------- 1363 */ 1364 public bool opBinaryRight(string op, Elm)(scope auto ref Elm elm)scope const 1365 if(op == "in"){ 1366 return this.contains(forward!elm); 1367 } 1368 1369 1370 1371 /** 1372 Compares the contents of a vector with another vector, range or null. 1373 1374 Returns `true` if they are equal, `false` otherwise 1375 1376 Examples: 1377 -------------------- 1378 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3); 1379 1380 assert(vec != null); 1381 assert(null != vec); 1382 1383 assert(vec == [1, 2, 3]); 1384 assert([1, 2, 3] == vec); 1385 1386 assert(vec == typeof(vec).build(1, 2, 3)); 1387 assert(typeof(vec).build(1, 2, 3) == vec); 1388 1389 1390 import std.range : only; 1391 assert(vec == only(1, 2, 3)); 1392 assert(only(1, 2, 3) == vec); 1393 -------------------- 1394 */ 1395 public bool opEquals(typeof(null) nil)const scope pure nothrow @safe @nogc{ 1396 return this.empty; 1397 } 1398 1399 /// ditto 1400 public bool opEquals(R)(scope R rhs)const scope nothrow 1401 if(isBtlInputRange!R){ 1402 import std.algorithm.comparison : equal; 1403 1404 return equal(this.storage.elements, forward!rhs); 1405 } 1406 1407 /// ditto 1408 public bool opEquals(V)(scope const auto ref V rhs)const scope nothrow 1409 if(isVector!V){ 1410 import std.algorithm.comparison : equal; 1411 1412 return equal(this.storage.elements, rhs.storage.elements); 1413 } 1414 1415 1416 1417 1418 /** 1419 Compares the contents of a vector with another vector or range. 1420 1421 Examples: 1422 -------------------- 1423 auto a1 = Vector!(int, 6).build(1, 2, 3); 1424 auto a2 = Vector!(int, 6).build(1, 2, 3, 4); 1425 auto b = Vector!(int, 6).build(3, 2, 1); 1426 1427 assert(a1 < b); 1428 assert(a1 < a2); 1429 assert(a2 < b); 1430 assert(a1 <= a1); 1431 -------------------- 1432 */ 1433 public int opCmp(R)(scope R rhs)const scope nothrow 1434 if(isBtlInputRange!R){ 1435 import std.algorithm.comparison : cmp; 1436 1437 return cmp(this.storage.elements, forward!rhs); 1438 } 1439 1440 /// ditto 1441 public int opCmp(V)(scope const auto ref V rhs)const scope nothrow 1442 if(isVector!V){ 1443 import std.algorithm.comparison : cmp; 1444 1445 return cmp(this.storage.elements, rhs.storage.elements); 1446 } 1447 1448 1449 1450 /** 1451 Returns a slice [begin .. end]. If the requested slice extends past the end of the vector, the returned slice is invalid. 1452 1453 The slice returned may be invalidated by further calls to other member functions that modify the object. 1454 1455 Examples: 1456 -------------------- 1457 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3, 4, 5, 6); 1458 1459 assert(vec[1 .. 4] == [2, 3, 4]); 1460 assert(vec[1 .. $] == [2, 3, 4, 5, 6]); 1461 -------------------- 1462 */ 1463 public inout(ElementType)[] opSlice(bool check = true)(const size_t begin, const size_t end)inout return pure nothrow @system @nogc{ 1464 this._bounds_check([begin, end]); 1465 1466 return this.ptr[begin .. end]; 1467 1468 } 1469 1470 // 1471 public size_t[2] opSlice(size_t dim : 0)(size_t begin, size_t end)const pure nothrow @safe @nogc{ 1472 return [begin, end]; 1473 } 1474 1475 1476 1477 /** 1478 Return slice of all elements (same as `Vector.elements`). 1479 1480 The slice returned may be invalidated by further calls to other member functions that modify the object. 1481 1482 Examples: 1483 -------------------- 1484 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3); 1485 1486 int[] slice = vec[]; 1487 assert(slice.length == vec.length); 1488 assert(slice.ptr is vec.ptr); 1489 1490 vec.reserve(vec.capacity * 2); 1491 assert(slice.length == vec.length); 1492 // slice contains dangling pointer! 1493 -------------------- 1494 */ 1495 public inout(ElementType)[] opIndex()inout return pure nothrow @system @nogc{ 1496 return this.elements(); 1497 } 1498 1499 1500 1501 /** 1502 Returns reference to element at specified location `pos`. 1503 1504 Examples: 1505 -------------------- 1506 auto vec = Vector!(int, 10).build(1, 2, 3); 1507 1508 assert(vec[1] == 2); 1509 -------------------- 1510 */ 1511 public ref inout(ElementType) opIndex(const size_t pos)inout scope pure nothrow @system @nogc{ 1512 this._bounds_check(pos); 1513 1514 return *(this.ptr + pos); 1515 } 1516 1517 1518 1519 /** 1520 Returns reference to element at specified location `pos`. 1521 1522 Examples: 1523 -------------------- 1524 auto vec = Vector!(int, 10).build(1, 2, 3); 1525 1526 assert(vec.at(1) == 2); 1527 -------------------- 1528 */ 1529 public ref inout(ElementType) at(const size_t pos)inout scope pure nothrow @system @nogc{ 1530 return this.opIndex(pos); 1531 } 1532 1533 1534 1535 /** 1536 Returns a copy to the element at position `pos`. 1537 1538 Examples: 1539 -------------------- 1540 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3, 4, 5, 6); 1541 1542 assert(vec.atCopy(3) == 4); 1543 assert(vec.atCopy(vec.length-1) == 6); 1544 -------------------- 1545 */ 1546 public GetElementType!This atCopy(this This)(const size_t pos)scope{ 1547 this._bounds_check(pos); 1548 1549 return *(()@trusted => this.ptr + pos )(); 1550 } 1551 1552 1553 1554 /** 1555 Assign value `val` to element at position `index`. 1556 1557 Examples: 1558 -------------------- 1559 { 1560 auto vec = Vector!(int, 4).build(1, 2, 3, 4, 5); 1561 1562 vec[1] = 42; 1563 1564 assert(vec == [1, 42, 3, 4, 5]); 1565 } 1566 1567 { 1568 auto vec = Vector!(int, 4).build(1, 2, 3, 4, 5); 1569 1570 vec[1 .. $-1] = 42; 1571 1572 assert(vec == [1, 42, 42, 42, 5]); 1573 } 1574 -------------------- 1575 1576 */ 1577 public void opIndexAssign(Val)(auto ref Val val, size_t index){ 1578 this._bounds_check(index); 1579 1580 *(()@trusted => (this.ptr + index) )() = forward!val; 1581 } 1582 1583 /// ditto 1584 public void opIndexAssign(Val)(auto ref Val val, size_t[2] index){ 1585 this._bounds_check(index); 1586 1587 foreach(ref elm; (()@trusted => this.ptr[index[0] .. index[1]] )() ) 1588 elm = val; 1589 } 1590 1591 1592 1593 /** 1594 Assign `op` value `val` to element at position `index`. 1595 1596 Examples: 1597 -------------------- 1598 { 1599 auto vec = Vector!(int, 4).build(1, 2, 3, 4, 5); 1600 1601 vec[1] += 40; 1602 1603 assert(vec == [1, 42, 3, 4, 5]); 1604 } 1605 1606 { 1607 auto vec = Vector!(int, 4).build(1, 2, 3, 4, 5); 1608 1609 vec[1 .. $-1] *= -1; 1610 1611 assert(vec == [1, -2, -3, -4, 5]); 1612 } 1613 -------------------- 1614 1615 */ 1616 public void opIndexOpAssign(string op, Val)(auto ref Val val, size_t index){ 1617 this._bounds_check(index); 1618 1619 ref ElementType elm()@trusted{ 1620 return *(this.ptr + index); 1621 } 1622 1623 mixin("elm() " ~ op ~ "= forward!val;"); 1624 } 1625 1626 /// ditto 1627 public void opIndexOpAssign(string op, Val)(auto ref Val val, size_t[2] index){ 1628 this._bounds_check(index); 1629 1630 foreach(ref elm; (()@trusted => this.ptr[index[0] .. index[1]] )() ) 1631 mixin("elm " ~ op ~ "= val;"); 1632 } 1633 1634 1635 1636 /** 1637 Returns the length of the vector, in terms of number of elements. 1638 1639 Same as `length()`. 1640 */ 1641 public size_t opDollar()const scope pure nothrow @safe @nogc{ 1642 return this.length; 1643 } 1644 1645 1646 1647 /** 1648 Swaps the contents of `this` and `rhs`. 1649 1650 Examples: 1651 -------------------- 1652 auto a = Vector!(int, 6).build(1, 2, 3); 1653 auto b = Vector!(int, 6).build(4, 5, 6); 1654 1655 a.proxySwap(b); 1656 assert(a == [4, 5, 6]); 1657 assert(b == [1, 2, 3]); 1658 1659 import std.algorithm.mutation : swap; 1660 1661 swap(a, b); 1662 assert(a == [1, 2, 3]); 1663 assert(b == [4, 5, 6]); 1664 -------------------- 1665 */ 1666 public void proxySwap()(ref scope typeof(this) rhs)scope{ 1667 import std.algorithm.mutation : swap; 1668 1669 static if(minimalCapacity == 0){ 1670 static if(!hasStatelessAllocator) 1671 swap(this._allocator, rhs._allocator); 1672 1673 swap(this.storage.length, rhs.storage.length); 1674 swap(this.storage.heap, rhs.storage.heap); 1675 } 1676 else{ 1677 //heap <-> heap 1678 if(this.storage.external && rhs.storage.external){ 1679 static if(!hasStatelessAllocator) 1680 swap(this._allocator, rhs._allocator); 1681 1682 swap(this.storage.length, rhs.storage.length); 1683 swap(this.storage.heap, rhs.storage.heap); 1684 } 1685 //inline <-> inline 1686 else if(!this.storage.external && !rhs.storage.external){ 1687 auto small = (()@trusted => (this.length < rhs.length) ? &this : &rhs )(); 1688 auto large = (()@trusted => (this.length < rhs.length) ? &rhs : &this )(); 1689 1690 //TODO range swap generalization: 1691 for(size_t i = 0; i < this.length; ++i) 1692 swap( 1693 *(()@trusted => small.storage.inline.ptr + i )(), 1694 *(()@trusted => large.storage.inline.ptr + i )() 1695 ); 1696 1697 moveEmplaceRangeImpl( 1698 (()@trusted => small.storage.inline.ptr + small.length )(), 1699 (()@trusted => large.storage.inline.ptr + small.length )(), 1700 (large.length - small.length) 1701 ); 1702 1703 swap(this.storage.length, rhs.storage.length); 1704 } 1705 //heap <-> inline || inline <-> heap 1706 else{ 1707 assert(this.storage.external != rhs.storage.external); 1708 1709 auto heap = (()@trusted => this.storage.external ? &this : &rhs )(); 1710 auto inline = (()@trusted => this.storage.external ? &rhs : &this )(); 1711 1712 //copy heap to tmp: 1713 Storage.Heap tmp_heap = heap.storage.heap; 1714 1715 //copy inline to old heap: 1716 heap.storage.external = false; 1717 moveEmplaceRangeImpl( 1718 (()@trusted => heap.storage.inline.ptr )(), 1719 (()@trusted => inline.storage.inline.ptr )(), 1720 inline.storage.length 1721 ); 1722 1723 //swap lengths: 1724 swap(inline.storage.length, heap.storage.length); 1725 1726 //copy tmp heap to new heap: 1727 inline.storage.heap = tmp_heap; 1728 1729 assert(!heap.storage.external); 1730 assert(inline.storage.external); 1731 } 1732 1733 } 1734 } 1735 1736 1737 1738 /** 1739 Swaps the contents of `this` and `rhs` only if both are heap allocated. 1740 1741 Return `true` if swap successed or `false` if not (`this` or `rhs` is non heap allocated). 1742 1743 Examples: 1744 -------------------- 1745 auto a = Vector!(int, 3).build(1, 2, 3); 1746 auto b = Vector!(int, 3).build(6, 7, 8); 1747 1748 assert(a.heapSwap(b) == false); 1749 assert(a == [1, 2, 3]); 1750 assert(b == [6, 7, 8]); 1751 1752 a ~= 4; 1753 b ~= 9; 1754 assert(a == [1, 2, 3, 4]); 1755 assert(b == [6, 7, 8, 9]); 1756 1757 assert(a.heapSwap(b) == true); 1758 assert(a == [6, 7, 8, 9]); 1759 assert(b == [1, 2, 3, 4]); 1760 -------------------- 1761 */ 1762 public bool heapSwap()(ref scope typeof(this) rhs)scope{ 1763 import std.algorithm.mutation : swap; 1764 1765 //heap <-> heap 1766 if((minimalCapacity == 0) || (this.storage.external && rhs.storage.external)){ 1767 static if(!hasStatelessAllocator) 1768 swap(this._allocator, rhs._allocator); 1769 1770 swap(this.storage.length, rhs.storage.length); 1771 swap(this.storage.heap, rhs.storage.heap); 1772 1773 return true; 1774 } 1775 else{ 1776 return false; 1777 } 1778 } 1779 1780 1781 1782 /** 1783 Inserts a new element into the container directly before `pos` or `ptr`. 1784 1785 Return index of first inserted element. 1786 1787 Parameters: 1788 `pos` Insertion point, the new contents are inserted before the element at position `pos`. 1789 1790 `ptr` Pointer pointing to the insertion point, the new contents are inserted before the element pointed by ptr. 1791 1792 `args` arguments to forward to the constructor of the element 1793 1794 Examples: 1795 -------------------- 1796 { 1797 auto vec = Vector!(int, 6).build(1, 2, 3); 1798 1799 vec.emplace(1, 42); 1800 assert(vec == [1, 42, 2, 3]); 1801 1802 vec.emplace(4, 314); 1803 assert(vec == [1, 42, 2, 3, 314]); 1804 1805 vec.emplace(100, -1); 1806 assert(vec == [1, 42, 2, 3, 314, -1]); 1807 } 1808 1809 { 1810 auto vec = Vector!(int, 6).build(1, 2, 3); 1811 1812 vec.emplace(vec.ptr + 1, 42); 1813 assert(vec == [1, 42, 2, 3]); 1814 1815 vec.emplace(vec.ptr + 4, 314); 1816 assert(vec == [1, 42, 2, 3, 314]); 1817 1818 vec.emplace(vec.ptr + 100, -1); 1819 assert(vec == [1, 42, 2, 3, 314, -1]); 1820 } 1821 1822 { 1823 static struct Foo{ 1824 int i; 1825 string str; 1826 } 1827 1828 auto vec = Vector!(Foo, 6).build(Foo(1, "A")); 1829 1830 vec.emplace(1, 2, "B"); 1831 assert(vec == only(Foo(1, "A"), Foo(2, "B"))); 1832 1833 vec.emplace(0, 42, "X"); 1834 assert(vec == only(Foo(42, "X"), Foo(1, "A"), Foo(2, "B"))); 1835 } 1836 -------------------- 1837 */ 1838 public size_t emplace(Args...)(const size_t pos, auto ref Args args)scope{ 1839 const size_t old_length = this.length; 1840 1841 if(old_length <= pos){ 1842 this.emplaceBack(forward!args); 1843 return old_length; 1844 } 1845 1846 const size_t new_length = (old_length + 1); 1847 1848 this.reserve(new_length); 1849 1850 auto ptr = (()@trusted => this.ptr + pos)(); 1851 1852 moveEmplaceRangeImpl( 1853 ptr + 1, 1854 ptr, 1855 (old_length - pos) //shift 1856 ); 1857 1858 this.storage.length = new_length; 1859 1860 emplaceImpl(*ptr, forward!args); 1861 1862 return pos; 1863 } 1864 1865 /// ditto 1866 public size_t emplace(Args...)(scope const ElementType* ptr, auto ref Args args)scope{ 1867 auto this_ptr = (()@trusted => this.ptr )(); 1868 1869 const size_t pos = (ptr < this_ptr) 1870 ? 0 1871 : (ptr - this_ptr); 1872 1873 return this.emplace(pos, forward!args); 1874 } 1875 1876 1877 1878 /** 1879 Appends a new element to the end of the container. The element is constructed through `emplace`. 1880 1881 Parameters: 1882 `args` arguments to forward to the constructor of the element. 1883 1884 Examples: 1885 -------------------- 1886 { 1887 auto vec = Vector!(int, 6).build(1, 2, 3); 1888 1889 vec.emplaceBack(42); 1890 assert(vec == [1, 2, 3, 42]); 1891 1892 vec.emplaceBack(); 1893 assert(vec == [1, 2, 3, 42, 0]); 1894 } 1895 1896 { 1897 static struct Foo{ 1898 int i; 1899 string str; 1900 } 1901 1902 auto vec = Vector!(Foo, 6).build(Foo(1, "A")); 1903 1904 vec.emplaceBack(2, "B"); 1905 assert(vec == only(Foo(1, "A"), Foo(2, "B"))); 1906 } 1907 -------------------- 1908 */ 1909 public void emplaceBack(Args...)(auto ref Args args)scope{ 1910 const size_t old_length = this.length; 1911 const size_t new_length = (old_length + 1); 1912 1913 this.reserve(new_length); 1914 auto ptr = (()@trusted => this.ptr + old_length )(); 1915 1916 emplaceImpl(*ptr, forward!args); 1917 1918 this.storage.length = new_length; 1919 } 1920 1921 1922 1923 /** 1924 Extends the `Vector` by appending additional elements at the end of vector. 1925 1926 Return index of first inserted element. 1927 1928 Parameters: 1929 `val` appended value. 1930 1931 `vec` appended vector. 1932 1933 `range` appended input renge. 1934 1935 `count` Number of times `val` is appended. 1936 1937 Examples: 1938 -------------------- 1939 { 1940 auto vec = Vector!(int, 6).build(1, 2, 3); 1941 1942 vec.append(42); 1943 assert(vec == [1, 2, 3, 42]); 1944 } 1945 1946 { 1947 auto vec = Vector!(int, 6).build(1, 2, 3); 1948 1949 vec.append(only(4, 5, 6)); 1950 assert(vec == [1, 2, 3, 4, 5, 6]); 1951 } 1952 1953 { 1954 auto a = Vector!(int, 6).build(1, 2, 3); 1955 auto b = Vector!(int, 6).build(4, 5, 6); 1956 1957 a.append(b); 1958 assert(a == [1, 2, 3, 4, 5, 6]); 1959 } 1960 1961 { 1962 Vector!(int, 3) vec = Vector!(int, 3).build(1, 2, 3); 1963 int[3] tmp = [4, 5, 6]; 1964 vec.append(tmp[]); 1965 assert(vec == [1, 2, 3, 4, 5, 6]); 1966 } 1967 1968 { 1969 struct Range{ 1970 int i; 1971 1972 bool empty()(){return i == 0;} 1973 int front()(){return i;} 1974 void popFront()(){i -= 1;} 1975 //size_t length(); //no length 1976 } 1977 1978 Vector!(int, 3) vec = Vector!(int, 3).build(6, 5, 4); 1979 vec.append(Range(3)); 1980 assert(vec == [6, 5, 4, 3, 2, 1]); 1981 } 1982 -------------------- 1983 */ 1984 public size_t append(R)(R range)scope 1985 if(isBtlInputRange!R && is(ElementEncodingType!R : ElementType)){ 1986 static if(hasLength!R){ 1987 return this._append_impl(forward!range); 1988 } 1989 else{ 1990 const len = this.length; 1991 while(!range.empty){ 1992 this._append_impl(range.front); 1993 range.popFront; 1994 } 1995 1996 return len; 1997 } 1998 } 1999 2000 /// ditto 2001 public size_t append(Vec)(scope auto ref Vec vec)scope 2002 if(isVector!Vec && is(GetElementType!Vec : ElementType)){ 2003 return this.append(vec.storage.elements); 2004 } 2005 2006 /// ditto 2007 public size_t append(Val)(auto ref Val val, const size_t count = 1)scope 2008 if(is(Val : ElementType)){ 2009 return this._append_impl(forward!val, count); 2010 } 2011 2012 private size_t _append_impl(Args...)(auto ref Args args)scope{ 2013 const size_t args_length = emplaceLength(args); 2014 const size_t old_length = this.length; 2015 const size_t new_length = (old_length + args_length); 2016 2017 this.reserve(new_length); 2018 2019 { 2020 ElementType[] elms = ()@trusted{ 2021 return this.ptr[old_length .. new_length]; 2022 }(); 2023 2024 size_t emplaced = 0; 2025 scope(failure) 2026 this.storage.length = (old_length + emplaced); 2027 2028 emplaceElements(emplaced, elms, forward!args); 2029 } 2030 2031 this.storage.length = new_length; 2032 2033 return old_length; 2034 } 2035 2036 2037 2038 /** 2039 Inserts additional elements into the `Vector` right before the element indicated by `pos` or `ptr`. 2040 2041 Return index of first inserted element. 2042 2043 Parameters: 2044 `pos` Insertion point, the new contents are inserted before the element at position `pos`. 2045 2046 `ptr` Pointer pointing to the insertion point, the new contents are inserted before the element pointed by ptr. 2047 2048 `val` Value inserted before insertion point `pos` or `ptr`. 2049 2050 `vec` appended vector. 2051 2052 `range` appended input renge. 2053 2054 `count` Number of times `val` is inserted. 2055 2056 Examples: 2057 -------------------- 2058 //pos: 2059 { 2060 auto vec = Vector!(int, 3).build(1, 2, 3); 2061 2062 size_t pos = vec.insert(1, 42, 2); 2063 assert(pos == 1); 2064 assert(vec == [1, 42, 42, 2, 3]); 2065 2066 pos = vec.insert(100, 4, 3); 2067 assert(pos == 5); 2068 assert(vec == [1, 42, 42, 2, 3, 4, 4, 4]); 2069 } 2070 2071 { 2072 auto vec = Vector!(int, 3).build(1, 2, 3); 2073 2074 size_t pos = vec.insert(1, [20, 30, 40]); 2075 assert(pos == 1); 2076 assert(vec == [1, 20, 30, 40, 2, 3]); 2077 2078 pos = vec.insert(100, [4, 5, 6]); 2079 assert(pos == 6); 2080 assert(vec == [1, 20, 30, 40, 2, 3, 4, 5, 6]); 2081 } 2082 2083 { 2084 auto vec = Vector!(int, 3).build(1, 2, 3); 2085 auto tmp = Vector!(int, 10).build(-1, -2, -3); 2086 2087 size_t pos = vec.insert(1, tmp); 2088 assert(pos == 1); 2089 assert(vec == [1, -1, -2, -3, 2, 3]); 2090 2091 pos = vec.insert(100, Vector!(int, 10).build(40, 50, 60)); 2092 assert(pos == 6); 2093 assert(vec == [1, -1, -2, -3, 2, 3, 40, 50, 60]); 2094 } 2095 2096 //ptr: 2097 { 2098 auto vec = Vector!(int, 3).build(1, 2, 3); 2099 2100 size_t pos = vec.insert(vec.ptr + 1, 42, 2); 2101 assert(pos == 1); 2102 assert(vec == [1, 42, 42, 2, 3]); 2103 2104 pos = vec.insert(vec.ptr + 100, 4, 3); 2105 assert(pos == 5); 2106 assert(vec == [1, 42, 42, 2, 3, 4, 4, 4]); 2107 } 2108 2109 { 2110 auto vec = Vector!(int, 3).build(1, 2, 3); 2111 2112 size_t pos = vec.insert(vec.ptr + 1, [20, 30, 40]); 2113 assert(pos == 1); 2114 assert(vec == [1, 20, 30, 40, 2, 3]); 2115 2116 pos = vec.insert(vec.ptr + 100, [4, 5, 6]); 2117 assert(pos == 6); 2118 assert(vec == [1, 20, 30, 40, 2, 3, 4, 5, 6]); 2119 } 2120 2121 { 2122 auto vec = Vector!(int, 3).build(1, 2, 3); 2123 auto tmp = Vector!(int, 10).build(-1, -2, -3); 2124 2125 size_t pos = vec.insert(vec.ptr + 1, tmp); 2126 assert(pos == 1); 2127 assert(vec == [1, -1, -2, -3, 2, 3]); 2128 2129 pos = vec.insert(vec.ptr + 100, Vector!(int, 10).build(40, 50, 60)); 2130 assert(pos == 6); 2131 assert(vec == [1, -1, -2, -3, 2, 3, 40, 50, 60]); 2132 } 2133 -------------------- 2134 */ 2135 public size_t insert(R)(const size_t pos, R range)scope 2136 if( hasLength!R 2137 && isBtlInputRange!R 2138 && is(ElementEncodingType!R : ElementType) 2139 ){ 2140 return this._insert_impl(pos, forward!range); 2141 } 2142 2143 /// ditto 2144 public size_t insert(Vec)(const size_t pos, scope auto ref Vec vec)scope 2145 if(isVector!Vec && is(GetElementType!Vec : ElementType)){ 2146 return this._insert_impl(pos, vec.storage.elements); 2147 } 2148 2149 /// ditto 2150 public size_t insert(Val)(const size_t pos, auto ref Val val, const size_t count = 1)scope 2151 if(is(Val : ElementType)){ 2152 return this._insert_impl(pos, forward!val, count); 2153 } 2154 2155 /// ditto 2156 public size_t insert(R)(scope const ElementType* ptr, R range)scope 2157 if(isBtlInputRange!R && is(ElementEncodingType!R : ElementType)){ 2158 static assert(hasLength!R, "range need length property"); 2159 2160 return this._insert_impl(ptr, forward!range); 2161 } 2162 2163 /// ditto 2164 public size_t insert(Vec)(scope const ElementType* ptr, scope auto ref Vec vec)scope 2165 if(isVector!Vec && is(GetElementType!Vec : ElementType)){ 2166 return this._insert_impl(ptr, vec.storage.elements); 2167 } 2168 2169 /// ditto 2170 public size_t insert(Val)(scope const ElementType* ptr, auto ref Val val, const size_t count = 1)scope 2171 if(is(Val : ElementType)){ 2172 return this._insert_impl(ptr, forward!val, count); 2173 } 2174 2175 private size_t _insert_impl(Args...)(const size_t pos, auto ref Args args)scope{ 2176 2177 if(pos > this.length) 2178 return this.append(forward!args); 2179 2180 const size_t args_length = emplaceLength(args); 2181 const size_t old_length = this.length; 2182 const size_t new_length = (old_length + args_length); 2183 2184 this.reserve(new_length); 2185 2186 ElementType[] elms = (()@trusted => this.ptr[pos .. pos + args_length])(); 2187 2188 moveEmplaceRangeImpl( 2189 (()@trusted => elms.ptr + args_length )(), 2190 (()@trusted => elms.ptr )(), 2191 (old_length - pos) //shift 2192 ); 2193 2194 this.storage.length = new_length; 2195 2196 { 2197 size_t emplaced = 0; 2198 scope(failure) 2199 initElements(elms[emplaced .. $]); 2200 2201 emplaceElements(emplaced, elms, forward!args); 2202 } 2203 2204 2205 return pos; 2206 } 2207 2208 private size_t _insert_impl(Args...)(scope const ElementType* ptr, auto ref Args args)scope{ 2209 const size_t pos = (ptr > this.ptr) 2210 ? (ptr - this.ptr) 2211 : 0; 2212 2213 return this._insert_impl(pos, forward!args); 2214 } 2215 2216 2217 2218 /** 2219 Removes specified element from the vector. 2220 2221 Return index of first removed element. 2222 2223 Parameters: 2224 `pos` position of first element to be removed. 2225 2226 `n` number of elements to be removed. 2227 2228 `ptr` pointer to elements to be removed. 2229 2230 `slice` sub-slice to be removed, `slice` must be subset of `this` 2231 2232 Examples: 2233 -------------------- 2234 //pos: 2235 { 2236 auto vec = Vector!(int, 3).build(1, 2, 3, 4, 5, 6); 2237 2238 size_t pos = vec.erase(3); 2239 assert(pos == 3); 2240 assert(vec == [1, 2, 3]); 2241 2242 pos = vec.erase(100); 2243 assert(pos == 3); 2244 assert(vec == [1, 2, 3]); 2245 } 2246 2247 { 2248 auto vec = Vector!(int, 3).build(1, 2, 3, 4, 5, 6); 2249 2250 size_t pos = vec.erase(1, 4); 2251 assert(pos == 1); 2252 assert(vec == [1, 6]); 2253 2254 pos = vec.erase(100, 4); 2255 assert(pos == 2); 2256 assert(vec == [1, 6]); 2257 2258 pos = vec.erase(0, 100); 2259 assert(pos == 0); 2260 assert(vec.empty); 2261 } 2262 2263 //ptr: 2264 { 2265 auto vec = Vector!(int, 3).build(1, 2, 3, 4, 5, 6); 2266 2267 size_t pos = vec.erase(vec.ptr + 3); 2268 assert(pos == 3); 2269 assert(vec == [1, 2, 3]); 2270 2271 pos = vec.erase(vec.ptr + 100); 2272 assert(pos == 3); 2273 assert(vec == [1, 2, 3]); 2274 } 2275 2276 { 2277 auto vec = Vector!(int, 3).build(1, 2, 3, 4, 5, 6); 2278 2279 size_t pos = vec.erase(vec[1 .. 5]); 2280 assert(pos == 1); 2281 assert(vec == [1, 6]); 2282 } 2283 -------------------- 2284 */ 2285 public size_t erase()(const size_t pos)scope nothrow{ 2286 const size_t old_length = this.length; 2287 2288 if(pos >= old_length) 2289 return old_length; 2290 2291 ElementType[] elements = this.storage.elements[pos .. old_length]; 2292 destructRangeImpl!false(elements); 2293 2294 this.storage.length = pos; 2295 2296 return pos; 2297 } 2298 2299 /// ditto 2300 public size_t erase()(const size_t pos, const size_t n)scope{ 2301 const size_t old_length = this.length; 2302 2303 if(pos >= old_length) 2304 return old_length; 2305 2306 const size_t top = (pos + n); 2307 2308 if(top >= old_length) 2309 return this.erase(pos); 2310 2311 if(n != 0){ 2312 ElementType[] elements = this.storage.elements; 2313 2314 destructRangeImpl!false(elements[pos .. top]); 2315 2316 moveEmplaceRangeImpl( 2317 (()@trusted => elements.ptr + pos )(), 2318 (()@trusted => elements.ptr + top )(), 2319 (old_length - top) 2320 ); 2321 2322 this.storage.length = (old_length - n); 2323 } 2324 2325 return pos; 2326 } 2327 2328 /// ditto 2329 public size_t erase()(scope const ElementType* ptr)scope nothrow{ 2330 if(ptr <= this.ptr){ 2331 this.clear(); 2332 return 0; 2333 } 2334 2335 return this.erase(ptr - this.ptr); 2336 } 2337 2338 /// ditto 2339 public size_t erase()(scope const ElementType[] slice)scope nothrow @safe{ 2340 const ptr = (()@trusted => this.ptr )(); 2341 2342 if(slice.ptr < ptr){ 2343 const size_t offset = (()@trusted => ptr - slice.ptr)(); 2344 2345 if(offset >= slice.length) 2346 return 0; 2347 2348 return this.erase(0, slice.length - offset); 2349 } 2350 2351 debug assert(slice.ptr >= ptr); 2352 2353 const size_t pos = (()@trusted => slice.ptr - ptr )(); 2354 2355 return this.erase(pos, slice.length); 2356 } 2357 2358 2359 /** 2360 Replaces the portion of the vector that begins at element `pos` and spans `len` characters (or the part of the vector in the slice `slice`) by new contents. 2361 2362 Parameters: 2363 `pos` position of the first character to be replaced. 2364 2365 `len` number of elements to replace (if the vector is shorter, as many elements as possible are replaced). 2366 2367 `slice` sub-slice to be removed, `slice` must be subset of `this` 2368 2369 `val` inserted value. 2370 2371 `count` number of times `val` is inserted. 2372 2373 Examples: 2374 -------------------- 2375 //pos: 2376 { 2377 auto vec = Vector!(int, 3).build(1, 2, 3, 4, 5, 6); 2378 2379 size_t pos = vec.replace(2, 2, 0, 5); 2380 assert(pos == 2); 2381 assert(vec == [1, 2, 0, 0, 0, 0, 0, 5, 6]); 2382 2383 pos = vec.replace(100, 2, 42, 2); 2384 assert(pos == 9); 2385 assert(vec == [1, 2, 0, 0, 0, 0, 0, 5, 6, 42, 42]); 2386 2387 pos = vec.replace(2, 100, -1); 2388 assert(pos == 2); 2389 assert(vec == [1, 2, -1]); 2390 } 2391 2392 { 2393 auto vec = Vector!(int, 3).build(1, 2, 3, 4, 5, 6); 2394 2395 size_t pos = vec.replace(2, 2, [0, 0, 0, 0, 0]); 2396 assert(pos == 2); 2397 assert(vec == [1, 2, 0, 0, 0, 0, 0, 5, 6]); 2398 2399 pos = vec.replace(100, 2, [42, 42]); 2400 assert(pos == 9); 2401 assert(vec == [1, 2, 0, 0, 0, 0, 0, 5, 6, 42, 42]); 2402 2403 pos = vec.replace(2, 100, [-1]); 2404 assert(pos == 2); 2405 assert(vec == [1, 2, -1]); 2406 } 2407 2408 { 2409 auto vec = Vector!(int, 3).build(1, 2, 3, 4, 5, 6); 2410 2411 size_t pos = vec.replace(2, 2, Vector!(int, 3).build(0, 0, 0, 0, 0)); 2412 assert(pos == 2); 2413 assert(vec == [1, 2, 0, 0, 0, 0, 0, 5, 6]); 2414 2415 pos = vec.replace(100, 2, Vector!(int, 2).build(42, 42)); 2416 assert(pos == 9); 2417 assert(vec == [1, 2, 0, 0, 0, 0, 0, 5, 6, 42, 42]); 2418 2419 pos = vec.replace(2, 100, Vector!(int, 2).build(-1)); 2420 assert(pos == 2); 2421 assert(vec == [1, 2, -1]); 2422 } 2423 2424 //ptr: 2425 { 2426 auto vec = Vector!(int, 3).build(1, 2, 3, 4, 5, 6); 2427 2428 size_t pos = vec.replace(vec[2 .. 4], 0, 5); 2429 assert(pos == 2); 2430 assert(vec == [1, 2, 0, 0, 0, 0, 0, 5, 6]); 2431 2432 pos = vec.replace(vec.ptr[100 .. 102], 42, 2); 2433 assert(pos == 9); 2434 assert(vec == [1, 2, 0, 0, 0, 0, 0, 5, 6, 42, 42]); 2435 2436 pos = vec.replace(vec.ptr[2 .. 100], -1); 2437 assert(pos == 2); 2438 assert(vec == [1, 2, -1]); 2439 } 2440 2441 { 2442 auto vec = Vector!(int, 3).build(1, 2, 3, 4, 5, 6); 2443 2444 size_t pos = vec.replace(vec[2 .. 4], [0, 0, 0, 0, 0]); 2445 assert(pos == 2); 2446 assert(vec == [1, 2, 0, 0, 0, 0, 0, 5, 6]); 2447 2448 pos = vec.replace(vec.ptr[100 .. 102], [42, 42]); 2449 assert(pos == 9); 2450 assert(vec == [1, 2, 0, 0, 0, 0, 0, 5, 6, 42, 42]); 2451 2452 pos = vec.replace(vec.ptr[2 .. 100], [-1]); 2453 assert(pos == 2); 2454 assert(vec == [1, 2, -1]); 2455 } 2456 2457 { 2458 auto vec = Vector!(int, 3).build(1, 2, 3, 4, 5, 6); 2459 2460 size_t pos = vec.replace(vec[2 .. 4], Vector!(int, 3).build(0, 0, 0, 0, 0)); 2461 assert(pos == 2); 2462 assert(vec == [1, 2, 0, 0, 0, 0, 0, 5, 6]); 2463 2464 pos = vec.replace(vec.ptr[100 .. 102], Vector!(int, 2).build(42, 42)); 2465 assert(pos == 9); 2466 assert(vec == [1, 2, 0, 0, 0, 0, 0, 5, 6, 42, 42]); 2467 2468 pos = vec.replace(vec.ptr[2 .. 100], Vector!(int, 2).build(-1)); 2469 assert(pos == 2); 2470 assert(vec == [1, 2, -1]); 2471 } 2472 -------------------- 2473 */ 2474 public size_t replace(Val)(const size_t pos, const size_t len, auto ref Val val, const size_t count = 1)scope 2475 if(is(Val : ElementType)){ 2476 return this._replace_impl(pos, len, forward!val, count); 2477 } 2478 2479 /// ditto 2480 public size_t replace(R)(const size_t pos, const size_t len, R range)scope 2481 if( hasLength!R 2482 && isBtlInputRange!R 2483 && is(ElementEncodingType!R : ElementType) 2484 ){ 2485 return this._replace_impl(pos, len, forward!range); 2486 } 2487 2488 /// ditto 2489 public size_t replace(Vec)(const size_t pos, const size_t len, scope auto ref Vec vec)scope 2490 if(isVector!Vec && is(GetElementType!Vec : ElementType)){ 2491 return this._replace_impl(pos, len, vec.storage.elements); 2492 } 2493 2494 /// ditto 2495 public size_t replace(Val)(scope const ElementType[] slice, auto ref Val val, const size_t count = 1)scope 2496 if(is(Val : ElementType)){ 2497 return this._replace_impl(slice, forward!val, count); 2498 } 2499 2500 /// ditto 2501 public size_t replace(R)(scope const ElementType[] slice, R range)scope 2502 if( hasLength!R 2503 && isBtlInputRange!R 2504 && is(ElementEncodingType!R : ElementType) 2505 ){ 2506 return this._replace_impl(slice, forward!range); 2507 } 2508 2509 /// ditto 2510 public size_t replace(Vec)(scope const ElementType[] slice, scope auto ref Vec vec)scope 2511 if(isVector!Vec && is(GetElementType!Vec : ElementType)){ 2512 return this._replace_impl(slice, vec.storage.elements); 2513 } 2514 2515 2516 private size_t _replace_impl(Args...)(const size_t pos, const size_t len, auto ref Args args)scope{ 2517 const size_t old_length = this.length; 2518 2519 if(len == 0){ 2520 return this.insert(pos, forward!args); 2521 } 2522 2523 if(old_length <= pos){ 2524 return this.append(forward!args); 2525 } 2526 2527 const size_t top = (pos + len); 2528 2529 if(top >= old_length){ 2530 this.erase(pos); 2531 return this.append(forward!args); 2532 } 2533 2534 const size_t args_length = emplaceLength(args); 2535 alias erase_length = len; 2536 2537 if(args_length == erase_length){ 2538 ElementType[] elements = this.storage.elements; 2539 ElementType[] elms = elements[pos .. top]; 2540 destructRangeImpl!false(elms); 2541 2542 { 2543 size_t emplaced = 0; 2544 scope(failure) 2545 initElements(elms[emplaced .. $]); 2546 2547 emplaceElements(emplaced, elms, forward!args); 2548 } 2549 2550 return pos; 2551 } 2552 2553 if(args_length < erase_length){ 2554 const size_t diff = (erase_length - args_length); 2555 const size_t new_length = (old_length - diff); 2556 2557 ElementType[] elements = this.storage.elements; 2558 ElementType[] old_elms = elements[pos .. top]; 2559 ElementType[] new_elms = elements[pos .. pos + args_length]; 2560 2561 destructRangeImpl!false(old_elms); 2562 2563 moveEmplaceRangeImpl( 2564 (()@trusted => elements.ptr + top )(), 2565 (()@trusted => elements.ptr + top - diff )(), 2566 diff 2567 ); 2568 2569 this.storage.length = new_length; 2570 2571 { 2572 size_t emplaced = 0; 2573 scope(failure) 2574 initElements(new_elms[emplaced .. $]); 2575 2576 emplaceElements(emplaced, new_elms, forward!args); 2577 } 2578 2579 2580 return pos; 2581 } 2582 2583 assert(args_length > erase_length); 2584 { 2585 const size_t diff = (args_length - erase_length); 2586 const size_t new_length = (old_length + diff); 2587 2588 this.reserve(new_length); 2589 2590 ElementType[] elements = (()@trusted => this.storage.allocatedElements)(); 2591 ElementType[] old_elms = elements[pos .. top]; 2592 ElementType[] new_elms = elements[pos .. pos + args_length]; 2593 2594 destructRangeImpl!false(old_elms); 2595 2596 moveEmplaceRangeImpl( 2597 (()@trusted => elements.ptr + top + diff )(), 2598 (()@trusted => elements.ptr + top )(), 2599 diff 2600 ); 2601 2602 this.storage.length = new_length; 2603 2604 { 2605 size_t emplaced = 0; 2606 scope(failure) 2607 initElements(new_elms[emplaced .. $]); 2608 2609 emplaceElements(emplaced, new_elms, forward!args); 2610 } 2611 2612 return pos; 2613 } 2614 } 2615 2616 private size_t _replace_impl(Args...)(scope const ElementType[] slice, auto ref Args args)scope{ 2617 const ptr = (()@trusted => this.ptr )(); 2618 2619 if(slice.ptr < ptr){ 2620 const size_t offset = (()@trusted => ptr - slice.ptr)(); 2621 2622 return (offset >= slice.length) 2623 ? this.insert(0, forward!args) 2624 : this.replace(0, slice.length - offset, forward!args); 2625 } 2626 2627 debug assert(slice.ptr >= ptr); 2628 2629 const size_t pos = (()@trusted => slice.ptr - ptr )(); 2630 2631 return this.replace(pos, slice.length, forward!args); 2632 } 2633 2634 2635 2636 ///Alias to append. 2637 public alias put = append; 2638 2639 2640 2641 /** 2642 Returns a reference to the first element in the vector. 2643 2644 Calling this function on an empty container causes undefined behavior. 2645 */ 2646 public ref inout(ElementType) front()inout return pure nothrow @system @nogc{ 2647 this._bounds_check(0); 2648 return *this.ptr; 2649 } 2650 2651 2652 2653 /** 2654 Returns a copy of the first element in the vector. 2655 2656 Examples: 2657 -------------------- 2658 auto vec = Vector!(int, 10).build(1, 2, 3); 2659 2660 assert(vec.frontCopy == 1); 2661 assert(vec == [1, 2, 3]); 2662 -------------------- 2663 */ 2664 public auto frontCopy(this This)()scope{ 2665 this._bounds_check(0); 2666 2667 return *(()@trusted => this.ptr )(); 2668 } 2669 2670 2671 2672 /** 2673 Move of the first element in the vector and return it. 2674 2675 Examples: 2676 -------------------- 2677 auto vec = Vector!(int, 10).build(1, 2, 3); 2678 2679 assert(vec.moveFront == 1); 2680 assert(vec == [0, 2, 3]); 2681 -------------------- 2682 */ 2683 public ElementType moveFront()()scope{ 2684 this._bounds_check(0); 2685 2686 return move(*(()@trusted => this.ptr )()); 2687 } 2688 2689 2690 2691 /** 2692 Returns a reference to the last element in the vector. 2693 2694 Calling this function on an empty container causes undefined behavior. 2695 */ 2696 public ref inout(ElementType) back()inout return pure nothrow @system @nogc{ 2697 this._bounds_check(0); 2698 2699 return *((this.ptr - 1) + this.length) ; 2700 } 2701 2702 2703 2704 /** 2705 Returns a copy of the first element in the vector. 2706 2707 Examples: 2708 -------------------- 2709 auto vec = Vector!(int, 10).build(1, 2, 3); 2710 2711 assert(vec.backCopy == 3); 2712 assert(vec == [1, 2, 3]); 2713 -------------------- 2714 */ 2715 public auto backCopy(this This)()scope{ 2716 this._bounds_check(0); 2717 2718 return *(()@trusted => (this.ptr + (length - 1)) )(); 2719 } 2720 2721 2722 2723 /** 2724 Move of the last element in the vector and return it. 2725 2726 Examples: 2727 -------------------- 2728 auto vec = Vector!(int, 10).build(1, 2, 3); 2729 2730 assert(vec.moveBack == 3); 2731 assert(vec == [1, 2, 0]); 2732 -------------------- 2733 */ 2734 public ElementType moveBack()()scope{ 2735 this._bounds_check(0); 2736 return *(()@trusted => (this.ptr + (length - 1)) )(); 2737 } 2738 2739 2740 2741 /** 2742 Static function which return `Vector` construct from arguments `args`. 2743 2744 Parameters: 2745 `allocator` exists only if template parameter `_Allocator` has state. 2746 2747 `args` values of type `ElementType`, input range or `Vector`. 2748 2749 Examples: 2750 -------------------- 2751 import std.range : only; 2752 2753 auto vec = Vector!(int, 6).build(1, 2, [3, 4], only(5, 6), Vector!(int, 10).build(7, 8)); 2754 assert(vec == [1, 2, 3, 4, 5, 6, 7, 8]); 2755 -------------------- 2756 */ 2757 public static typeof(this) build(Args...)(auto ref Args args){ 2758 import core.lifetime : forward; 2759 2760 auto result = Vector.init; 2761 2762 result._build_impl(forward!args); 2763 2764 return ()@trusted{ 2765 return *&result; 2766 }(); 2767 } 2768 2769 /// ditto 2770 static if(allowHeap) 2771 public static typeof(this) build(Args...)(AllocatorType allocator, auto ref Args args){ 2772 import core.lifetime : forward; 2773 2774 auto result = (()@trusted => Vector(forward!allocator))(); 2775 2776 result._build_impl(forward!args); 2777 2778 return ()@trusted{ 2779 return *&result; 2780 }(); 2781 } 2782 2783 private void _build_impl(Args...)(auto ref Args args)scope{ 2784 import std.traits : isArray; 2785 2786 assert(this.empty); 2787 2788 size_t new_length = 0; 2789 2790 foreach(ref arg; args) 2791 new_length += emplaceLength(arg); 2792 2793 2794 if(new_length == 0) 2795 return; 2796 2797 this.reserve(new_length); 2798 2799 2800 /+foreach(alias arg; args) 2801 this.append(forward!arg); 2802 +/ 2803 2804 ElementType* ptr = (()@trusted => this.ptr )(); 2805 2806 foreach(alias arg; args){ 2807 const size_t len = emplaceLength(arg); 2808 2809 ElementType[] elms = (()@trusted => ptr[0 .. len] )(); 2810 2811 { 2812 size_t emplaced = 0; 2813 scope(failure) 2814 this.storage.length = (this.length + emplaced); 2815 2816 emplaceElements(emplaced, elms, forward!arg); 2817 } 2818 2819 2820 ()@trusted{ 2821 ptr += len; 2822 }(); 2823 2824 this.storage.length = (this.length + len); 2825 } 2826 } 2827 2828 2829 2830 //internals: 2831 private Storage storage; 2832 2833 static if(!allowHeap) 2834 private alias _allocator = statelessAllcoator!NullAllocator; 2835 else static if(hasStatelessAllocator) 2836 private alias _allocator = statelessAllcoator!AllocatorType; 2837 else 2838 private AllocatorType _allocator; 2839 2840 2841 //enforce: 2842 private void _enforce(bool con, string msg)const pure nothrow @safe @nogc{ 2843 if(!con)assert(0, msg); 2844 } 2845 2846 //grow: 2847 private static size_t _grow_capacity(size_t old_capacity, size_t new_capacity)pure nothrow @safe @nogc{ 2848 static if(minimalCapacity == 0) 2849 return max(2, old_capacity * 2, new_capacity); 2850 else 2851 return max(old_capacity * 2, new_capacity); 2852 } 2853 2854 //allocation: 2855 private void _allocate_heap()(ref Storage.Heap heap, size_t new_capacity)scope nothrow{ 2856 new_capacity = Storage.heapCapacity(new_capacity); 2857 2858 void[] data = _allocator.allocate(new_capacity * ElementType.sizeof); 2859 2860 _enforce(data.length != 0, "allocation fail"); 2861 2862 static if(supportGC) 2863 gcAddRange(data); 2864 2865 heap.ptr = (()@trusted => cast(ElementType*)data.ptr )(); 2866 heap.capacity = new_capacity; 2867 } 2868 2869 private void _deallocate_heap()(const ref Storage.Heap heap)scope nothrow{ 2870 void[] data = ()@trusted{ 2871 return cast(void[])heap.data; 2872 }(); 2873 2874 static if(supportGC) 2875 gcRemoveRange(data); 2876 2877 static if(safeAllcoate!(typeof(_allocator))) 2878 const d = ()@trusted{ 2879 return _allocator.deallocate(data); 2880 }(); 2881 2882 else 2883 const d = _allocator.deallocate(data); 2884 2885 _enforce(d, "deallocation fail"); 2886 } 2887 2888 private void _reallocate_heap(bool optional = false)(ref Storage.Heap heap, size_t new_capacity, const size_t length)scope nothrow{ 2889 new_capacity = Storage.heapCapacity(new_capacity); 2890 2891 import std.traits : hasElaborateMove; 2892 2893 if(heap.capacity >= new_capacity) 2894 return; 2895 2896 void[] data = heap.data; 2897 void[] old_data = data; 2898 2899 static if(!hasElaborateMove!ElementType){ 2900 static if(safeAllcoate!(typeof(_allocator))) 2901 const bool reallcoated = ()@trusted{ 2902 return _allocator.reallocate(data, new_capacity * ElementType.sizeof); 2903 }(); 2904 else 2905 const bool reallcoated = _allocator.reallocate(data, new_capacity * ElementType.sizeof); 2906 2907 if(reallcoated){ 2908 heap.ptr = (()@trusted => cast(ElementType*)data.ptr )(); 2909 heap.capacity = new_capacity; 2910 2911 static if(supportGC){ 2912 gcRemoveRange(old_data); 2913 gcAddRange(data); 2914 } 2915 2916 return; 2917 } 2918 } 2919 2920 2921 static if(!optional){ 2922 Storage.Heap heap_new; 2923 2924 { 2925 this._allocate_heap(heap_new, new_capacity); 2926 2927 moveEmplaceRangeImpl!false( 2928 (()@trusted => heap_new.ptr )(), 2929 (()@trusted => heap.ptr )(), 2930 length 2931 ); 2932 } 2933 2934 this._deallocate_heap(heap); 2935 2936 heap = heap_new; 2937 } 2938 } 2939 2940 //bounds check: 2941 private pragma(inline, true) void _bounds_check(const size_t pos)const pure nothrow @safe @nogc{ 2942 assert(pos < this.length); 2943 2944 version(BTL_VECTOR_BOUNDS_CHECK){ 2945 if(pos >= this.length){ 2946 assert(0, "btl.vector bounds check error"); 2947 } 2948 } 2949 } 2950 2951 private pragma(inline, true) void _bounds_check(const size_t pos, const size_t len)const pure nothrow @safe @nogc{ 2952 assert(pos <= this.length); 2953 assert((pos + len) <= this.length); 2954 2955 version(BTL_VECTOR_BOUNDS_CHECK){ 2956 if(pos > this.length){ 2957 assert(0, "btl.vector bounds check error"); 2958 } 2959 if((pos + len) > this.length){ 2960 assert(0, "btl.vector bounds check error"); 2961 } 2962 } 2963 } 2964 2965 private pragma(inline, true) void _bounds_check(const size_t[2] index)const pure nothrow @safe @nogc{ 2966 assert(index[0] <= this.length); 2967 assert(index[1] <= this.length); 2968 2969 version(BTL_VECTOR_BOUNDS_CHECK){ 2970 if(index[0] > this.length){ 2971 assert(0, "btl.vector bounds check error"); 2972 } 2973 if(index[1] > this.length){ 2974 assert(0, "btl.vector bounds check error"); 2975 } 2976 } 2977 } 2978 2979 } 2980 2981 2982 private{ 2983 2984 static size_t emplaceLength(Val)(ref Val val) 2985 if(is(immutable Val : immutable _Type)){ 2986 return 1; 2987 } 2988 2989 static size_t emplaceLength(Val)(ref Val val, const size_t count) 2990 if(is(immutable Val : immutable _Type)){ 2991 return count; 2992 } 2993 2994 static size_t emplaceLength(Vec)(ref Vec vec) 2995 if(isVector!Vec && is(immutable Vec.ElementType == immutable _Type)){ 2996 return vec.length; 2997 } 2998 2999 static size_t emplaceLength(R)(ref R range) 3000 if(hasLength!R && isBtlInputRange!R && is(immutable ElementEncodingType!R : immutable _Type)){ 3001 return range.length; 3002 } 3003 3004 3005 3006 static void emplaceElements(T, Val)(ref size_t emplaced, T[] slice, auto ref Val val, const size_t count) 3007 if(is(immutable Val : immutable _Type)){ 3008 assert(slice.length == count); 3009 3010 foreach(ref elm; slice){ 3011 emplaceImpl(elm, val); 3012 emplaced += 1; 3013 } 3014 } 3015 3016 static void emplaceElements(T, Val)(ref size_t emplaced, T[] slice, auto ref Val val) 3017 if(is(immutable Val : immutable _Type)){ 3018 assert(slice.length == 1); 3019 3020 foreach(ref elm; slice){ 3021 emplaceImpl(elm, val); 3022 emplaced += 1; 3023 } 3024 } 3025 3026 static void emplaceElements(T, R)(ref size_t emplaced, T[] slice, R range) 3027 if(hasLength!R && isBtlInputRange!R && is(immutable ElementEncodingType!R : immutable _Type)){ 3028 //TODO trivial copy 3029 auto ptr = (()@trusted => slice.ptr )(); 3030 3031 debug auto end_ptr = (()@trusted => ptr + slice.length )(); 3032 3033 while(!range.empty){ 3034 debug assert(ptr < end_ptr); 3035 3036 emplaceImpl(*ptr, range.front); 3037 emplaced += 1; 3038 3039 range.popFront(); 3040 ()@trusted{ 3041 ptr += 1; 3042 }(); 3043 } 3044 } 3045 3046 static void emplaceElements(T, Vec)(ref size_t emplaced, T[] slice, scope auto ref Vec vec) 3047 if(isVector!Vec && is(immutable Vec.ElementType == immutable _Type)){ 3048 emplaceElements(emplaced, slice, (()@trusted => vec.elements )() ); 3049 } 3050 3051 static void emplaceElements(T)(ref size_t emplaced, T[] slice){ 3052 3053 /// TODO emplaceRangeImpl if nothrow ctors 3054 foreach(ref elm; slice){ 3055 emplaceImpl(elm); 3056 emplaced += 1; 3057 } 3058 } 3059 3060 static void emplaceElementsArgs(T, Args...)(ref size_t emplaced, T[] slice, auto ref Args args){ 3061 3062 /// TODO emplaceRangeImpl if nothrow ctors 3063 foreach(ref elm; slice){ 3064 emplaceImpl(elm, args); 3065 emplaced += 1; 3066 } 3067 } 3068 3069 3070 3071 static void initElements(T)(T[] elements)nothrow{ 3072 enum has_init = __traits(compiles, (ref _Type elm) => emplaceElement(elm)); 3073 3074 static if(has_init){ 3075 foreach(ref elm; elements) 3076 emplaceElement(elm); 3077 return true; 3078 } 3079 else{ 3080 import std.traits : Unqual; 3081 3082 assert(0, "fatal error: " ~ Unqual!T.stringof ~ " has @disabled init"); 3083 3084 } 3085 } 3086 3087 } 3088 } 3089 3090 /// Alias to `Vector` with different order of template parameters 3091 template Vector( 3092 _Type, 3093 _Allocator, 3094 bool _supportGC = shouldAddGCRange!_Type 3095 ){ 3096 alias Vector = .Vector!(_Type, 0, _Allocator, _supportGC); 3097 } 3098 3099 /// 3100 pure nothrow @nogc unittest{ 3101 import std.range : only; 3102 import std.algorithm : map, equal; 3103 3104 static struct Foo{ 3105 int i; 3106 string str; 3107 } 3108 3109 Vector!(Foo, 4) vec; 3110 3111 assert(vec.empty); 3112 assert(vec.capacity == 4); 3113 assert(typeof(vec).minimalCapacity == 4); 3114 3115 vec.append(Foo(1, "A")); 3116 assert(vec.length == 1); 3117 3118 vec.append(only(Foo(2, "B"), Foo(3, "C"))); 3119 assert(vec.length == 3); 3120 3121 vec.emplaceBack(4, "D"); 3122 assert(vec.length == 4); 3123 assert(vec.capacity == 4); 3124 3125 vec.insert(1, Foo(5, "E")); 3126 assert(vec.length == 5); 3127 assert(vec.capacity > 4); 3128 assert(equal(vec[].map!(e => e.str), only("A", "E", "B", "C", "D"))); 3129 3130 vec.erase(vec[1 .. $-1]); //same as vec.erase(1, 3); 3131 assert(vec == only(Foo(1, "A"), Foo(4, "D"))); 3132 3133 3134 vec = Vector!(Foo, 2).build(Foo(-1, "X"), Foo(-2, "Y")); 3135 assert(equal(vec[].map!(e => e.str), only("X", "Y"))); 3136 3137 3138 vec.clear(); 3139 assert(vec.length == 0); 3140 assert(vec.capacity > 4); 3141 3142 vec.release(); 3143 assert(vec.length == 0); 3144 assert(vec.capacity == typeof(vec).minimalCapacity); 3145 3146 } 3147 3148 3149 /// Alias to `Vector` with `void` allcoator 3150 template FixedVector( 3151 _Type, 3152 size_t N , 3153 bool _supportGC = shouldAddGCRange!_Type 3154 ) 3155 if(N > 0){ 3156 alias FixedVector = .Vector!(_Type, N, void, _supportGC); 3157 } 3158 3159 3160 /// Alias to `Vector` with with `N > 0` 3161 template SmallVector( 3162 _Type, 3163 size_t N , 3164 _Allocator = DefaultAllocator, 3165 bool _supportGC = shouldAddGCRange!_Type 3166 ) 3167 if(N > 0){ 3168 alias SmallVector = .Vector!(_Type, N, _Allocator, _supportGC); 3169 } 3170 3171 3172 3173 3174 public alias hasCopyConstructor_SP = hasCopyConstructor; 3175 //local traits: 3176 package{ 3177 3178 enum bool safeAllcoate(A) = __traits(compiles, (ref A allcoator)@safe{ 3179 const size_t size; 3180 allcoator.allocate(size); 3181 }(*cast(A*)null)); 3182 3183 3184 //copy ctor: 3185 template hasCopyConstructor(From, To) 3186 if(is(immutable From == immutable To)){ 3187 3188 enum bool hasCopyConstructor = true 3189 && !is(From == shared) 3190 && isConstructable!(From, To) 3191 && isCopyConstructableElement!( 3192 GetElementType!From, 3193 GetElementType!To 3194 ) 3195 && (From.hasStatelessAllocator 3196 || isCopyConstructableElement!( 3197 GetAllocatorType!From, 3198 GetAllocatorType!To 3199 ) 3200 ) 3201 && (From.hasStatelessAllocator 3202 || isCopyConstructableElement!( 3203 GetAllocatorType!From, 3204 To.AllocatorType 3205 ) 3206 ); 3207 } 3208 3209 //Move Constructable: 3210 template isMoveConstructable(alias from, To){ 3211 alias From = typeof(from); 3212 3213 enum isMoveConstructable = true 3214 && !isRef!from 3215 && isConstructable!(From, To) 3216 && is(GetElementReferenceType!From : GetElementReferenceType!To) 3217 && is(immutable From.AllocatorType == immutable To.AllocatorType) 3218 && (From.hasStatelessAllocator 3219 || isMoveConstructableElement!( 3220 GetAllocatorType!From, 3221 GetAllocatorType!To 3222 ) 3223 ); 3224 } 3225 3226 //Move Assignable: 3227 template isMoveAssignable(alias from, To){ 3228 alias From = typeof(from); 3229 3230 enum isMoveAssignable = true 3231 && !isRef!from 3232 && isAssignable!(From, To) 3233 && is(GetElementReferenceType!From : GetElementReferenceType!To) 3234 && is(immutable From.AllocatorType == immutable To.AllocatorType) 3235 && (From.hasStatelessAllocator 3236 || isMoveAssignableElement!( 3237 GetAllocatorType!From, 3238 GetAllocatorType!To 3239 ) 3240 ); 3241 } 3242 3243 //Constructable: 3244 template isConstructable(From, To){ 3245 3246 enum isConstructable = true 3247 && !is(From == shared) 3248 && (From.supportGC == To.supportGC) 3249 && is(GetElementType!From : GetElementType!To) 3250 && (From.hasStatelessAllocator 3251 ? is(immutable From.AllocatorType == immutable To.AllocatorType) 3252 : is(immutable From.AllocatorType : immutable To.AllocatorType) 3253 ); 3254 } 3255 3256 //Assignable: 3257 template isAssignable(From, To){ 3258 import std.traits : isMutable; 3259 3260 enum isAssignable = true 3261 && isMutable!To 3262 && !is(From == shared) && !is(To == shared) 3263 && (From.supportGC == To.supportGC) 3264 && is(GetElementType!From : GetElementType!To); 3265 } 3266 3267 3268 3269 template GetElementType(Vec){ 3270 alias GetElementType = CopyTypeQualifiers!(Vec, Vec.ElementType); 3271 } 3272 3273 template GetAllocatorType(Vec){ 3274 alias GetAllocatorType = CopyTypeQualifiers!(Vec, Vec.AllocatorType); 3275 } 3276 3277 template GetElementReferenceType(Vec){ 3278 alias GetElementReferenceType = ElementReferenceTypeImpl!(GetElementType!Vec); 3279 } 3280 3281 template ElementReferenceTypeImpl(T){ 3282 import std.traits : Select, isDynamicArray; 3283 import std.range : ElementEncodingType; 3284 3285 static if(false 3286 || is(T == class) || is(T == interface) 3287 || is(T == function) || is(T == delegate) 3288 || is(T : U*, U) 3289 ){ 3290 alias ElementReferenceTypeImpl = T; 3291 } 3292 else static if(isDynamicArray!T){ 3293 alias ElementReferenceTypeImpl = ElementEncodingType!T[]; 3294 } 3295 else{ 3296 alias ElementReferenceTypeImpl = T*; 3297 } 3298 } 3299 3300 3301 } 3302 3303 3304 //Vector examples: 3305 version(unittest){ 3306 3307 private alias ZeroVector(T, size_t N, A = Mallocator) = .Vector!(T, 0, A); 3308 3309 import std.range : only; 3310 static foreach(alias Vector; AliasSeq!(.Vector, ZeroVector)){ 3311 3312 //Vector.minimalCapacity 3313 pure nothrow @safe @nogc unittest{ 3314 Vector!(int, 10) vec; 3315 assert(vec.capacity == typeof(vec).minimalCapacity); 3316 } 3317 3318 //Vector.empty 3319 pure nothrow @safe @nogc unittest{ 3320 Vector!(int, 10) vec; 3321 assert(vec.empty); 3322 3323 vec.append(42); 3324 assert(!vec.empty); 3325 } 3326 3327 //Vector.full 3328 pure nothrow @safe @nogc unittest{ 3329 Vector!(int, 4, void) vec; //FixedVector 3330 assert(vec.empty); 3331 assert(vec.maximalCapacity == vec.minimalCapacity); 3332 3333 vec.resize(vec.maximalCapacity); 3334 assert(vec.full); 3335 } 3336 3337 //Vector.length 3338 pure nothrow @safe @nogc unittest{ 3339 Vector!(int, 10) vec = null; 3340 assert(vec.length == 0); 3341 3342 vec.append(42); 3343 assert(vec.length == 1); 3344 3345 vec.append(123); 3346 assert(vec.length == 2); 3347 3348 vec.clear(); 3349 assert(vec.length == 0); 3350 } 3351 3352 //Vector.capacity 3353 pure nothrow @safe @nogc unittest{ 3354 Vector!(int, 10) vec; 3355 assert(vec.capacity == typeof(vec).minimalCapacity); 3356 3357 vec.reserve(max(2, vec.capacity * 2)); 3358 assert(vec.capacity > typeof(vec).minimalCapacity); 3359 } 3360 3361 //Vector.ptr 3362 pure nothrow @nogc unittest{ 3363 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3); 3364 3365 assert(vec.ptr[0 .. 3] == [1, 2, 3]); 3366 } 3367 3368 //Vector.elements 3369 pure nothrow @nogc unittest{ 3370 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3); 3371 3372 int[] slice = vec.elements; 3373 assert(slice.length == vec.length); 3374 assert(slice.ptr is vec.ptr); 3375 3376 const size_t old_capacity = vec.capacity; 3377 vec.reserve(max(2, vec.capacity * 2)); 3378 assert(vec.capacity != old_capacity); 3379 assert(slice.length == vec.length); 3380 // slice contains dangling pointer! 3381 } 3382 3383 //Vector.front 3384 pure nothrow @nogc @system unittest{ 3385 auto vec = Vector!(int, 10).build(1, 2, 3); 3386 3387 assert(vec.front == 1); 3388 } 3389 3390 //Vector.frontCopy 3391 pure nothrow @nogc @safe unittest{ 3392 auto vec = Vector!(int, 10).build(1, 2, 3); 3393 3394 assert(vec.frontCopy == 1); 3395 assert(vec == [1, 2, 3]); 3396 } 3397 3398 //Vector.moveFront 3399 pure nothrow @nogc @safe unittest{ 3400 auto vec = Vector!(int, 10).build(1, 2, 3); 3401 3402 assert(vec.moveFront == 1); 3403 assert(vec == [1, 2, 3]); 3404 } 3405 3406 //Vector.back 3407 pure nothrow @nogc @system unittest{ 3408 auto vec = Vector!(int, 10).build(1, 2, 3); 3409 3410 assert(vec.back == 3); 3411 } 3412 3413 //Vector.backCopy 3414 pure nothrow @nogc @safe unittest{ 3415 auto vec = Vector!(int, 10).build(1, 2, 3); 3416 3417 assert(vec.backCopy == 3); 3418 assert(vec == [1, 2, 3]); 3419 } 3420 3421 //Vector.moveBack 3422 pure nothrow @nogc @safe unittest{ 3423 auto vec = Vector!(int, 10).build(1, 2, 3); 3424 3425 assert(vec.moveBack == 3); 3426 assert(vec == [1, 2, 3]); 3427 } 3428 3429 3430 //Vector.popBack 3431 pure nothrow @nogc @safe unittest{ 3432 Vector!(int, 6) vec = Vector!(int, 6).build(10, 20, 30); 3433 assert(vec.length == 3); 3434 3435 assert(vec.popBack == 30); 3436 assert(vec.length == 2); 3437 3438 assert(vec.popBack == 20); 3439 assert(vec.length == 1); 3440 3441 assert(vec.popBack == 10); 3442 assert(vec.empty); 3443 3444 assert(vec.popBack == int.init); 3445 assert(vec.empty); 3446 } 3447 3448 //Vector.pop 3449 pure nothrow @nogc @safe unittest{ 3450 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3, 4, 5); 3451 assert(vec.length == 5); 3452 3453 assert(vec.pop(0) == 1); 3454 assert(vec == [2, 3, 4, 5]); 3455 3456 assert(vec.pop(3) == 5); 3457 assert(vec == [2, 3, 4]); 3458 3459 assert(vec.pop(1) == 3); 3460 assert(vec == [2, 4]); 3461 } 3462 3463 //Vector.clear 3464 pure nothrow @nogc @safe unittest{ 3465 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3); 3466 3467 vec.reserve(vec.capacity * 2); 3468 assert(vec.length == 3); 3469 3470 const size_t cap = vec.capacity; 3471 vec.clear(); 3472 assert(vec.capacity == cap); 3473 } 3474 3475 //Vector.release 3476 pure nothrow @nogc @safe unittest{ 3477 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3); 3478 3479 vec.reserve(vec.capacity * 2); 3480 assert(vec.length == 3); 3481 3482 const size_t cap = vec.capacity; 3483 vec.clear(); 3484 assert(vec.capacity == cap); 3485 3486 vec.release(); 3487 assert(vec.capacity == typeof(vec).minimalCapacity); 3488 assert(vec.capacity < cap); 3489 } 3490 3491 //Vector.reserve 3492 pure nothrow @nogc @safe unittest{ 3493 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3); 3494 3495 const size_t old_capacity = vec.capacity;//assert(vec.capacity == typeof(vec).minimalCapacity); 3496 const size_t cap = (vec.capacity * 2); 3497 3498 vec.reserve(cap); 3499 assert(vec.capacity > old_capacity); 3500 assert(vec.capacity >= cap); 3501 } 3502 3503 //Vector.resize 3504 pure nothrow @nogc @safe unittest{ 3505 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3); 3506 3507 vec.resize(5, 0); 3508 assert(vec == [1, 2, 3, 0, 0]); 3509 3510 vec.resize(2); 3511 assert(vec == [1, 2]); 3512 } 3513 3514 //Vector.downsize 3515 pure nothrow @nogc @safe unittest{ 3516 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3); 3517 3518 vec.downsize(5); 3519 assert(vec == [1, 2, 3]); 3520 3521 vec.downsize(2); 3522 assert(vec == [1, 2]); 3523 } 3524 3525 //Vector.upsize 3526 pure nothrow @nogc @safe unittest{ 3527 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3); 3528 3529 vec.upsize(5, 0); 3530 assert(vec == [1, 2, 3, 0, 0]); 3531 3532 vec.upsize(2); 3533 assert(vec == [1, 2, 3, 0, 0]); 3534 } 3535 3536 //Vector.shrinkToFit 3537 pure nothrow @nogc @safe unittest{ 3538 auto vec = Vector!(int, 3).build(1, 2, 3); 3539 3540 3541 assert(vec.capacity == vec.length); 3542 3543 vec.reserve(vec.capacity * 2); 3544 assert(vec.capacity > vec.length); 3545 3546 static if(typeof(vec).minimalCapacity != 0){ 3547 vec.shrinkToFit(); 3548 assert(vec.capacity == vec.length); 3549 } 3550 } 3551 3552 //Vector._ctor 3553 pure nothrow @nogc @safe unittest{ 3554 { 3555 Vector!(int, 6) vec = null; 3556 assert(vec.empty); 3557 } 3558 3559 { 3560 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2); 3561 assert(vec == [1, 2]); 3562 } 3563 3564 { 3565 auto tmp = Vector!(int, 6).build(1, 2); 3566 Vector!(int, 6) vec = tmp; 3567 assert(vec == [1, 2]); 3568 } 3569 3570 3571 { 3572 Vector!(int, 6) vec = Vector!(int, 4).build(1, 2); 3573 assert(vec == [1, 2]); 3574 } 3575 3576 { 3577 auto tmp = Vector!(int, 4).build(1, 2); 3578 Vector!(int, 6) vec = tmp; 3579 assert(vec == [1, 2]); 3580 } 3581 3582 { 3583 int[3] tmp = [1, 2, 3]; 3584 Vector!(int, 6) vec = tmp[]; 3585 assert(vec == [1, 2, 3]); 3586 } 3587 3588 { 3589 struct Range{ 3590 int i; 3591 3592 bool empty()(){return i == 0;} 3593 int front()(){return i;} 3594 void popFront()(){i -= 1;} 3595 //size_t length(); //no length 3596 } 3597 3598 Vector!(int, 6) vec = Range(3); 3599 assert(vec == [3, 2, 1]); 3600 } 3601 } 3602 3603 //Vector.opAssign 3604 pure nothrow @nogc @safe unittest{ 3605 { 3606 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3); 3607 assert(!vec.empty); 3608 3609 vec = null; 3610 assert(vec.empty); 3611 3612 vec = Vector!(int, 42).build(3, 2, 1); 3613 assert(vec == [3, 2, 1]); 3614 3615 vec = Vector!(int, 2).build(4, 2); 3616 assert(vec == [4, 2]); 3617 } 3618 3619 { 3620 Vector!(int, 6) vec = null; 3621 int[3] tmp = [1, 2, 3]; 3622 vec = tmp[]; 3623 assert(vec == [1, 2, 3]); 3624 } 3625 3626 { 3627 struct Range{ 3628 int i; 3629 3630 bool empty()(){return i == 0;} 3631 int front()(){return i;} 3632 void popFront()(){i -= 1;} 3633 //size_t length(); //no length 3634 } 3635 3636 Vector!(int, 6) vec = null; 3637 vec = Range(3); 3638 assert(vec == [3, 2, 1]); 3639 } 3640 } 3641 3642 //Vector.contains 3643 pure nothrow @nogc @safe unittest{ 3644 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3); 3645 3646 assert(vec.contains(1)); 3647 assert(!vec.contains(42L)); 3648 } 3649 3650 //Vector.opBinaryRight!"in" 3651 pure nothrow @nogc @safe unittest{ 3652 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3); 3653 3654 assert(1 in vec); 3655 assert(42L !in vec); 3656 } 3657 3658 //Vector.opEquals 3659 pure nothrow @nogc @safe unittest{ 3660 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3); 3661 3662 assert(vec != null); 3663 assert(null != vec); 3664 3665 assert(vec == [1, 2, 3]); 3666 assert([1, 2, 3] == vec); 3667 3668 assert(vec == typeof(vec).build(1, 2, 3)); 3669 assert(typeof(vec).build(1, 2, 3) == vec); 3670 3671 3672 import std.range : only; 3673 assert(vec == only(1, 2, 3)); 3674 assert(only(1, 2, 3) == vec); 3675 } 3676 3677 //Vector.opCmp 3678 pure nothrow @nogc @safe unittest{ 3679 auto a1 = Vector!(int, 6).build(1, 2, 3); 3680 auto a2 = Vector!(int, 6).build(1, 2, 3, 4); 3681 auto b = Vector!(int, 6).build(3, 2, 1); 3682 3683 assert(a1 < b); 3684 assert(a1 < a2); 3685 assert(a2 < b); 3686 assert(a1 <= a1); 3687 } 3688 3689 //Vector.opIndexAssign 3690 pure nothrow @nogc @safe unittest{ 3691 3692 { 3693 auto vec = Vector!(int, 4).build(1, 2, 3, 4, 5); 3694 3695 vec[1] = 42; 3696 3697 assert(vec == [1, 42, 3, 4, 5]); 3698 } 3699 3700 { 3701 auto vec = Vector!(int, 4).build(1, 2, 3, 4, 5); 3702 3703 vec[1 .. $-1] = 42; 3704 3705 assert(vec == [1, 42, 42, 42, 5]); 3706 } 3707 } 3708 3709 //Vector.opIndexOpAssign 3710 pure nothrow @nogc @safe unittest{ 3711 { 3712 auto vec = Vector!(int, 4).build(1, 2, 3, 4, 5); 3713 3714 vec[1] += 40; 3715 3716 assert(vec == [1, 42, 3, 4, 5]); 3717 } 3718 3719 { 3720 auto vec = Vector!(int, 4).build(1, 2, 3, 4, 5); 3721 3722 vec[1 .. $-1] *= -1; 3723 3724 assert(vec == [1, -2, -3, -4, 5]); 3725 } 3726 } 3727 3728 //Vector.opIndex() 3729 pure nothrow @nogc @system unittest{ 3730 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3); 3731 3732 scope int[] slice = vec[]; 3733 assert(slice.length == vec.length); 3734 assert(slice.ptr is vec.ptr); 3735 3736 vec.reserve(vec.capacity * 2); 3737 assert(slice.length == vec.length); 3738 // slice contains dangling pointer! 3739 } 3740 3741 //Vector.opSlice(begin, end) 3742 pure nothrow @nogc @system unittest{ 3743 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3, 4, 5, 6); 3744 3745 assert(vec[1 .. 4] == [2, 3, 4]); 3746 assert(vec[1 .. $] == [2, 3, 4, 5, 6]); 3747 } 3748 3749 //Vector.opIndex 3750 pure nothrow @nogc @system unittest{ 3751 auto vec = Vector!(int, 10).build(1, 2, 3); 3752 3753 assert(vec[1] == 2); 3754 } 3755 3756 //Vector.at 3757 pure nothrow @nogc @system unittest{ 3758 auto vec = Vector!(int, 10).build(1, 2, 3); 3759 3760 assert(vec.at(1) == 2); 3761 } 3762 3763 //Vector.atCopy 3764 pure nothrow @nogc @safe unittest{ 3765 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3, 4, 5, 6); 3766 3767 assert(vec.atCopy(3) == 4); 3768 assert(vec.atCopy(vec.length-1) == 6); 3769 3770 } 3771 3772 //Vector.proxySwap 3773 pure nothrow @nogc @system unittest{ 3774 auto a = Vector!(int, 6).build(1, 2, 3); 3775 auto b = Vector!(int, 6).build(4, 5, 6, 7); 3776 3777 a.proxySwap(b); 3778 assert(a == [4, 5, 6, 7]); 3779 assert(b == [1, 2, 3]); 3780 3781 import std.algorithm.mutation : swap; 3782 3783 swap(a, b); 3784 assert(a == [1, 2, 3]); 3785 assert(b == [4, 5, 6, 7]); 3786 } 3787 3788 3789 //Vector.emplace 3790 pure nothrow @nogc @system unittest{ 3791 { 3792 auto vec = Vector!(int, 6).build(1, 2, 3); 3793 3794 vec.emplace(1, 42); 3795 //debug writeln(vec[]); 3796 assert(vec == [1, 42, 2, 3]); 3797 3798 vec.emplace(4, 314); 3799 assert(vec == [1, 42, 2, 3, 314]); 3800 3801 vec.emplace(100, -1); 3802 assert(vec == [1, 42, 2, 3, 314, -1]); 3803 } 3804 3805 { 3806 auto vec = Vector!(int, 6).build(1, 2, 3); 3807 3808 vec.emplace(vec.ptr + 1, 42); 3809 assert(vec == [1, 42, 2, 3]); 3810 3811 vec.emplace(vec.ptr + 4, 314); 3812 assert(vec == [1, 42, 2, 3, 314]); 3813 3814 vec.emplace(vec.ptr + 100, -1); 3815 assert(vec == [1, 42, 2, 3, 314, -1]); 3816 } 3817 3818 { 3819 static struct Foo{ 3820 int i; 3821 string str; 3822 } 3823 3824 auto vec = Vector!(Foo, 6).build(Foo(1, "A")); 3825 3826 vec.emplace(1, 2, "B"); 3827 assert(vec == only(Foo(1, "A"), Foo(2, "B"))); 3828 3829 vec.emplace(0, 42, "X"); 3830 assert(vec == only(Foo(42, "X"), Foo(1, "A"), Foo(2, "B"))); 3831 } 3832 } 3833 3834 3835 //Vector.emplaceBack 3836 pure nothrow @nogc @system unittest{ 3837 { 3838 auto vec = Vector!(int, 6).build(1, 2, 3); 3839 3840 vec.emplaceBack(42); 3841 assert(vec == [1, 2, 3, 42]); 3842 3843 vec.emplaceBack(); 3844 assert(vec == [1, 2, 3, 42, 0]); 3845 } 3846 3847 { 3848 static struct Foo{ 3849 int i; 3850 string str; 3851 } 3852 3853 auto vec = Vector!(Foo, 6).build(Foo(1, "A")); 3854 3855 vec.emplaceBack(2, "B"); 3856 assert(vec == only(Foo(1, "A"), Foo(2, "B"))); 3857 } 3858 } 3859 3860 //Vector.append 3861 pure nothrow @nogc @system unittest{ 3862 { 3863 auto vec = Vector!(int, 6).build(1, 2, 3); 3864 3865 vec.append(42); 3866 assert(vec == [1, 2, 3, 42]); 3867 } 3868 3869 { 3870 auto vec = Vector!(int, 6).build(1, 2, 3); 3871 3872 vec.append(only(4, 5, 6)); 3873 assert(vec == [1, 2, 3, 4, 5, 6]); 3874 } 3875 3876 { 3877 auto a = Vector!(int, 6).build(1, 2, 3); 3878 auto b = Vector!(int, 6).build(4, 5, 6); 3879 3880 a.append(b); 3881 assert(a == [1, 2, 3, 4, 5, 6]); 3882 } 3883 3884 { 3885 Vector!(int, 3) vec = Vector!(int, 3).build(1, 2, 3); 3886 int[3] tmp = [4, 5, 6]; 3887 vec.append(tmp[]); 3888 assert(vec == [1, 2, 3, 4, 5, 6]); 3889 } 3890 3891 { 3892 struct Range{ 3893 int i; 3894 3895 bool empty()(){return i == 0;} 3896 int front()(){return i;} 3897 void popFront()(){i -= 1;} 3898 //size_t length(); //no length 3899 } 3900 3901 Vector!(int, 3) vec = Vector!(int, 3).build(6, 5, 4); 3902 vec.append(Range(3)); 3903 assert(vec == [6, 5, 4, 3, 2, 1]); 3904 } 3905 3906 } 3907 3908 //Vector.insert 3909 pure nothrow @nogc @system unittest{ 3910 //pos: 3911 { 3912 auto vec = Vector!(int, 3).build(1, 2, 3); 3913 3914 size_t pos = vec.insert(1, 42, 2); 3915 assert(pos == 1); 3916 assert(vec == [1, 42, 42, 2, 3]); 3917 3918 pos = vec.insert(100, 4, 3); 3919 assert(pos == 5); 3920 assert(vec == [1, 42, 42, 2, 3, 4, 4, 4]); 3921 } 3922 3923 { 3924 auto vec = Vector!(int, 3).build(1, 2, 3); 3925 3926 size_t pos = vec.insert(1, only(20, 30, 40)); 3927 assert(pos == 1); 3928 assert(vec == [1, 20, 30, 40, 2, 3]); 3929 3930 pos = vec.insert(100, only(4, 5, 6)); 3931 assert(pos == 6); 3932 assert(vec == [1, 20, 30, 40, 2, 3, 4, 5, 6]); 3933 } 3934 3935 { 3936 auto vec = Vector!(int, 3).build(1, 2, 3); 3937 auto tmp = Vector!(int, 10).build(-1, -2, -3); 3938 3939 size_t pos = vec.insert(1, tmp); 3940 assert(pos == 1); 3941 assert(vec == [1, -1, -2, -3, 2, 3]); 3942 3943 pos = vec.insert(100, Vector!(int, 10).build(40, 50, 60)); 3944 assert(pos == 6); 3945 assert(vec == [1, -1, -2, -3, 2, 3, 40, 50, 60]); 3946 } 3947 3948 //ptr: 3949 { 3950 auto vec = Vector!(int, 3).build(1, 2, 3); 3951 3952 size_t pos = vec.insert(vec.ptr + 1, 42, 2); 3953 assert(pos == 1); 3954 assert(vec == [1, 42, 42, 2, 3]); 3955 3956 pos = vec.insert(vec.ptr + 100, 4, 3); 3957 assert(pos == 5); 3958 assert(vec == [1, 42, 42, 2, 3, 4, 4, 4]); 3959 } 3960 3961 { 3962 auto vec = Vector!(int, 3).build(1, 2, 3); 3963 3964 size_t pos = vec.insert(vec.ptr + 1, only(20, 30, 40)); 3965 assert(pos == 1); 3966 assert(vec == [1, 20, 30, 40, 2, 3]); 3967 3968 pos = vec.insert(vec.ptr + 100, only(4, 5, 6)); 3969 assert(pos == 6); 3970 assert(vec == [1, 20, 30, 40, 2, 3, 4, 5, 6]); 3971 } 3972 3973 { 3974 auto vec = Vector!(int, 3).build(1, 2, 3); 3975 auto tmp = Vector!(int, 10).build(-1, -2, -3); 3976 3977 size_t pos = vec.insert(vec.ptr + 1, tmp); 3978 assert(pos == 1); 3979 assert(vec == [1, -1, -2, -3, 2, 3]); 3980 3981 pos = vec.insert(vec.ptr + 100, Vector!(int, 10).build(40, 50, 60)); 3982 assert(pos == 6); 3983 assert(vec == [1, -1, -2, -3, 2, 3, 40, 50, 60]); 3984 } 3985 } 3986 3987 //Vector.erase 3988 pure nothrow @nogc @system unittest{ 3989 //pos: 3990 { 3991 auto vec = Vector!(int, 3).build(1, 2, 3, 4, 5, 6); 3992 3993 size_t pos = vec.erase(3); 3994 assert(pos == 3); 3995 assert(vec == [1, 2, 3]); 3996 3997 pos = vec.erase(100); 3998 assert(pos == 3); 3999 assert(vec == [1, 2, 3]); 4000 } 4001 4002 { 4003 auto vec = Vector!(int, 3).build(1, 2, 3, 4, 5, 6); 4004 4005 size_t pos = vec.erase(1, 4); 4006 assert(pos == 1); 4007 assert(vec == [1, 6]); 4008 4009 pos = vec.erase(100, 4); 4010 assert(pos == 2); 4011 assert(vec == [1, 6]); 4012 4013 pos = vec.erase(0, 100); 4014 assert(pos == 0); 4015 assert(vec.empty); 4016 } 4017 4018 //ptr: 4019 { 4020 auto vec = Vector!(int, 3).build(1, 2, 3, 4, 5, 6); 4021 4022 size_t pos = vec.erase(vec.ptr + 3); 4023 assert(pos == 3); 4024 assert(vec == [1, 2, 3]); 4025 4026 pos = vec.erase(vec.ptr + 100); 4027 assert(pos == 3); 4028 assert(vec == [1, 2, 3]); 4029 } 4030 4031 { 4032 auto vec = Vector!(int, 3).build(1, 2, 3, 4, 5, 6); 4033 4034 size_t pos = vec.erase(vec[1 .. 5]); 4035 assert(pos == 1); 4036 assert(vec == [1, 6]); 4037 } 4038 } 4039 4040 //Vector.replace 4041 pure nothrow @nogc @system unittest{ 4042 //pos: 4043 { 4044 auto vec = Vector!(int, 3).build(1, 2, 3, 4, 5, 6); 4045 4046 size_t pos = vec.replace(2, 2, 0, 5); 4047 assert(pos == 2); 4048 assert(vec == [1, 2, 0, 0, 0, 0, 0, 5, 6]); 4049 4050 pos = vec.replace(100, 2, 42, 2); 4051 assert(pos == 9); 4052 assert(vec == [1, 2, 0, 0, 0, 0, 0, 5, 6, 42, 42]); 4053 4054 pos = vec.replace(2, 100, -1); 4055 assert(pos == 2); 4056 assert(vec == [1, 2, -1]); 4057 } 4058 4059 { 4060 auto vec = Vector!(int, 3).build(1, 2, 3, 4, 5, 6); 4061 4062 size_t pos = vec.replace(2, 2, only(0, 0, 0, 0, 0)); 4063 assert(pos == 2); 4064 assert(vec == [1, 2, 0, 0, 0, 0, 0, 5, 6]); 4065 4066 pos = vec.replace(100, 2, only(42, 42)); 4067 assert(pos == 9); 4068 assert(vec == [1, 2, 0, 0, 0, 0, 0, 5, 6, 42, 42]); 4069 4070 pos = vec.replace(2, 100, only(-1)); 4071 assert(pos == 2); 4072 assert(vec == [1, 2, -1]); 4073 } 4074 4075 { 4076 auto vec = Vector!(int, 3).build(1, 2, 3, 4, 5, 6); 4077 4078 size_t pos = vec.replace(2, 2, Vector!(int, 3).build(0, 0, 0, 0, 0)); 4079 assert(pos == 2); 4080 assert(vec == [1, 2, 0, 0, 0, 0, 0, 5, 6]); 4081 4082 pos = vec.replace(100, 2, Vector!(int, 2).build(42, 42)); 4083 assert(pos == 9); 4084 assert(vec == [1, 2, 0, 0, 0, 0, 0, 5, 6, 42, 42]); 4085 4086 pos = vec.replace(2, 100, Vector!(int, 2).build(-1)); 4087 assert(pos == 2); 4088 assert(vec == [1, 2, -1]); 4089 } 4090 4091 //ptr: 4092 { 4093 auto vec = Vector!(int, 3).build(1, 2, 3, 4, 5, 6); 4094 4095 size_t pos = vec.replace(vec[2 .. 4], 0, 5); 4096 assert(pos == 2); 4097 assert(vec == [1, 2, 0, 0, 0, 0, 0, 5, 6]); 4098 4099 pos = vec.replace(vec.ptr[100 .. 102], 42, 2); 4100 assert(pos == 9); 4101 assert(vec == [1, 2, 0, 0, 0, 0, 0, 5, 6, 42, 42]); 4102 4103 pos = vec.replace(vec.ptr[2 .. 100], -1); 4104 assert(pos == 2); 4105 assert(vec == [1, 2, -1]); 4106 } 4107 4108 { 4109 auto vec = Vector!(int, 3).build(1, 2, 3, 4, 5, 6); 4110 4111 size_t pos = vec.replace(vec[2 .. 4], only(0, 0, 0, 0, 0)); 4112 assert(pos == 2); 4113 assert(vec == [1, 2, 0, 0, 0, 0, 0, 5, 6]); 4114 4115 pos = vec.replace(vec.ptr[100 .. 102], only(42, 42)); 4116 assert(pos == 9); 4117 assert(vec == [1, 2, 0, 0, 0, 0, 0, 5, 6, 42, 42]); 4118 4119 pos = vec.replace(vec.ptr[2 .. 100], only(-1)); 4120 assert(pos == 2); 4121 assert(vec == [1, 2, -1]); 4122 } 4123 4124 { 4125 auto vec = Vector!(int, 3).build(1, 2, 3, 4, 5, 6); 4126 4127 size_t pos = vec.replace(vec[2 .. 4], Vector!(int, 3).build(0, 0, 0, 0, 0)); 4128 assert(pos == 2); 4129 assert(vec == [1, 2, 0, 0, 0, 0, 0, 5, 6]); 4130 4131 pos = vec.replace(vec.ptr[100 .. 102], Vector!(int, 2).build(42, 42)); 4132 assert(pos == 9); 4133 assert(vec == [1, 2, 0, 0, 0, 0, 0, 5, 6, 42, 42]); 4134 4135 pos = vec.replace(vec.ptr[2 .. 100], Vector!(int, 2).build(-1)); 4136 assert(pos == 2); 4137 assert(vec == [1, 2, -1]); 4138 } 4139 } 4140 4141 //Vector.owns 4142 pure nothrow @nogc @system unittest{ 4143 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3, 4, 5, 6); 4144 4145 { 4146 assert(vec.owns(vec.ptr + 3)); 4147 assert(!vec.owns(cast(int*)null)); 4148 assert(!vec.owns(vec.ptr + 100)); 4149 } 4150 4151 { 4152 assert(vec.owns(&vec[$-1])); 4153 assert(!vec.owns(cast(long*)&vec[$-1])); 4154 } 4155 } 4156 4157 //Vector.ownsElement 4158 pure nothrow @nogc @system unittest{ 4159 Vector!(int, 6) vec = Vector!(int, 6).build(1, 2, 3, 4, 5, 6); 4160 4161 { 4162 assert(vec.ownsElement(vec.ptr + 3)); 4163 assert(!vec.ownsElement(cast(int*)null)); 4164 assert(!vec.ownsElement(vec.ptr + 100)); 4165 } 4166 4167 { 4168 const int* p = cast(int*)((cast(byte*)vec.ptr) + 1); 4169 assert(vec.owns(p)); 4170 assert(!vec.ownsElement(p)); 4171 } 4172 } 4173 4174 //Vector.build 4175 pure nothrow @nogc @safe unittest{ 4176 import std.range : only; 4177 4178 auto vec = Vector!(int, 6).build(1, 2, only(3, 4), only(5, 6), Vector!(int, 10).build(7, 8)); 4179 assert(vec == [1, 2, 3, 4, 5, 6, 7, 8]); 4180 } 4181 } 4182 } 4183 4184 4185 //ctors + assign tests: 4186 version(unittest){ 4187 struct Foo{ 4188 4189 static class Counter{ 4190 this(char name)pure @safe @nogc nothrow{ 4191 this.name = name; 4192 } 4193 char name; 4194 int objects = 0; 4195 uint ctor; 4196 uint copy; 4197 uint dtor; 4198 uint move_assign; 4199 uint copy_assign; 4200 uint move; 4201 } 4202 private Counter counter; 4203 4204 //@disable this(); 4205 4206 void opPostMove(const scope ref typeof(this))pure nothrow @safe @nogc{ 4207 if(counter) 4208 counter.move += 1; 4209 } 4210 this(Counter counter)pure nothrow @safe @nogc{ 4211 this.counter = counter; 4212 counter.objects += 1; 4213 counter.ctor += 1; 4214 } 4215 4216 this(ref scope typeof(this) rhs)pure nothrow @safe @nogc{ 4217 this.counter = (()@trusted => rhs.counter )(); 4218 4219 if(counter){ 4220 counter.objects += 1; 4221 counter.copy += 1; 4222 } 4223 } 4224 4225 ~this()scope pure nothrow @safe @nogc{ 4226 if(counter){ 4227 counter.objects -= 1; 4228 counter.dtor += 1; 4229 } 4230 } 4231 4232 void opAssign(ref scope typeof(this) rhs)scope pure nothrow @safe @nogc{ 4233 this.counter = (()@trusted => rhs.counter )(); 4234 4235 if(counter){ 4236 counter.objects += 1; 4237 counter.copy_assign += 1; 4238 } 4239 } 4240 4241 void opAssign(scope typeof(this) rhs)scope pure nothrow @safe @nogc{ 4242 this.counter = (()@trusted => *&rhs.counter )(); 4243 if(counter){ 4244 counter.move_assign += 1; 4245 rhs.counter = null; 4246 } 4247 } 4248 4249 4250 } 4251 4252 //ctors: 4253 pure nothrow @safe unittest{ 4254 import core.lifetime : move; 4255 import std.range : iota, array; 4256 import std.algorithm : map, all; 4257 4258 Foo.Counter[3] counters = [new Foo.Counter('A'), new Foo.Counter('B'), new Foo.Counter('C')]; 4259 4260 //small->small 4261 { 4262 //copy 4263 assert(counters[].all!(c => c.objects == 0)); 4264 { 4265 auto vec = Vector!(Foo, 4).build(iota(0, 3, 1).map!(x => Foo(counters[x]))); 4266 assert(counters[].all!(c => c.objects == 1)); 4267 assert(vec.small); 4268 4269 auto vec2 = vec; 4270 assert(counters[].all!(c => c.objects == 2)); 4271 assert(vec2.small); 4272 } 4273 4274 //move 4275 assert(counters[].all!(c => c.objects == 0)); 4276 { 4277 auto vec = Vector!(Foo, 4).build(iota(0, 3, 1).map!(x => Foo(counters[x]))); 4278 assert(counters[].all!(c => c.objects == 1)); 4279 assert(vec.small); 4280 4281 auto vec2 = move(vec); 4282 assert(counters[].all!(c => c.objects == 1)); 4283 assert(vec2.small); 4284 } 4285 } 4286 4287 //large->large 4288 { 4289 //copy 4290 assert(counters[].all!(c => c.objects == 0)); 4291 { 4292 auto vec = Vector!(Foo, 2).build(iota(0, 3, 1).map!(x => Foo(counters[x]))); 4293 assert(counters[].all!(c => c.objects == 1)); 4294 assert(!vec.small); 4295 4296 auto vec2 = vec; 4297 assert(counters[].all!(c => c.objects == 2)); 4298 assert(!vec2.small); 4299 } 4300 4301 //move 4302 assert(counters[].all!(c => c.objects == 0)); 4303 { 4304 auto vec = Vector!(Foo, 2).build(iota(0, 3, 1).map!(x => Foo(counters[x]))); 4305 assert(counters[].all!(c => c.objects == 1)); 4306 assert(!vec.small); 4307 4308 auto vec2 = move(vec); 4309 assert(counters[].all!(c => c.objects == 1)); 4310 assert(!vec2.small); 4311 } 4312 4313 } 4314 4315 4316 //large->small 4317 { 4318 //copy 4319 assert(counters[].all!(c => c.objects == 0)); 4320 { 4321 auto vec = Vector!(Foo, 2).build(iota(0, 3, 1).map!(x => Foo(counters[x]))); 4322 assert(counters[].all!(c => c.objects == 1)); 4323 assert(!vec.small); 4324 4325 Vector!(Foo, 4) vec2 = vec; 4326 assert(counters[].all!(c => c.objects == 2)); 4327 assert(vec2.small); 4328 } 4329 4330 //move 4331 assert(counters[].all!(c => c.objects == 0)); 4332 { 4333 auto vec = Vector!(Foo, 2).build(iota(0, 3, 1).map!(x => Foo(counters[x]))); 4334 assert(counters[].all!(c => c.objects == 1)); 4335 assert(!vec.small); 4336 4337 //debug writeln("-----"); 4338 Vector!(Foo, 4) vec2 = move(vec); 4339 assert(counters[].all!(c => c.objects == 1)); 4340 //debug writeln(vec2.length, ", ", vec2.capacity, ", ", vec2.minimalCapacity); 4341 assert(vec2.small); 4342 } 4343 4344 } 4345 4346 4347 //small->large 4348 { 4349 //copy 4350 assert(counters[].all!(c => c.objects == 0)); 4351 { 4352 auto vec = Vector!(Foo, 4).build(iota(0, 3, 1).map!(x => Foo(counters[x]))); 4353 assert(counters[].all!(c => c.objects == 1)); 4354 assert(vec.small); 4355 4356 Vector!(Foo, 2) vec2 = vec; 4357 assert(counters[].all!(c => c.objects == 2)); 4358 assert(!vec2.small); 4359 } 4360 4361 //move 4362 assert(counters[].all!(c => c.objects == 0)); 4363 { 4364 auto vec = Vector!(Foo, 4).build(iota(0, 3, 1).map!(x => Foo(counters[x]))); 4365 assert(counters[].all!(c => c.objects == 1)); 4366 assert(vec.small); 4367 4368 Vector!(Foo, 2) vec2 = move(vec); 4369 assert(counters[].all!(c => c.objects == 1)); 4370 assert(!vec2.small); 4371 } 4372 } 4373 4374 4375 } 4376 4377 //assign: 4378 pure nothrow @safe unittest{ 4379 //TODO 4380 } 4381 4382 4383 //simple rvalue ctor: 4384 pure nothrow @safe @nogc unittest{ 4385 import core.lifetime : move; 4386 { 4387 auto vec = Vector!(int, 4).build(1, 2, 3); 4388 assert(vec.small); 4389 4390 auto vec2 = move(vec); 4391 assert(vec2.small); 4392 4393 4394 //assert(vec2 == [1, 2, 3]); 4395 assert(vec.empty); 4396 4397 } 4398 4399 { 4400 auto vec = Vector!(int, 4).build(1, 2, 3); 4401 assert(vec.small); 4402 4403 Vector!(int, 2) vec2 = move(vec); 4404 assert(!vec2.small); 4405 4406 assert(vec2 == [1, 2, 3]); 4407 assert(vec.empty); 4408 } 4409 4410 { 4411 auto vec = Vector!(int, 2).build(1, 2, 3); 4412 assert(!vec.small); 4413 4414 Vector!(int, 2) vec2 = move(vec); 4415 assert(!vec2.small); 4416 4417 assert(vec2 == [1, 2, 3]); 4418 assert(vec.empty); 4419 } 4420 4421 { 4422 auto vec = Vector!(int, 2).build(1, 2, 3); 4423 assert(!vec.small); 4424 4425 Vector!(int, 4) vec2 = move(vec); 4426 assert(vec2.small); 4427 4428 assert(vec2 == [1, 2, 3]); 4429 assert(vec.empty); 4430 } 4431 } 4432 4433 //simple lvalue ctor: 4434 pure nothrow @safe @nogc unittest{ 4435 import core.lifetime : move; 4436 { 4437 auto vec = Vector!(int, 4).build(1, 2, 3); 4438 auto vec2 = vec; 4439 4440 assert(vec.small && vec2.small); 4441 4442 assert(vec2 == [1, 2, 3]); 4443 assert(vec == [1, 2, 3]); 4444 } 4445 4446 { 4447 auto vec = Vector!(int, 4).build(1, 2, 3); 4448 Vector!(int, 2) vec2 = vec; 4449 4450 assert(vec.small && !vec2.small); 4451 4452 assert(vec2 == [1, 2, 3]); 4453 assert(vec == [1, 2, 3]); 4454 } 4455 4456 { 4457 auto vec = Vector!(int, 2).build(1, 2, 3); 4458 Vector!(int, 2) vec2 = vec; 4459 4460 assert(!vec.small && !vec2.small); 4461 4462 assert(vec2 == [1, 2, 3]); 4463 assert(vec == [1, 2, 3]); 4464 } 4465 4466 { 4467 auto vec = Vector!(int, 2).build(1, 2, 3); 4468 Vector!(int, 4) vec2 = vec; 4469 4470 assert(!vec.small && vec2.small); 4471 4472 assert(vec2 == [1, 2, 3]); 4473 assert(vec == [1, 2, 3]); 4474 } 4475 } 4476 4477 } 4478 4479 //opAssign tests: 4480 version(unittest){ 4481 //TODO 4482 4483 } 4484 4485 4486 //swap tests: 4487 version(unittest){ 4488 4489 pure nothrow @safe @nogc unittest{ 4490 auto small = Vector!(int, 4).build(1, 2); 4491 auto large = Vector!(int, 4).build(10, 20, 30, 40, 50, 60, 70); 4492 4493 assert(small.small == true); 4494 assert(large.small == false); 4495 4496 small.proxySwap(large); 4497 assert(small == [10, 20, 30, 40, 50, 60, 70]); 4498 assert(large == [1, 2]); 4499 4500 4501 assert(small.small == false); 4502 assert(large.small == true); 4503 } 4504 4505 pure nothrow @safe @nogc unittest{ 4506 auto a = Vector!(int, 4).build(1, 2); 4507 auto b = Vector!(int, 4).build(3, 4); 4508 4509 assert(a.small == true); 4510 assert(b.small == true); 4511 4512 a.proxySwap(b); 4513 assert(a == [3, 4]); 4514 assert(b == [1, 2]); 4515 4516 assert(a.small == true); 4517 assert(b.small == true); 4518 } 4519 4520 pure nothrow @safe @nogc unittest{ 4521 auto a = Vector!(int, 4).build(1, 2, 3, 4, 5, 6, 7); 4522 auto b = Vector!(int, 4).build(10, 20, 30, 40, 50, 60, 70); 4523 4524 assert(a.small == false); 4525 assert(b.small == false); 4526 4527 a.proxySwap(b); 4528 assert(a == [10, 20, 30, 40, 50, 60, 70]); 4529 assert(b == [1, 2, 3, 4, 5, 6, 7]); 4530 4531 assert(a.small == false); 4532 assert(b.small == false); 4533 } 4534 4535 4536 } 4537 4538 //version 4539 version(unittest){ 4540 private import btl.internal.test_allocator; 4541 4542 nothrow unittest{ 4543 TestAllocator* allcoator = new TestAllocator; 4544 4545 auto vec = Vector!(int, 2, TestAllocator*)(allcoator); 4546 4547 assert(allcoator.get_count == 0); 4548 4549 vec.append([1, 2, 3, 4, 5, 6]); 4550 assert(allcoator.get_count == 1); 4551 4552 auto vec2 = vec; 4553 assert(allcoator.get_count == 2); 4554 4555 vec.release(); 4556 assert(allcoator.get_count == 1); 4557 4558 vec2.release(); 4559 assert(allcoator.get_count == 0); 4560 } 4561 4562 } 4563 4564 4565 //.md example 4566 pure nothrow @nogc unittest{ 4567 import std.range : only; 4568 import std.algorithm : map, equal; 4569 4570 static struct Foo{ 4571 int i; 4572 string str; 4573 } 4574 4575 Vector!(Foo, 4) vec; 4576 4577 assert(vec.empty); 4578 assert(vec.capacity == 4); 4579 assert(typeof(vec).minimalCapacity == 4); 4580 4581 vec.append(Foo(1, "A")); 4582 assert(vec.length == 1); 4583 4584 vec.append(only(Foo(2, "B"), Foo(3, "C"))); 4585 assert(vec.length == 3); 4586 4587 vec.emplaceBack(4, "D"); 4588 assert(vec.length == 4); 4589 assert(vec.capacity == 4); 4590 4591 vec.insert(1, Foo(5, "E")); 4592 assert(vec.length == 5); 4593 assert(vec.capacity > 4); 4594 assert(equal(vec[].map!(e => e.str), only("A", "E", "B", "C", "D"))); 4595 4596 vec.erase(vec[1 .. $-1]); //same as vec.erase(1, 3); 4597 assert(vec == only(Foo(1, "A"), Foo(4, "D"))); 4598 4599 4600 vec.clear(); 4601 assert(vec.length == 0); 4602 assert(vec.capacity > 4); 4603 4604 vec.release(); 4605 assert(vec.length == 0); 4606 assert(vec.capacity == typeof(vec).minimalCapacity); 4607 4608 vec = Vector!(Foo, 4).build(Foo(-1, "X"), Foo(-2, "Y")); 4609 assert(equal(vec[].map!(e => e.str), only("X", "Y"))); 4610 4611 } 4612 4613 4614 //opIndexAssign 4615 @safe pure nothrow @nogc unittest{ 4616 auto vec = Vector!int.build(1, 2, 3); 4617 4618 vec[0] = -1; 4619 assert(vec == [-1, 2, 3]); 4620 4621 vec[1 .. $] = -2; 4622 assert(vec == [-1, -2, -2]); 4623 4624 vec[0] *= -1; 4625 assert(vec == [1, -2, -2]); 4626 4627 vec[1 .. $] *= -1; 4628 assert(vec == [1, 2, 2]); 4629 } 4630 4631