1 /// Test value semantics 2 module ut.value; 3 4 5 import unit_threaded; 6 import tardy; 7 8 9 // verify that copying obeys value semantics 10 @("copy") 11 // not pure because the copy constructor isn't (and can't) 12 @safe unittest { 13 import std.algorithm.iteration: map; 14 15 static interface IPrintable { 16 void inc() @safe; 17 string stringify() @safe const; 18 } 19 20 alias Printable = Polymorphic!IPrintable; 21 22 import std.conv: text; 23 static struct Foo { 24 int i; 25 void inc() @safe { ++i; } 26 string stringify() @safe const { return text("Foo(", i, ")"); } 27 } 28 static struct Bar { 29 int i; 30 void inc() @safe { ++i; } 31 string stringify() @safe const { return text("Bar(", i, ")"); } 32 } 33 static struct Baz { 34 int i; 35 void inc() @safe { ++i; } 36 string stringify() @safe const { return text("Baz(", i, ")"); } 37 } 38 39 auto printables = [ 40 Printable(Foo(0)), 41 Printable(Foo(1)), 42 Printable(Bar(2)), 43 Printable(Baz(3)), 44 ]; 45 46 string call(Printable p) { return p.stringify; } 47 auto strings = printables.map!call; 48 () @trusted { 49 strings.should == ["Foo(0)", "Foo(1)", "Bar(2)", "Baz(3)"]; 50 }(); 51 52 auto bar = printables[2]; 53 bar.stringify.should == "Bar(2)"; 54 bar.inc; 55 bar.inc; 56 bar.inc; 57 bar.stringify.should == "Bar(5)"; 58 59 strings = printables.map!call; 60 () @trusted { 61 strings.should == ["Foo(0)", "Foo(1)", "Bar(2)", "Baz(3)"]; 62 }(); 63 } 64 65 66 @("uncopiable") 67 @safe unittest { 68 static interface IPrintable { 69 void inc() @safe; 70 string stringify() @safe const; 71 } 72 73 alias Printable = Polymorphic!IPrintable; 74 75 static struct Foo { 76 @disable this(this); 77 int i; 78 void inc() @safe { ++i; } 79 string stringify() @safe const { import std.conv: text; return text("Foo(", i, ")"); } 80 } 81 82 static assert(!__traits(compiles, Printable(Foo(42)))); 83 auto p = Printable.create!Foo(42); 84 p.stringify.should == "Foo(42)"; 85 p.inc; 86 p.stringify.should == "Foo(43)"; 87 }