[Issue 13872] New: std.container.Array inconsistent/misleading reference semantics for Array.init and make!Array(..)
via Digitalmars-d-bugs
digitalmars-d-bugs at puremagic.com
Wed Dec 17 03:55:02 PST 2014
https://issues.dlang.org/show_bug.cgi?id=13872
Issue ID: 13872
Summary: std.container.Array inconsistent/misleading reference
semantics for Array.init and make!Array(..)
Product: D
Version: D2
Hardware: x86_64
OS: Linux
Status: NEW
Severity: enhancement
Priority: P1
Component: Phobos
Assignee: nobody at puremagic.com
Reporter: tobias at pankrath.net
std.container.Array has reference semantics. Array.init basically is a null
reference, but it's not an error to use it since it will initialize itself
behind your back. However if you assign this reference somewhere it still
behaves like null in the sense that you get two references to two conceptually
distinct Arrays:
---------
void main()
{
import std.container, std.stdio;
{
/// Example 1
writeln("Example 1");
// to create an empty array, you can use Array.init
Array!int array1;
array1.insertBack(0);
// since Array offers reference semantics, you can make use of them
auto refTo1 = array1;
refTo1.insertBack(1);
// so this prints [0, 1], as expected
writeln(array1[]);
}
{
/// Example 2
writeln("\nExample 2");
// however that only works if you triggered array1 to be initialized,
// before assigning to refTo1
// create an empty array
Array!int array1;
// get a second reference to it, before doing anything meaningful
auto refTo1 = array1;
// and fill it now
array1.insertBack(0);
refTo1.insertBack(1);
// does not work as expected
// prints array1: [0]\nrefTo1: [1] instead of
// array1: [0, 1]\nrefTo1: [0, 1]
writefln("array1: %s", array1[]);
writefln("refTo1: %s", refTo1[]);
}
}
---
While I do think that using Array.init should assert, I do recognize that we
probably cannot change this anymore. This should work though if I use
make!Array to construct the arrays, but does not:
---
{
/// Example 1
writeln("Example 1");
// to create an empty array, you could use make as well
Array!int array1 = make!(Array!int);
array1.insertBack(0);
// since Array offers reference semantics, you can make use of them
auto refTo1 = array1;
refTo1.insertBack(1);
// so this prints [0, 1], as expected
writeln(array1[]);
}
{
/// Example 2
writeln("\nExample 2");
// however that only works if you triggered array1 to be initialized,
// before assigning to refTo1
// create an empty array
Array!int array1 = make!(Array!int);
// get a second reference to it, before doing anything meaningful
auto refTo1 = array1;
// and fill it now
array1.insertBack(0);
refTo1.insertBack(1);
// does not work as expected
// prints array1: [0]\nrefTo1: [1] instead of
// array1: [0, 1]\nrefTo1: [0, 1]
writefln("array1: %s", array1[]);
writefln("refTo1: %s", refTo1[]);
}
---
make(Container) should return an empty array, not the equivalent of a null
reference. This is inconsistent to class based containers as well, where make
returns a 'newed' container.
This would be an easy fix to make if we had a consistent way to force a struct
based container to become initialized. Inserting and removing an element is
ugly. In case of std.container.Array we could explicitly set length to 0, but
thats undocumented behaviour.
--
More information about the Digitalmars-d-bugs
mailing list