1 module ut.memory.classes;
2 
3 
4 import ut;
5 import std.experimental.allocator.mallocator: Mallocator;
6 
7 
8 private interface ITransformer {
9     import std.traits: FA = FunctionAttribute;
10 
11     enum CopyConstructorAttrs = FA.safe | FA.pure_;
12     enum DestructorAttrs = FA.pure_ | FA.nogc;
13 
14     int transform(int) @safe @nogc pure const;
15 }
16 
17 private alias Transformer = Polymorphic!(ITransformer, Mallocator);
18 
19 // @system because the copy constructor can't be safe
20 private int xform(in Transformer t, int i) @system @nogc pure {
21     return t.transform(i);
22 }
23 
24 private class Multiplier {
25     int i;
26     this(int i) @safe @nogc pure nothrow inout { this.i = i; }
27     this(const Multiplier other) @safe @nogc pure nothrow inout { this.i = other.i; }
28     int transform(int j) @safe @nogc pure nothrow const { return i * j; }
29     override string toString() @safe pure nothrow const {
30         import std.conv: text;
31         return text(`Multiplier(`, i, `)`);
32     }
33 }
34 
35 private class Thrice {
36     int transform(int i) @safe @nogc pure const { return i * 3; }
37 }
38 
39 
40 @("mallocator.stateful.create")
41 @system pure unittest {
42     const multiplier = Transformer.create!Multiplier(3);
43     xform(multiplier, 2).should == 6;
44     xform(multiplier, 3).should == 9;
45 }
46 
47 
48 @("mallocator.stateful.copy")
49 @system pure unittest {
50     const multiplier = Transformer(new Multiplier(3));
51     xform(multiplier, 2).should == 6;
52     xform(multiplier, 3).should == 9;
53 }
54 
55 
56 @("mallocator.stateless.create")
57 @system pure unittest {
58     const multiplier = Transformer.create!Thrice(3);
59     xform(multiplier, 2).should == 6;
60     xform(multiplier, 3).should == 9;
61 }