Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 58 additions & 24 deletions std/container/util.d
Original file line number Diff line number Diff line change
@@ -1,56 +1,75 @@
/**
This module contains some common utilities used by containers.
This module contains common utilities used by containers.

This module is a submodule of $(MREF std, container).

Source: $(PHOBOSSRC std/container/util.d)

Copyright: 2010- Andrei Alexandrescu. All rights reserved by the respective holders.
Copyright: 2010- Andrei Alexandrescu.

License: Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at $(HTTP
boost.org/LICENSE_1_0.txt)).

Authors: $(HTTP erdani.com, Andrei Alexandrescu)

$(SCRIPT inhibitQuickIndex = 1;)
Authors: Andrei Alexandrescu
Comment on lines +2 to +12
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not include unrelated documentation changes in this PR.

*/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not include unrelated formatting changes in this PR.

module std.container.util;

import std.algorithm.mutation : forward;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import std.algorithm.mutation : forward;
import core.lifetime : forward;

The fact that this import is incorrect suggests that you did not even attempt to compile or test this change on your own device before submitting a PR. Please do so in the future; it will save both you and us a lot of time.


/**
Returns an initialized object. This function is mainly for eliminating
construction differences between structs and classes. It allows code to not
worry about whether the type it's constructing is a struct or a class.
*/
Creates and returns an initialized instance of type `T`.

This utility abstracts the difference between constructing
structs and classes.

Structs are constructed using:
---
T(args)
---

Classes are constructed using:
---
new T(args)
---

This allows generic container code to construct objects
without worrying about whether `T` is a struct or class.
*/
Comment on lines +20 to +37
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not include unrelated documentation changes in this PR.

template make(T)
if (is(T == struct) || is(T == class))
{
T make(Args...)(Args arguments)
if (is(T == struct) && __traits(compiles, T(arguments)))
@safe T make(Args...)(Args arguments)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make is a template function, which means that attributes like @safe are inferred automatically by the compiler. It should not be necessary to add an explicit @safe attribute here.

If there is something in the function body that prevents @safe from being inferred when it ought to be, the body should be changed to make that inference possible.

if (is(T == struct))
{
// constructing an std.container.Array without arguments,
static assert(__traits(compiles, T(arguments)),
"Cannot construct "~T.stringof~" with given arguments");

// constructing an std.container.Array without arguments
// does not initialize its payload and is equivalent
// to a null reference. We therefore construct an empty container
// by passing an empty array to its constructor.
// https://issues.dlang.org/show_bug.cgi?id=13872.
static if (arguments.length == 0)
{
import std.range.primitives : ElementType;
alias ET = ElementType!(T.Range);
return T(ET[].init);
}
else
return T(arguments);
{
return T(forward!arguments);
}
}

T make(Args...)(Args arguments)
if (is(T == class) && __traits(compiles, new T(arguments)))
@safe T make(Args...)(Args arguments)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above re: inference of @safe.

if (is(T == class))
{
return new T(arguments);
static assert(__traits(compiles, new T(arguments)),
"Cannot construct "~T.stringof~" with given arguments");

return new T(forward!arguments);
}
}


///
@system unittest
{
Expand All @@ -75,11 +94,13 @@ if (is(T == struct) || is(T == class))

auto arr1 = make!(Array!dchar)();
assert(arr1.empty);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not include unrelated formatting changes in this PR.

auto arr2 = make!(Array!dchar)("hello"d);
assert(equal(arr2[], "hello"d));

auto rtb1 = make!(RedBlackTree!dchar)();
assert(rtb1.empty);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not include unrelated formatting changes in this PR.

auto rtb2 = make!(RedBlackTree!dchar)('h', 'e', 'l', 'l', 'o');
assert(equal(rtb2[], "ehlo"d));
}
Expand All @@ -94,14 +115,15 @@ if (is(T == struct) || is(T == class))
auto b = make!(DList!int)(1,2,3,4);
auto c = make!(DList!int)(1,2,3,5);
auto d = make!(DList!int)(1,2,3,4,5);
assert(a == b); // this better terminate!

assert(a == b);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not include unrelated formatting changes in this PR.

assert(a != c);
assert(a != d);
}

/**
* Convenience function for constructing a generic container.
*/
Convenience function for constructing a generic container.
*/
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not include unrelated formatting changes in this PR.

template make(alias Container, Args...)
if (!is(Container))
{
Expand All @@ -127,7 +149,7 @@ if (!is(Container))
{
import std.container.array : Array;
import std.range : only, repeat;
import std.range.primitives : isInfinite;

static assert(__traits(compiles, { auto arr = make!Array(only(5)); }));
static assert(!__traits(compiles, { auto arr = make!Array(repeat(5)); }));
}
Expand Down Expand Up @@ -187,3 +209,15 @@ if (!is(Container))
refToDList.insert(1);
assert(!dlist.empty);
}

/// Additional edge case tests
@safe unittest
{
import std.container.array;

auto arr = make!(Array!int)();
assert(arr.empty);

auto arr2 = make!(Array!int)(1);
assert(arr2.front == 1);
}