digitalmars.D.bugs - [Issue 13872] New: std.container.Array inconsistent/misleading
- via Digitalmars-d-bugs (98/98) Dec 17 2014 https://issues.dlang.org/show_bug.cgi?id=13872
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 puremagic.com Reporter: tobias 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. --
Dec 17 2014