├── typedef.pdf ├── utils ├── unionsyntax.d ├── enumsyntax.d ├── isanytype.d ├── crtp.d ├── using_record.d ├── usingmystruct2.d ├── interfacesyntax.d ├── member.d ├── nameof3.d ├── allmemberstemplate.d ├── scopename.d ├── anonymous_error.d ├── functionarity.d ├── maxtemplate.d ├── storage.d ├── acceptingtuple.d ├── isastringliteral.d ├── ndim.d ├── using_ndim.d ├── using_tree.d ├── forwarder.d ├── usingfields.d ├── templatedconstructors.d ├── isdynamicarray.d ├── classsyntax1.d ├── pair.d ├── transp.d ├── variant_error.d ├── allarrays.d ├── constraints_error.d ├── allmemberstemplate2.d ├── overloads1.d ├── emptytuple.d ├── istype.d ├── usingBasicTree1.d ├── using_calltwice.d ├── anonymous_function1.d ├── enumdefasstring.d ├── intro.d ├── ctvalue.d ├── mixinconcatenate.d ├── tree1.d ├── cclass.d ├── classsyntax2.d ├── nmap.d ├── sortingtypes.d ├── usingtuple.d ├── usingmixinconcatenate.d ├── usingunique.d ├── calltwice.d ├── differentinstantiations.d ├── extendenum.d ├── parametrizedbaseclass.d ├── gobbler.d ├── usinggobbler.d ├── usingmax.d ├── nfilter.d ├── record.d ├── classinvariant.d ├── nameof.d ├── staticmap.d ├── deduced.d ├── filelinetagging.d ├── rank1.d ├── heap1.d ├── inoutclauses.d ├── istuple.d ├── mystruct3.d ├── holder.d ├── nameof2.d ├── flatten1.d ├── morph.d ├── ttflatten.d ├── usingstaticfilter1.d ├── function_declaration1.d ├── constraintsyntax.d ├── internaldeclarations2.d ├── usingqualifiedname.d ├── nameof1.d ├── basicTree1.d ├── checkedinheritance.d ├── mystruct1.d ├── genericTree.d ├── getset2.d ├── tree3.d ├── parent.d ├── allmembers.d ├── selector.d ├── namedtuple.d ├── heap2.d ├── isserializable.d ├── usingnotify.d ├── tree2.d ├── usingmystruct1.d ├── ifti.d ├── isbuiltintype.d ├── using_flatten1.d ├── using_rank1.d ├── usingoverloads1.d ├── canbeinstantiated.d ├── mystruct2.d ├── def.d ├── areallranges.d ├── flatten2.d ├── init.d ├── staticfilter.d ├── transp2.d ├── nmap2.d ├── specialization1.d ├── using_makecounter.d ├── dropfront.d ├── templateintrospection.d ├── templatedinner.d ├── checkedwrite.d ├── classsyntax3.d ├── serializetemplate.d ├── flatten4.d ├── tester.d ├── maponalias.d ├── qualifiedname.d ├── repeatedcomposition.d ├── usingcheckedwrite.d ├── usingstaticfilter2.d ├── rank2.d ├── baseelementtype.d ├── checkcompatibility.d ├── makemember.d ├── usingnamedtuple.d ├── allmembersmodule.d ├── rangewrapper.d ├── usingmemoize1.d ├── number.d ├── variadic.d ├── specialization2.d ├── function_declaration2.d ├── staticscan.d ├── debugger.d ├── innerconcatenate.d ├── internaldeclarations1.d ├── usingscopename.d ├── buildsortingcode.d ├── noduplicates.d ├── tupledemonstration.d ├── inordertree.d ├── networksort.d ├── staticreduce.d ├── popallfronts.d ├── anonymous_function2.d ├── summingtree.d ├── maptuple.d ├── myclass.d ├── constrained.d ├── descriptor.d ├── usingallmembers2.d ├── compare.d ├── interfacelist.d ├── tree4.d ├── dispatcher.d ├── usingtransparent.d ├── juxtapose.d ├── usingallmembers1.d ├── eliminate.d ├── basicTree2.d ├── anonymousclass.d ├── makecounter.d ├── flatten3.d ├── usingfriends.d ├── superlist.d ├── fieldsof.d ├── usingrelational.d ├── interleave.d ├── memoize1.d ├── validcall.d ├── tree5.d ├── maker.d ├── staticswitch.d ├── half.d ├── using_power.d ├── hasarithmeticoperations.d ├── sortingnetwork.d ├── ttiteration.d ├── using_tree4.d ├── fields.d ├── stringinterpolation.d ├── qualified.d ├── notify.d ├── implements.d ├── declaration.d ├── librarytypedef.d ├── overloads2.d ├── curry.d ├── juxtaposehelper.d ├── sorttypes.d ├── verifychecks.d ├── memoize3.d ├── alist.d ├── instantiation.d ├── getset3.d ├── getset.d ├── using_flatten4.d ├── filtertuple.d ├── annotation.d ├── publisher.d ├── inheritanceexample.d ├── getformatters.d ├── memoize2.d ├── friends.d ├── relational.d ├── codesamples.d └── results.txt ├── .gitignore ├── D-templates-tutorial.epub ├── D-templates-tutorial.pdf ├── README.md └── TODO.md /typedef.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PhilippeSigaud/D-templates-tutorial/HEAD/typedef.pdf -------------------------------------------------------------------------------- /utils/unionsyntax.d: -------------------------------------------------------------------------------- 1 | module unionsyntax; 2 | 3 | union Union(A,B,C) { A a; B b; C c;} 4 | -------------------------------------------------------------------------------- /utils/enumsyntax.d: -------------------------------------------------------------------------------- 1 | module enumsyntax; 2 | 3 | template Enum(T) 4 | { 5 | enum Enum : T { A, B, C} 6 | } 7 | -------------------------------------------------------------------------------- /utils/isanytype.d: -------------------------------------------------------------------------------- 1 | module isanytype; 2 | 3 | template isAnyType(T) 4 | { 5 | enum isAnyType = true; 6 | } 7 | -------------------------------------------------------------------------------- /utils/crtp.d: -------------------------------------------------------------------------------- 1 | module crtp; 2 | 3 | class Base(Child) { /*...*/ } 4 | 5 | class Derived : Base!Derived { /*...*/ } 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .directory 2 | *.aux 3 | *.log 4 | *.gz 5 | *.idx 6 | *.out 7 | *.toc 8 | *.ind 9 | *.ilg 10 | *~ 11 | -------------------------------------------------------------------------------- /D-templates-tutorial.epub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PhilippeSigaud/D-templates-tutorial/HEAD/D-templates-tutorial.epub -------------------------------------------------------------------------------- /D-templates-tutorial.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PhilippeSigaud/D-templates-tutorial/HEAD/D-templates-tutorial.pdf -------------------------------------------------------------------------------- /utils/using_record.d: -------------------------------------------------------------------------------- 1 | module using_record; 2 | import record; 3 | 4 | Record!(int,string,double[]) recordslist; 5 | /* ... */ 6 | -------------------------------------------------------------------------------- /utils/usingmystruct2.d: -------------------------------------------------------------------------------- 1 | module usingmystruct2; 2 | import mystruct2; 3 | 4 | MyStruct!"First" f1, f2; 5 | MyStruct!"Second" s1; 6 | -------------------------------------------------------------------------------- /utils/interfacesyntax.d: -------------------------------------------------------------------------------- 1 | module interfacesyntax; 2 | 3 | interface Interf(T) 4 | { 5 | T foo(T); 6 | T[] bar(T,int); 7 | } 8 | -------------------------------------------------------------------------------- /utils/member.d: -------------------------------------------------------------------------------- 1 | module member; 2 | 3 | struct Member(string n, T) 4 | { 5 | enum name = n; // for external access 6 | alias T Type; 7 | } 8 | -------------------------------------------------------------------------------- /utils/nameof3.d: -------------------------------------------------------------------------------- 1 | module nameof3; 2 | 3 | template nameOf(T...) if (T.length == 1) // restricted to one argument 4 | { 5 | enum string nameOf = T[0].stringof; 6 | } 7 | -------------------------------------------------------------------------------- /utils/allmemberstemplate.d: -------------------------------------------------------------------------------- 1 | module allmemberstemplate; 2 | 3 | class MyClass(T) 4 | { 5 | T field; 6 | } 7 | 8 | static assert([__traits(allMembers, MyClass)] == ["MyClass"]); 9 | -------------------------------------------------------------------------------- /utils/scopename.d: -------------------------------------------------------------------------------- 1 | module scopename; 2 | public import qualifiedname; 3 | 4 | mixin template getScopeName() 5 | { 6 | enum scopeName = qualifiedName!(__traits(parent, scopeName)); 7 | } 8 | -------------------------------------------------------------------------------- /utils/anonymous_error.d: -------------------------------------------------------------------------------- 1 | module anonymous_error; 2 | 3 | auto concatenate(A)(A a) 4 | { 5 | /* !! Not legal D code !! */ 6 | return (B)(B b) { return to!string(a) ~ to!string(b);}; 7 | } 8 | -------------------------------------------------------------------------------- /utils/functionarity.d: -------------------------------------------------------------------------------- 1 | module functionarity; 2 | import std.traits; 3 | 4 | template arity(alias fun) 5 | if (isFunction!fun) 6 | { 7 | enum size_t arity = ParameterTypeTuple!(fun).length; 8 | } 9 | -------------------------------------------------------------------------------- /utils/maxtemplate.d: -------------------------------------------------------------------------------- 1 | module maxtemplate; 2 | 3 | template Max(T1, T2) 4 | { 5 | static if (T1.sizeof >= T2.sizeof) 6 | alias T1 Max; 7 | else 8 | alias T2 Max; 9 | } 10 | -------------------------------------------------------------------------------- /utils/storage.d: -------------------------------------------------------------------------------- 1 | module storage; 2 | 3 | void init(T)(ref T t) 4 | { 5 | t = T.init; 6 | } 7 | 8 | unittest 9 | { 10 | int i = 10; 11 | init(i); 12 | assert(i == 0); 13 | } 14 | -------------------------------------------------------------------------------- /utils/acceptingtuple.d: -------------------------------------------------------------------------------- 1 | module acceptingtuple; 2 | 3 | template tuplify(alias fun) 4 | { 5 | auto tuplify(T...)(Tuple!T tup) 6 | { 7 | return fun(tup.expand); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /utils/isastringliteral.d: -------------------------------------------------------------------------------- 1 | module isastringliteral; 2 | import std.traits: isSomeString; 3 | 4 | template isAStringLiteral(alias name) 5 | { 6 | enum isAStringLiteral = isSomeString!(typeof(name)); 7 | } 8 | -------------------------------------------------------------------------------- /utils/ndim.d: -------------------------------------------------------------------------------- 1 | module ndim; 2 | 3 | template NDimArray(T, size_t r) 4 | { 5 | static if (r == 0) 6 | alias T NDimArray; 7 | else 8 | alias NDimArray!(T, r-1)[] NDimArray; 9 | } 10 | -------------------------------------------------------------------------------- /utils/using_ndim.d: -------------------------------------------------------------------------------- 1 | module using_ndim; 2 | import ndim; 3 | 4 | alias NDimArray!(double, 8) Level8; 5 | static assert(is(Level8 == double[][][][][][][][])); 6 | static assert(is(NDimArray!(double, 0) == double)); 7 | -------------------------------------------------------------------------------- /utils/using_tree.d: -------------------------------------------------------------------------------- 1 | module using_tree; 2 | import tree1; 3 | 4 | void main() 5 | { 6 | auto t0 = Tree!int(0); 7 | auto t1 = Tree!int(1, [t0,t0]); 8 | Tree!int[] children = t1.children; 9 | } 10 | -------------------------------------------------------------------------------- /utils/forwarder.d: -------------------------------------------------------------------------------- 1 | module forwarder; 2 | 3 | mixin template Forwarder() 4 | { 5 | auto opDispatch(string name, Args...)(Args args) 6 | { 7 | mixin("return " ~ name ~ "(args);"); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /utils/usingfields.d: -------------------------------------------------------------------------------- 1 | module usingfields; 2 | import fields; 3 | 4 | struct Point { 5 | mixin Fields!(int, "x", "y", "z", "w"); 6 | } 7 | 8 | struct Size { 9 | mixin Fields!(int, "width", "height"); 10 | } 11 | -------------------------------------------------------------------------------- /utils/templatedconstructors.d: -------------------------------------------------------------------------------- 1 | module templatedconstructors; 2 | 3 | struct S(T) 4 | { 5 | this(U)(U u) { /*...*/ } 6 | } 7 | 8 | void main() 9 | { 10 | auto s = S!string(1); // T is string, U is int. 11 | } 12 | -------------------------------------------------------------------------------- /utils/isdynamicarray.d: -------------------------------------------------------------------------------- 1 | module isdynamicarray; 2 | 3 | template isDynamicArray(T) 4 | { 5 | static if (is(T t == U[], U)) 6 | enum isDynamicArray = true; 7 | else 8 | enum isDynamicArray = false; 9 | } 10 | -------------------------------------------------------------------------------- /utils/classsyntax1.d: -------------------------------------------------------------------------------- 1 | module classsyntax1; 2 | 3 | class Base {} 4 | interface Interface1 {} 5 | interface Interface2 {} 6 | 7 | class MyClass(Type, alias fun, bool b = false) 8 | : Base, Interface1, Interface2 9 | { /*...*/ } 10 | -------------------------------------------------------------------------------- /utils/pair.d: -------------------------------------------------------------------------------- 1 | module pair; 2 | 3 | template pair(T) 4 | { 5 | // template 'pair' declares only a 'pair' member 6 | T[] pair(T t) { return [t,t];} 7 | } 8 | 9 | auto array = pair!(int)(1); // no need to do pair!(int).pair(1) 10 | -------------------------------------------------------------------------------- /utils/transp.d: -------------------------------------------------------------------------------- 1 | module transp; 2 | 3 | struct Transparent(T) 4 | { 5 | T value; 6 | alias value this; 7 | } 8 | 9 | // factory function 10 | Transparent!T transparent(T)(T t) 11 | { 12 | return Transparent!T(t); 13 | } 14 | -------------------------------------------------------------------------------- /utils/variant_error.d: -------------------------------------------------------------------------------- 1 | module variant_error; 2 | import std.variant; 3 | 4 | void main() 5 | { 6 | Algebraic!(int, double, string) algOne; 7 | algOne = 1; 8 | Algebraic!(double, int, string) algTwo = algOne; // fail! 9 | } 10 | -------------------------------------------------------------------------------- /utils/allarrays.d: -------------------------------------------------------------------------------- 1 | module allarrays; 2 | 3 | template AllArraysOf(T) 4 | { 5 | alias T Element; 6 | alias T* PointerTo; 7 | alias T[] DynamicArray; 8 | alias T[1] StaticArray; 9 | alias T[T] AssociativeArray; 10 | } 11 | -------------------------------------------------------------------------------- /utils/constraints_error.d: -------------------------------------------------------------------------------- 1 | module constraints_error; 2 | 3 | template Temp(T) 4 | if (is(T:int)) // #1, specialized for ints 5 | { /*...*/ } 6 | 7 | template Temp(T) // #2, generic case 8 | { /*...*/ } 9 | 10 | alias Temp!int TI;// Error! 11 | -------------------------------------------------------------------------------- /utils/allmemberstemplate2.d: -------------------------------------------------------------------------------- 1 | module allmemberstemplate2; 2 | import allmemberstemplate; 3 | 4 | static assert([__traits(allMembers, MyClass!int)] 5 | == ["field", "toString", "toHash", "opCmp", 6 | "opEquals", "Monitor", "factory"]); 7 | -------------------------------------------------------------------------------- /utils/overloads1.d: -------------------------------------------------------------------------------- 1 | module overloads1; 2 | import std.typetuple; 3 | import makemember; 4 | 5 | template Overloads(alias a, string member) 6 | { 7 | alias staticMap!(MakeMember, __traits(getOverloads,a, member)) 8 | Overloads; 9 | } 10 | -------------------------------------------------------------------------------- /utils/emptytuple.d: -------------------------------------------------------------------------------- 1 | module emptytuple; 2 | import std.typetuple; 3 | 4 | alias TypeTuple!(void) Void; 5 | alias TypeTuple!() Empty; 6 | static assert( !is(Void == Empty) ); 7 | 8 | static assert(!is( TypeTuple!(int, void, string) == TypeTuple!(int, string))); 9 | -------------------------------------------------------------------------------- /utils/istype.d: -------------------------------------------------------------------------------- 1 | module istype; 2 | 3 | template isType(T) 4 | { 5 | enum isType = true; 6 | } 7 | 8 | template isType(alias a) 9 | { 10 | static if (is(a)) 11 | enum isType = true; 12 | else 13 | enum isType = false; 14 | } 15 | -------------------------------------------------------------------------------- /utils/usingBasicTree1.d: -------------------------------------------------------------------------------- 1 | module usingBasicTree1; 2 | 3 | import basicTree1; 4 | 5 | void main() 6 | { 7 | auto tree = Tree(0, [Tree(1), Tree(2, [Tree(3), Tree(4), Tree(5)])]); 8 | assert(!tree.isLeaf); 9 | assert(tree.size() == 6); 10 | } 11 | -------------------------------------------------------------------------------- /utils/using_calltwice.d: -------------------------------------------------------------------------------- 1 | module using_calltwice; 2 | import calltwice; 3 | 4 | unittest 5 | { 6 | enum b = 3; // Manifest constant, initialized to 3 7 | alias callTwice!( (a){ return a+b;}) addTwoB; 8 | assert(addTwoB(2) == 2 + 3 + 3); 9 | } 10 | -------------------------------------------------------------------------------- /utils/anonymous_function1.d: -------------------------------------------------------------------------------- 1 | module anonymous_function1; 2 | 3 | auto adder(int a) 4 | { 5 | return (int b) { return a+b;}; 6 | } 7 | 8 | unittest 9 | { 10 | auto add1 = adder(1); // add1 is an int delegate(int) 11 | assert(add1(2) == 3); 12 | } 13 | -------------------------------------------------------------------------------- /utils/enumdefasstring.d: -------------------------------------------------------------------------------- 1 | module enumdefasstring; 2 | 3 | string EnumDefAsString(T)() 4 | if (is(T == enum)) 5 | { 6 | string result = ""; 7 | foreach (e; __traits(allMembers, T)) 8 | result ~= e ~ " = T." ~ e ~ ","; 9 | return result; 10 | } 11 | -------------------------------------------------------------------------------- /utils/intro.d: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a doc comment. 3 | */ 4 | module intro; 5 | 6 | import std.stdio; 7 | 8 | void main() 9 | { 10 | int times = 10; 11 | // This is a comment 12 | foreach(i; 0..times) 13 | writeln("Hello, Word!"); 14 | } 15 | -------------------------------------------------------------------------------- /utils/ctvalue.d: -------------------------------------------------------------------------------- 1 | module ctvalue; 2 | 3 | auto callTwice(alias fun, T)(T arg) 4 | // Is it OK to do fun(fun(some T))? 5 | if (is(typeof({ 6 | fun(fun(T.init)); 7 | }()))) 8 | { 9 | return fun(fun(arg)); 10 | } 11 | -------------------------------------------------------------------------------- /utils/mixinconcatenate.d: -------------------------------------------------------------------------------- 1 | module mixinconcatenate; 2 | import std.typecons; 3 | 4 | mixin template Concatenate() 5 | { 6 | Tuple!(typeof(this), U) opBinary(string op, U)(U u) 7 | if (op == "~") 8 | { 9 | return tuple(this, u); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /utils/tree1.d: -------------------------------------------------------------------------------- 1 | module tree1; 2 | import std.array; 3 | 4 | struct Tree(T) 5 | { 6 | T value; 7 | Tree[] children; 8 | 9 | bool isLeaf() @property { return children.empty;} 10 | /* More tree functions: adding children, removing some,... */ 11 | } 12 | -------------------------------------------------------------------------------- /utils/cclass.d: -------------------------------------------------------------------------------- 1 | module cclass; 2 | import nameof; 3 | 4 | class C 5 | { 6 | int i; 7 | int foo(int j) 8 | { 9 | int k; // k is "cclass.C.foo.k" 10 | assert(nameOf!(__traits(parent, k)) == "foo"); 11 | return i+k; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /utils/classsyntax2.d: -------------------------------------------------------------------------------- 1 | module classsyntax2; 2 | 3 | class Base(T) {} 4 | interface Interface1 {} 5 | interface Interface2(alias fun, bool b) {} 6 | 7 | class MyClass(Type, alias fun, bool b = false) 8 | : Base!(Type), Interface1, Interface2!(fun,b) 9 | { /*...*/ } 10 | -------------------------------------------------------------------------------- /utils/nmap.d: -------------------------------------------------------------------------------- 1 | module nmap; 2 | import std.algorithm; 3 | import std.typetuple: allSatisfy; 4 | import acceptingtuple; 5 | 6 | // Very easy to do, now: 7 | auto nmap(alias fun, R...)(R ranges) if (allSatisfy!(isInputRange,R)) 8 | { 9 | return map!(tuplify!fun)(zip(ranges)); 10 | } 11 | -------------------------------------------------------------------------------- /utils/sortingtypes.d: -------------------------------------------------------------------------------- 1 | module sortingtypes; 2 | import std.typetuple; 3 | import sorttypes; 4 | 5 | alias TypeTuple!(int, bool, string function(int), float[]) Types1; 6 | alias TypeTuple!(int, float[], string function(int), bool) Types2; 7 | 8 | static assert(is(Sort!Types1 == Sort!Types2)); 9 | -------------------------------------------------------------------------------- /utils/usingtuple.d: -------------------------------------------------------------------------------- 1 | module usingtuple; 2 | import std.typecons; 3 | 4 | void main() 5 | { 6 | // tuple1 is a Tuple!(int,double,string) 7 | auto tuple1 = tuple(1, 3.14159, "abc"); 8 | // tuple2 is a Tuple!(char,char,char) 9 | auto tuple2 = tuple('a','b','c'); 10 | } 11 | -------------------------------------------------------------------------------- /utils/usingmixinconcatenate.d: -------------------------------------------------------------------------------- 1 | module usingmixinconcatenate; 2 | import std.typecons; 3 | import mixinconcatenate; 4 | 5 | struct S 6 | { 7 | mixin Concatenate; 8 | } 9 | 10 | unittest 11 | { 12 | S s,t; 13 | auto result = s ~ t; 14 | assert(result == tuple(s,t)); 15 | } 16 | -------------------------------------------------------------------------------- /utils/usingunique.d: -------------------------------------------------------------------------------- 1 | module usingunique; 2 | import filelinetagging; 3 | 4 | void main() 5 | { 6 | auto u = unique(1); // Unique!(int, "thefile.d", 4) 7 | 8 | auto v = unique(1); // Unique!(int, "thefile.d", 6) 9 | 10 | static assert(!is( typeof(v) == typeof(u) )); 11 | } 12 | -------------------------------------------------------------------------------- /utils/calltwice.d: -------------------------------------------------------------------------------- 1 | module calltwice; 2 | 3 | template callTwice(alias fun) 4 | { 5 | auto callTwice(T)(T t) 6 | { 7 | return fun(fun(t)); 8 | } 9 | } 10 | 11 | unittest 12 | { 13 | alias callTwice!( (a){ return a+1;}) addTwo; 14 | assert(addTwo(2) == 4); 15 | } 16 | -------------------------------------------------------------------------------- /utils/differentinstantiations.d: -------------------------------------------------------------------------------- 1 | module differentinstantiations; 2 | import declaration; 3 | 4 | alias StoD = Transformer!(string,double); 5 | alias DtoS = Transformer!(double,string); 6 | alias StoI = Transformer!(string,int); 7 | // Now we can use three different functions and three different classes. 8 | -------------------------------------------------------------------------------- /utils/extendenum.d: -------------------------------------------------------------------------------- 1 | module extendenum; 2 | import enumdefasstring; 3 | 4 | template ExtendEnum(T, string s) 5 | if (is(T == enum) && 6 | is(typeof({mixin("enum a{"~s~"}");}))) 7 | { 8 | mixin( 9 | "enum ExtendEnum {" 10 | ~ EnumDefAsString!T() 11 | ~ s 12 | ~ "}"); 13 | } 14 | -------------------------------------------------------------------------------- /utils/parametrizedbaseclass.d: -------------------------------------------------------------------------------- 1 | module parametrizedbaseclass; 2 | 3 | interface ISerializable 4 | { 5 | size_t serialize() @property; 6 | } 7 | 8 | class Serializable(T) : T, ISerializable 9 | { 10 | size_t serialize() @property 11 | { 12 | return this.tohash; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /utils/gobbler.d: -------------------------------------------------------------------------------- 1 | module gobbler; 2 | 3 | struct Gobbler(T...) 4 | { 5 | alias T Types; 6 | T store; 7 | Gobbler!(T, U) opBinary(string op, U)(U u) if (op == "~") 8 | { 9 | return Gobbler!(T, U)(store, u); 10 | } 11 | } 12 | 13 | Gobbler!() gobble() { return Gobbler!()();} 14 | -------------------------------------------------------------------------------- /utils/usinggobbler.d: -------------------------------------------------------------------------------- 1 | module usinggobbler; 2 | import std.typetuple; 3 | import gobbler; 4 | 5 | void main() 6 | { 7 | auto list = gobble ~ 1 ~ "abc" ~ 3.14 ~ "another string!"; 8 | assert(is(list.Types == TypeTuple!(int, string, double, string))); 9 | assert(list.store[2] == 3.14); 10 | } 11 | -------------------------------------------------------------------------------- /utils/usingmax.d: -------------------------------------------------------------------------------- 1 | module usingmax; 2 | import std.typetuple; 3 | import maxtemplate; 4 | import staticreduce; 5 | 6 | alias TypeTuple!(int, bool, double, float delegate(float), string[]) Types; 7 | 8 | alias staticReduce!(Max, Types) MaxType; 9 | static assert(is(MaxType == float delegate(float))); 10 | -------------------------------------------------------------------------------- /utils/nfilter.d: -------------------------------------------------------------------------------- 1 | module nfilter; 2 | import std.algorithm; 3 | import std.range; 4 | import std.typetuple : allSatisfy; 5 | 6 | import acceptingtuple; // tuplify 7 | 8 | auto nfilter(alias fun, R...)(R ranges) if (allSatisfy!(isInputRange, R)) 9 | { 10 | return filter!(tuplify!fun)(zip(ranges)); 11 | } 12 | -------------------------------------------------------------------------------- /utils/record.d: -------------------------------------------------------------------------------- 1 | module record; 2 | 3 | template Record(T, U, V) 4 | { 5 | import std.typecons: Tuple, tuple; 6 | 7 | // The real work is done here 8 | // Use as many symbols as you need. 9 | alias Tuple!(T,U) Pair; 10 | alias Pair[V] AssocArray; 11 | alias AssocArray[] Record; 12 | } 13 | -------------------------------------------------------------------------------- /utils/classinvariant.d: -------------------------------------------------------------------------------- 1 | module classinvariant; 2 | 3 | class MyClass(T, U, V) 4 | { 5 | /*...*/ 6 | 7 | invariant () 8 | { 9 | static if (is(T == U)) 10 | { 11 | /* invariant code */ 12 | } 13 | else 14 | { } /* empty invariant */ 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /utils/nameof.d: -------------------------------------------------------------------------------- 1 | module nameof; 2 | 3 | template nameOf(alias a) 4 | { 5 | enum string nameOf = __traits(identifier, a); 6 | } 7 | 8 | unittest 9 | { 10 | int foo(int i, int j) { return i+j;} 11 | enum name = nameOf!foo; // name is available at compile-time 12 | 13 | assert(name == "foo"); 14 | } 15 | -------------------------------------------------------------------------------- /utils/staticmap.d: -------------------------------------------------------------------------------- 1 | module staticmap; 2 | import std.typetuple; 3 | 4 | template staticMap(alias M, T...) 5 | { 6 | static if (T.length == 0) // End of sequence 7 | alias TypeTuple!() staticMap; // stop there 8 | else 9 | alias TypeTuple!(M!(T[0]), staticMap!(M, T[1..$])) staticMap; 10 | } 11 | -------------------------------------------------------------------------------- /utils/deduced.d: -------------------------------------------------------------------------------- 1 | module deduced; 2 | import std.typecons: Tuple; 3 | 4 | template Deduced(T : U[], V = T, U) 5 | { 6 | alias Tuple!(T,U,V) Deduced; 7 | } 8 | 9 | alias Deduced!(int[], double) D1; // U deduced to be int. Force V to be a double. 10 | alias Deduced!(int[]) D2; // U deduced to be int. V is int, too. 11 | -------------------------------------------------------------------------------- /utils/filelinetagging.d: -------------------------------------------------------------------------------- 1 | module filelinetagging; 2 | 3 | struct Unique(T, string file, size_t line) 4 | { 5 | enum size_t l = line; 6 | enum string f = file; 7 | T t; 8 | } 9 | 10 | auto unique(T, string file = __FILE__, size_t line = __LINE__)(T t) 11 | { 12 | return Unique!(T, file, line)(t); 13 | } 14 | -------------------------------------------------------------------------------- /utils/rank1.d: -------------------------------------------------------------------------------- 1 | module rank1; 2 | 3 | template rank(T) 4 | { 5 | static if (is(T t == U[], U)) // is T an array of U, for some type U? 6 | enum size_t rank = 1 + rank!(U); // then let's recurse down. 7 | else 8 | enum size_t rank = 0; // Base case, ending the recursion. 9 | } 10 | -------------------------------------------------------------------------------- /utils/heap1.d: -------------------------------------------------------------------------------- 1 | module heap1; 2 | 3 | bool lessThan(T)(T a, T b) { return a 0); 10 | } 11 | body 12 | { 13 | return sqrt(n); 14 | } 15 | -------------------------------------------------------------------------------- /utils/istuple.d: -------------------------------------------------------------------------------- 1 | module istuple; 2 | import std.typecons; 3 | 4 | template isTuple(T) 5 | { 6 | enum bool isTuple = 7 | is(typeof({ 8 | void tupleTester(InnerTypes...)(Tuple!(InnerTypes) tup) {} 9 | T.init possibleTuple; 10 | tupleTester(possibleTuple); 11 | }())); 12 | } 13 | -------------------------------------------------------------------------------- /utils/mystruct3.d: -------------------------------------------------------------------------------- 1 | module mystruct3; 2 | 3 | template MyStruct(string name) 4 | { 5 | alias MyStructImpl!(name).result MyStruct; 6 | } 7 | 8 | template MyStructImpl(string name) 9 | { 10 | mixin("struct " ~ name 11 | ~ " {" 12 | ~ "/* some code */" 13 | ~ " }\n" 14 | ~ "alias " ~ name ~ " result;"); 15 | } 16 | -------------------------------------------------------------------------------- /utils/holder.d: -------------------------------------------------------------------------------- 1 | module holder; 2 | import std.conv; 3 | 4 | struct Holder(Type) 5 | { 6 | Type value; 7 | 8 | this(AnotherType)(AnotherType _value) 9 | { 10 | value = to!Type(_value); 11 | } 12 | } 13 | 14 | void main() 15 | { 16 | Holder!int h = Holder!int(3.14); 17 | assert(h.value == 3); 18 | } 19 | -------------------------------------------------------------------------------- /utils/nameof2.d: -------------------------------------------------------------------------------- 1 | module nameof2; 2 | 3 | template nameOf(T) 4 | { 5 | enum string nameOf = T.stringof; 6 | } 7 | 8 | template nameOf(alias a) 9 | { 10 | enum string nameOf = a.stringof; 11 | } 12 | 13 | unittest 14 | { 15 | assert(nameOf!(double[]) == "double[]"); 16 | 17 | int i; 18 | assert(nameOf!(i) == "i"); 19 | } 20 | -------------------------------------------------------------------------------- /utils/flatten1.d: -------------------------------------------------------------------------------- 1 | module flatten1; 2 | import std.algorithm; 3 | import rank2; 4 | 5 | auto flatten(Arr)(Arr array) 6 | { 7 | static if (rank!Arr <= 1) 8 | return array; 9 | else 10 | { 11 | auto children = map!(.flatten)(array); 12 | return reduce!"a~b"(children); // concatenate the children 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /utils/morph.d: -------------------------------------------------------------------------------- 1 | module morph; 2 | 3 | // What morph will return will heavily depend on T and U 4 | auto morph(alias f, T, U)(U arg) 5 | { 6 | static if (is(T == class)) 7 | return new T(f(arg)); 8 | else static if (is(T == struct)) 9 | return T(f(arg)); 10 | else 11 | return; // void-returning function. 12 | } 13 | -------------------------------------------------------------------------------- /utils/ttflatten.d: -------------------------------------------------------------------------------- 1 | module ttflatten; 2 | import std.typetuple; 3 | 4 | alias TypeTuple!(int, string, double) ISD; 5 | alias TypeTuple!(ISD, ISD) ISDISD; 6 | // ISDISD is *not* ((int, string, double), (int, string, double)) 7 | // It's (int, string, double, int, string, double) 8 | static assert(is(ISDISD == TypeTuple!(int,string,double,int,string,double))); 9 | -------------------------------------------------------------------------------- /utils/usingstaticfilter1.d: -------------------------------------------------------------------------------- 1 | module usingstaticfilter1; 2 | import std.typetuple; 3 | import std.traits; 4 | import staticfilter; 5 | 6 | alias TypeTuple!(int, double, float, string, byte, bool, float, void) Types; 7 | 8 | alias staticFilter!(isIntegral, Types) OnlyIntegrals; 9 | 10 | static assert(is(OnlyIntegrals == TypeTuple!(int, byte))); 11 | -------------------------------------------------------------------------------- /utils/function_declaration1.d: -------------------------------------------------------------------------------- 1 | module function_declaration1; 2 | import std.conv : to; 3 | 4 | // declaration: 5 | template myFunc(T, int n) 6 | { 7 | auto myFunc(T t) { return to!int(t) * n;} 8 | } 9 | 10 | void main() 11 | { 12 | // call: 13 | auto result = myFunc!(double,3)(3.1415); 14 | 15 | assert(result == to!int(3.1415)*3); 16 | } 17 | -------------------------------------------------------------------------------- /utils/constraintsyntax.d: -------------------------------------------------------------------------------- 1 | module constraintsyntax; 2 | 3 | T theFunction(T)(T argument) 4 | if (is(T : int) || is(T : double)) 5 | { return argument; } 6 | 7 | struct TheStruct(T) 8 | if (is(T : int) || is(T : double)) 9 | { /*...*/ } 10 | 11 | class TheClass(T) 12 | if (is(T : int) || is(T : double)) 13 | : BaseClass!T, Interface1 14 | { /*...*/ } 15 | -------------------------------------------------------------------------------- /utils/internaldeclarations2.d: -------------------------------------------------------------------------------- 1 | module internaldeclarations2; 2 | import declaration; 3 | 4 | alias DtoS = Transformer!(double, string); 5 | 6 | void main() 7 | { 8 | auto s = DtoS.transform(3.14159); 9 | auto m = new DtoS.Modificator(1.618); // DtoS.Modificator is a class 10 | // storing a double and a string. 11 | } 12 | -------------------------------------------------------------------------------- /utils/usingqualifiedname.d: -------------------------------------------------------------------------------- 1 | module usingqualifiedname; 2 | import qualifiedname; 3 | import cclass; 4 | 5 | void main() 6 | { 7 | auto c = new C(); 8 | assert(qualifiedName!c == "usingqualifiedname.main.c"); 9 | 10 | assert(qualifiedName!(c.foo) == "cclass.C.foo"); // same in both cases 11 | assert(qualifiedName!(C.foo) == "cclass.C.foo"); 12 | } 13 | -------------------------------------------------------------------------------- /utils/nameof1.d: -------------------------------------------------------------------------------- 1 | module nameof1; 2 | 3 | template nameOf(alias name) 4 | { 5 | enum string nameOf = name.stringof; 6 | } 7 | 8 | struct Example { int i;} 9 | 10 | void main() 11 | { 12 | Example example; 13 | 14 | auto s1 = nameOf!(Example); 15 | auto s2 = nameOf!(example); 16 | 17 | assert(s1 == "Example"); 18 | assert(s2 == "example"); 19 | } 20 | -------------------------------------------------------------------------------- /utils/basicTree1.d: -------------------------------------------------------------------------------- 1 | module basicTree1; 2 | 3 | struct Tree { 4 | int value; 5 | Tree[] children; 6 | 7 | size_t size() { 8 | size_t s = 1; 9 | foreach(child; children) 10 | s += child.size(); 11 | return s; 12 | } 13 | 14 | bool isLeaf() @property { 15 | return children.length == 0; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /utils/checkedinheritance.d: -------------------------------------------------------------------------------- 1 | module checkedinheritance; 2 | import superlist; 3 | import interfacelist; 4 | 5 | template CheckedInheritance(Base) 6 | { 7 | alias CheckedImpl!(Base).Result CheckedInheritance; 8 | } 9 | 10 | template CheckedImpl(Base) 11 | { 12 | /* Rewrite the 13 | } 14 | 15 | // It works! 16 | class NoError : CheckedInheritance!(MyClass) { /*...*/ } 17 | -------------------------------------------------------------------------------- /utils/mystruct1.d: -------------------------------------------------------------------------------- 1 | module mystruct1; 2 | 3 | template MyStruct(string name) 4 | { 5 | enum string MyStruct = "struct " ~ name 6 | ~ " { " 7 | ~ "/+ some code +/" 8 | ~ " }"; 9 | } 10 | 11 | // For example, with name == "First", it will return 12 | // "struct First { /+ some code +/ }" 13 | // 14 | -------------------------------------------------------------------------------- /utils/genericTree.d: -------------------------------------------------------------------------------- 1 | module genericTree; 2 | 3 | struct Tree(Type) { 4 | Type value; 5 | Tree[] children; 6 | 7 | size_t size() { 8 | size_t s = 1; 9 | foreach(child; children) 10 | s += child.size(); 11 | return s; 12 | } 13 | 14 | bool isLeaf() @property { 15 | return children.length == 0; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /utils/getset2.d: -------------------------------------------------------------------------------- 1 | module getset2; 2 | 3 | enum GetSet { no, yes} 4 | 5 | struct S(GetSet getset = GetSet.no, T) 6 | { 7 | enum priv = "private T value;\n" 8 | ~ "T get() @property { return value;}\n" 9 | ~ "void set(T _value) { value = _value;}"; 10 | 11 | enum pub = "T value;"; 12 | 13 | mixin( (getset == GetSet.yes) ? priv : pub); 14 | } 15 | -------------------------------------------------------------------------------- /utils/tree3.d: -------------------------------------------------------------------------------- 1 | module tree3; 2 | import std.array; 3 | 4 | struct Tree(T) 5 | { 6 | alias T Type; 7 | T value; 8 | Tree[] children; 9 | 10 | bool isLeaf() @property { return children.empty;} 11 | } 12 | 13 | void main() 14 | { 15 | Tree!string t0 =Tree!string("abc"); 16 | alias typeof(t0) T0; 17 | 18 | static assert(is( T0.Type == string )); 19 | } 20 | -------------------------------------------------------------------------------- /utils/parent.d: -------------------------------------------------------------------------------- 1 | module parent; 2 | import nameof; 3 | import cclass; 4 | 5 | // C is more precisely a cclass.C) 6 | static assert(nameOf!(__traits(parent, C)) == "cclass"); 7 | 8 | void main() 9 | { 10 | auto c = new C(); // c is "parent.main.c" 11 | assert(nameOf!(__traits(parent, c)) == "main"); 12 | assert(nameOf!(__traits(parent, c.i)) == "C"); 13 | c.foo(1); 14 | } 15 | -------------------------------------------------------------------------------- /utils/allmembers.d: -------------------------------------------------------------------------------- 1 | module allmembers; 2 | import overloads2; 3 | import std.typetuple; 4 | 5 | template GetOverloads(alias a) 6 | { 7 | template GetOverloads(string member) 8 | { 9 | alias Overloads!(a, member) GetOverloads; 10 | } 11 | } 12 | 13 | template AllMembers(alias a) 14 | { 15 | alias staticMap!(GetOverloads!(a), __traits(allMembers, a)) AllMembers; 16 | } 17 | -------------------------------------------------------------------------------- /utils/selector.d: -------------------------------------------------------------------------------- 1 | module selector; 2 | import std.traits: isIntegral, isFloatingPoint; 3 | 4 | template selector(T, alias intFoo, alias floatFoo, alias defaultFoo) 5 | { 6 | static if (isIntegral!T) 7 | alias intFoo selector; 8 | else static if (isFloatingPoint!T) 9 | alias floatFoo selector; 10 | else // default case 11 | alias defaultFoo selector; 12 | } 13 | -------------------------------------------------------------------------------- /utils/namedtuple.d: -------------------------------------------------------------------------------- 1 | module namedtuple; 2 | import std.typecons; 3 | import std.typetuple; 4 | import interleave; 5 | import isastringliteral; 6 | 7 | template tuple(names...) 8 | if (names.length && allSatisfy!(isAStringLiteral, names)) 9 | { 10 | auto tuple(T...)(T args) if (T.length >= names.length) 11 | { 12 | return Tuple!(Interleave!(T).With!(names))(args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /utils/heap2.d: -------------------------------------------------------------------------------- 1 | module heap2; 2 | 3 | auto heap(alias predicate, Type)(Type[] values) 4 | { 5 | struct Heap 6 | { 7 | Type[] values; 8 | this(Type[] _values) 9 | { 10 | /* some code initializing values using predicate */ 11 | } 12 | /* more heapy code */ 13 | } 14 | 15 | return Heap(values); // alias predicate is implicit there 16 | } 17 | -------------------------------------------------------------------------------- /utils/isserializable.d: -------------------------------------------------------------------------------- 1 | module isserializable; 2 | 3 | template isSerializable(Type) 4 | { 5 | static if (__traits(compiles, { 6 | Type type; 7 | size_t num = type.serialize; 8 | })) 9 | enum bool isSerializable = true; 10 | else 11 | enum bool isSerializable = false; 12 | } 13 | -------------------------------------------------------------------------------- /utils/usingnotify.d: -------------------------------------------------------------------------------- 1 | module usingnotify; 2 | import std.stdio; 3 | import usingfields; 4 | import notify; 5 | 6 | class Widget 7 | { 8 | this() 9 | { 10 | point.init((ref Point pt) { writefln("changed point to %s", pt); }); 11 | size.init((ref Size sz) { writefln("changed size to %s", sz); }); 12 | } 13 | 14 | Notify!Point point; 15 | Notify!Size size; 16 | } 17 | -------------------------------------------------------------------------------- /utils/tree2.d: -------------------------------------------------------------------------------- 1 | module tree2; 2 | import tree1; 3 | 4 | auto tree(T)(T value, Tree!T[] children = null) 5 | { 6 | return Tree!(T)(value, children); 7 | } 8 | 9 | void main() 10 | { 11 | auto t0 = tree(0); // Yes! 12 | auto t1 = tree(1, [t0,t0]); // Yes! 13 | 14 | static assert(is( typeof(t1) == Tree!int )); 15 | 16 | auto t2 = tree(t0); // Yes! typeof(t2) == Tree!(Tree!(int)) 17 | } 18 | -------------------------------------------------------------------------------- /utils/usingmystruct1.d: -------------------------------------------------------------------------------- 1 | module usingmystruct1; 2 | import mystruct1; 3 | 4 | mixin(MyStruct!"First"); // creates a new type called First (a struct) 5 | mixin(MyStruct!"Second"); // and another one called Second 6 | 7 | void main() 8 | { 9 | // "First" code was injected right there, in module 'mine'. 10 | First f1, f2; 11 | Second s1; 12 | 13 | assert(is( typeof(f1) == First)); 14 | } 15 | -------------------------------------------------------------------------------- /utils/ifti.d: -------------------------------------------------------------------------------- 1 | module ifti; 2 | import function_declaration2; 3 | 4 | struct Foo {} 5 | 6 | void main() 7 | { 8 | string res1 = concatenate(1, 3.14); // A is int and B is double 9 | string res2 = concatenate("abc", Foo()); // A is string, B is Foo 10 | 11 | auto res3 = select(3,4); // how is "max", Arg is int. 12 | auto res4 = select!"min"(3.1416, 2.718); // how is "min", Arg is double. 13 | } 14 | -------------------------------------------------------------------------------- /utils/isbuiltintype.d: -------------------------------------------------------------------------------- 1 | module isbuiltintype; 2 | 3 | template isSymbol(alias a) 4 | { 5 | enum isSymbol = true; 6 | } 7 | 8 | template isBuiltinType(T) 9 | { 10 | static if (__traits(compiles, isSymbol!(T))) 11 | enum isBuiltinType = false; 12 | else 13 | enum isBuiltinType = true; 14 | } 15 | 16 | template isBuiltinType(alias a) 17 | { 18 | enum isBuiltinType = false; 19 | } 20 | -------------------------------------------------------------------------------- /utils/using_flatten1.d: -------------------------------------------------------------------------------- 1 | module using_flatten1; 2 | import flatten1; 3 | 4 | void main() 5 | { 6 | assert( flatten([[0,1],[2,3],[4]]) == [0,1,2,3,4] ); 7 | assert( flatten([[0,1]]) == [0,1] ); 8 | assert( flatten([0,1]) == [0,1] ); 9 | assert( flatten(0) == 0 ); 10 | 11 | assert( flatten([[[0,1],[]], [[2]], [[3], [4,5]], [[]], [[6,7,8]]]) 12 | == [0,1,2,3,4,5,6,7,8] ); 13 | } 14 | -------------------------------------------------------------------------------- /utils/using_rank1.d: -------------------------------------------------------------------------------- 1 | module using_rank1; 2 | import rank1; 3 | 4 | static assert(rank!(int) == 0); 5 | static assert(rank!(int[]) == 1); 6 | static assert(rank!(int[][]) == 2); 7 | static assert(rank!(int[][][]) == 3); 8 | 9 | /* It will work for any type, obviously */ 10 | struct S {} 11 | 12 | static assert(rank!(S) == 0); 13 | static assert(rank!(S[])== 1); 14 | static assert(rank!(S*) == 0); 15 | -------------------------------------------------------------------------------- /utils/usingoverloads1.d: -------------------------------------------------------------------------------- 1 | module usingoverloads1; 2 | import std.stdio; 3 | import overloads1; 4 | import myclass; 5 | 6 | void main() 7 | { 8 | alias Overloads!(MyClass, "foo") o; 9 | 10 | /* 11 | prints: 12 | foo, of type: void(int j) 13 | foo, of type: int(int j, int k = 0) 14 | */ 15 | foreach(elem; o) 16 | writeln(elem.name, ", of type: ", elem.Type.stringof); 17 | } 18 | -------------------------------------------------------------------------------- /utils/canbeinstantiated.d: -------------------------------------------------------------------------------- 1 | module canbeinstantiated; 2 | 3 | template CanBeInstantiatedWith(alias templateName, Types...) 4 | { 5 | // is templateName!(Types) a valid type? 6 | static if (is( templateName!(Types) ResultType )) 7 | // here you can use ResultType (== templateName!(Types)) 8 | alias ResultType CanBeInstantiatedWith; 9 | else 10 | alias void CanBeInstantiatedWith; 11 | } 12 | -------------------------------------------------------------------------------- /utils/mystruct2.d: -------------------------------------------------------------------------------- 1 | module mystruct2; 2 | 3 | template MyStruct(string name) 4 | { 5 | alias MyStructImpl!(name).result MyStruct; 6 | } 7 | 8 | template MyStructImpl(string name) 9 | { 10 | enum string code = "struct " ~ name 11 | ~ " { " 12 | ~ "/+ some code +/" 13 | ~ " }"; 14 | mixin(code); 15 | mixin("alias " ~ name ~ " result;"); 16 | } 17 | -------------------------------------------------------------------------------- /utils/def.d: -------------------------------------------------------------------------------- 1 | module def; 2 | 3 | template Default(T = int, bool flag = false) 4 | { 5 | static if (flag) 6 | alias T Default; 7 | else 8 | alias void Default; 9 | } 10 | 11 | alias Default!(double) D1; // Instantiate Default!(double, false) 12 | alias Default!(double, true) D2; // Instantiate Default!(double, true) (Doh!) 13 | alias Default!() D3; // Instantiate Default!(int, false) 14 | -------------------------------------------------------------------------------- /utils/areallranges.d: -------------------------------------------------------------------------------- 1 | module areallranges; 2 | import std.range; 3 | 4 | template areAllRanges(Ranges...) 5 | { 6 | static if (Ranges.length == 0) // Base case: stop. 7 | enum areAllRanges = true; 8 | else static if (!isInputRange!(Ranges[0])) // Found a not-range:stop. 9 | enum areAllRanges = false; 10 | else // Continue the recursion 11 | enum areAllRanges = areAllRanges!(Ranges[1..$]); 12 | } 13 | -------------------------------------------------------------------------------- /utils/flatten2.d: -------------------------------------------------------------------------------- 1 | module flatten2; 2 | 3 | import std.range; 4 | import rank2; 5 | 6 | struct Flatten(Range) 7 | { 8 | Range range; 9 | /*...*/ 10 | } 11 | 12 | auto flatten(Range)(Range range) 13 | { 14 | static if (rank!Range == 0) 15 | static assert(0, "flatten needs a range."); 16 | else static if (rank!Range == 1) 17 | return range; 18 | else 19 | return Flatten!(Range)(range); 20 | } 21 | -------------------------------------------------------------------------------- /utils/init.d: -------------------------------------------------------------------------------- 1 | // Has anyone a better example? 2 | module init; 3 | 4 | template init(T) 5 | { 6 | static if (is(T == immutable) || is(T == const)) 7 | void init(T t) {} // do nothing 8 | else static if (is(T == class)) 9 | void init(ref T t) 10 | { 11 | t = new T(); 12 | } 13 | else 14 | void init(ref T t) 15 | { 16 | t = T.init; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /utils/staticfilter.d: -------------------------------------------------------------------------------- 1 | module staticfilter; 2 | import std.typetuple; 3 | 4 | template staticFilter(alias Pred, T...) 5 | { 6 | static if (T.length == 0) // End of sequence 7 | alias TypeTuple!() staticFilter; 8 | else static if (Pred!(T[0])) 9 | alias TypeTuple!(T[0], staticFilter!(Pred, T[1..$])) staticFilter; 10 | else 11 | alias TypeTuple!( staticFilter!(Pred, T[1..$])) staticFilter; 12 | } 13 | -------------------------------------------------------------------------------- /utils/transp2.d: -------------------------------------------------------------------------------- 1 | module transp2; 2 | import transp; 3 | 4 | struct Thin(T) 5 | { 6 | T value; 7 | alias value this; 8 | } 9 | 10 | Thin!T thin(T)(T t) 11 | { 12 | return Thin!T(t); 13 | } 14 | 15 | unittest 16 | { 17 | auto i = transparent(10); 18 | auto t = thin(i); // Works. 19 | assert(t == 10); // Yep, value was transmitted correctly. 20 | 21 | assert(is(typeof(t) == Thin!(Transparent!int))); 22 | } 23 | -------------------------------------------------------------------------------- /utils/nmap2.d: -------------------------------------------------------------------------------- 1 | module nmap2; 2 | import std.algorithm; 3 | import std.functional : adjoin; 4 | import std.range; 5 | import std.typetuple : allSatisfy; 6 | import acceptingtuple; // tuplify 7 | 8 | template nmap(fun...) if (fun.length >= 1) 9 | { 10 | auto nmap(R...)(R ranges) if (allSatisfy!(isInputRange, R)) 11 | { 12 | alias adjoin!(staticMap!(tuplify, fun)) _fun; 13 | return map!(_fun)(zip(ranges)); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /utils/specialization1.d: -------------------------------------------------------------------------------- 1 | module specialization1; 2 | 3 | template ElementType(T : U[], U) // can only be instantiated with arrays 4 | { 5 | alias U ElementType; 6 | } 7 | 8 | template ElementType(T : U[n], U, size_t n) // only with static arrays 9 | { 10 | alias U ElementType; 11 | } 12 | 13 | class Array { alias int ElementType;} 14 | 15 | template ElementType(T : Array) 16 | { 17 | alias Array.ElementType ElementType; 18 | } 19 | -------------------------------------------------------------------------------- /utils/using_makecounter.d: -------------------------------------------------------------------------------- 1 | module using_makecounter; 2 | import makecounter; 3 | 4 | void main() 5 | { 6 | auto c = makeCounter(0); // T is int. 7 | auto c2 = makeCounter!int; // The very same. 8 | 9 | c.inc(5); 10 | assert(c.counter() == 5); 11 | c.inc(10); 12 | assert(c.counter() == 15); 13 | c.changeSense(); // now each increment will in fact decrement 14 | c.inc(5); 15 | assert(c.counter() == 10); 16 | } 17 | -------------------------------------------------------------------------------- /utils/dropfront.d: -------------------------------------------------------------------------------- 1 | module dropfront; 2 | 3 | template DropFront(T...) 4 | { 5 | static if ( T.length > 0 // .length. At least 1 element 6 | && is(T[0] == int)) // Indexing 7 | alias T[1..$] DropFront; // Slicing 8 | else 9 | alias void DropFront; 10 | } 11 | 12 | alias DropFront!(int, double, string) Shortened; 13 | static assert(is( Shortened[0] == double)); 14 | static assert(is( Shortened[1] == string)); 15 | -------------------------------------------------------------------------------- /utils/templateintrospection.d: -------------------------------------------------------------------------------- 1 | module templateintrospection; 2 | 3 | template Temp(A, B) 4 | { 5 | A a; 6 | B foo(A a, B b) { return b;} 7 | int i; 8 | alias A AType; 9 | alias A[B] AAType; 10 | } 11 | 12 | static assert([__traits(allMembers, Temp)] 13 | == ["a", "foo", "i", "AType", "AAType"]); 14 | static assert([__traits(allMembers, Temp!(double,string))] 15 | == ["a","foo", "i", "AType", "AAType"]); 16 | -------------------------------------------------------------------------------- /utils/templatedinner.d: -------------------------------------------------------------------------------- 1 | module templatedinner; 2 | 3 | struct Outer(O) 4 | { 5 | O o; 6 | 7 | struct Inner(I) 8 | { 9 | O o; 10 | I i; 11 | } 12 | 13 | auto inner(I)(I i) { return Inner!(I)(o,i);} 14 | } 15 | 16 | auto outer(O)(O o) { return Outer!(O)(o);} 17 | 18 | void main() 19 | { 20 | auto o = outer(1); // o is an Outer!int; 21 | auto i = o.inner("abc"); // Outer.Outer!(int).Inner.Inner!(string) 22 | } 23 | -------------------------------------------------------------------------------- /utils/checkedwrite.d: -------------------------------------------------------------------------------- 1 | module checkedwrite; 2 | import std.stdio; 3 | import std.traits; 4 | import verifychecks; 5 | 6 | void cwritef(alias a, Args...)(Args args) 7 | if (isSomeString!(typeof(a)) 8 | && VerifyChecks!(1, ArgsChecks!(a)).on!(Args)) 9 | { 10 | writef(a, args); 11 | } 12 | 13 | void cwritefln(alias a, Args...)(Args args) 14 | if (isSomeString!(typeof(a)) 15 | && VerifyChecks!(1, ArgsChecks!(a)).on!(Args)) 16 | { 17 | writefln(a, args); 18 | } 19 | -------------------------------------------------------------------------------- /utils/classsyntax3.d: -------------------------------------------------------------------------------- 1 | module classsyntax3; 2 | 3 | enum WhatBase { Object, Interface, BaseClass } 4 | 5 | template Base(WhatBase whatBase = WhatBase.Object) 6 | { 7 | static if (is(T == WhatBase.Object)) 8 | alias Object Base; // MyClass inherits directly from Object 9 | else static if(is(T == WhatBase.Interface)) 10 | alias TheInterface Base; 11 | else 12 | alias TheBase Base; 13 | } 14 | 15 | class MyClass(Type) : Base!Type {} 16 | -------------------------------------------------------------------------------- /utils/serializetemplate.d: -------------------------------------------------------------------------------- 1 | module serializetemplate; 2 | 3 | enum SerializationPolicy { policy1, policy2 } 4 | 5 | interface ISerializable 6 | (SerializationPolicy policy = SerializationPolicy.policy1) 7 | { 8 | static if (is(policy == SerializationPolicy.policy1)) 9 | void serialize() { /*...*/ } 10 | else 11 | void serialize() { /*...*/ } 12 | } 13 | 14 | class Serializable(T, Policy) : T, ISerializable!Policy 15 | { 16 | /*...*/ 17 | } 18 | -------------------------------------------------------------------------------- /utils/flatten4.d: -------------------------------------------------------------------------------- 1 | module flatten4; 2 | import rank2; 3 | public import flatten3; 4 | 5 | auto flatten(Range)(Range range) 6 | { 7 | static if (rank!Range == 0) 8 | static assert(0, "flatten needs a range."); 9 | else static if (rank!Range == 1) 10 | return range; 11 | else static if (rank!Range == 2) 12 | return Flatten!(Range)(range); 13 | else // rank 3 or higher 14 | return flatten(Flatten!(Range)(range)); 15 | } 16 | -------------------------------------------------------------------------------- /utils/tester.d: -------------------------------------------------------------------------------- 1 | module tester; 2 | import qualified; 3 | 4 | void myFun(T)(T t) {} 5 | 6 | template test(alias fun) 7 | { 8 | void on(T...)() 9 | { 10 | foreach(Type; T) 11 | static if (!__traits(compiles, fun(Type.init))) 12 | pragma(msg, "Bad testing combination: " 13 | ~ fun.stringof ~ " and " ~ Type.stringof); 14 | } 15 | } 16 | 17 | unittest 18 | { 19 | test!(myFun).on!(QualifiedTypes); 20 | } 21 | -------------------------------------------------------------------------------- /utils/maponalias.d: -------------------------------------------------------------------------------- 1 | module maponalias; 2 | import std.typetuple; 3 | 4 | /** 5 | * Maps the Mapper template on the alias list. 6 | */ 7 | template MapOnAlias(alias Mapper, alias current, Rest...) 8 | { 9 | static if (Rest.length) 10 | alias TypeTuple!(Mapper!current, MapOnAlias!(Mapper, Rest)) MapOnAlias; 11 | else 12 | alias Mapper!current MapOnAlias; 13 | } 14 | 15 | template MapOnAlias(alias Mapper) 16 | { 17 | alias TypeTuple!() MapOnAlias; 18 | } 19 | -------------------------------------------------------------------------------- /utils/qualifiedname.d: -------------------------------------------------------------------------------- 1 | module qualifiedname; 2 | import nameof; 3 | 4 | template qualifiedName(alias a) 5 | { 6 | // does it have a parent? 7 | static if (__traits(compiles, __traits(parent, a))) 8 | // If yes, get the name and recurse 9 | enum qualifiedName = qualifiedName!(__traits(parent, a)) 10 | ~ "." ~ nameOf!(a); 11 | // if not, it's a module name. Stop there. 12 | else 13 | enum qualifiedName = nameOf!a; 14 | } 15 | -------------------------------------------------------------------------------- /utils/repeatedcomposition.d: -------------------------------------------------------------------------------- 1 | module repeatedcomposition; 2 | 3 | template power(alias fun, uint exponent) 4 | { 5 | static if (exponent == 0) // degenerate case -> id function 6 | auto power(Args)(Args args) { return args; } 7 | else static if (exponent == 1) // end-of-recursion case -> fun 8 | alias fun power; 9 | else 10 | auto power(Args...)(Args args) 11 | { 12 | return .power!(fun, exponent-1)(fun(args)); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /utils/usingcheckedwrite.d: -------------------------------------------------------------------------------- 1 | module usingcheckedwrite; 2 | import checkedwrite; 3 | 4 | void main() 5 | { 6 | cwritefln!"For sample #%d, the results are (%s, %f)"( 0, "foo", 3.14); // OK 7 | 8 | // NOK: bad number or args: waited for 3 args, got 2. 9 | // cwritefln!"For sample #%d, the results are (%s, %f)"( 0, "foo"); 10 | 11 | // NOK: arg #3 of type double does not verify check isFloatingPoint 12 | // cwritefln!"For sample #%d, the results are (%s, %f)"( 0, 3.14, "foo"); 13 | } 14 | -------------------------------------------------------------------------------- /utils/usingstaticfilter2.d: -------------------------------------------------------------------------------- 1 | module usingstaticfilter2; 2 | import std.typetuple; 3 | import staticfilter; 4 | import istype; 5 | import isbuiltintype; 6 | 7 | class MyClass {} 8 | int foo(int i) { return i;} 9 | 10 | alias staticFilter!(isType, 1, int, 3.14, "abc", foo, MyClass) Types; 11 | alias staticFilter!(isBuiltinType, 1, int, 3.14, "abc", foo, MyClass) Builtins; 12 | 13 | static assert(is(Types == TypeTuple!(int, MyClass))); 14 | static assert(is(Builtins == TypeTuple!(int))); 15 | -------------------------------------------------------------------------------- /utils/rank2.d: -------------------------------------------------------------------------------- 1 | module rank2; 2 | import std.range; 3 | 4 | template rank(T) 5 | { 6 | static if (isInputRange!T) // is T a range? 7 | enum size_t rank = 1 + rank!(ElementType!T); // if yes, recurse 8 | else 9 | enum size_t rank = 0; // base case, stop there 10 | } 11 | 12 | unittest 13 | { 14 | auto c = cycle([[0,1],[2,3]]); // == [[0,1],[2,3],[0,1],[2,3],[0,1]... 15 | assert(rank!(typeof(c)) == 2); // range of ranges 16 | } 17 | -------------------------------------------------------------------------------- /utils/baseelementtype.d: -------------------------------------------------------------------------------- 1 | module baseelementtype; 2 | import std.range; 3 | import rank2; 4 | 5 | template BaseElementType(T) 6 | { 7 | static if (rank!T == 0) // not a range 8 | static assert(0, T.stringof ~ " is not a range."); 9 | else static if (rank!T == 1) // simple range 10 | alias ElementType!T BaseElementType; 11 | else // at least range of ranges 12 | alias BaseElementType!(ElementType!(T)) BaseElementType; 13 | } 14 | -------------------------------------------------------------------------------- /utils/checkcompatibility.d: -------------------------------------------------------------------------------- 1 | module checkcompatibility; 2 | 3 | template CheckCompatibility(T...) 4 | { 5 | template With(U...) 6 | { 7 | static if (U.length != T.length) 8 | enum With = false; 9 | else static if (T.length == 0) // U.length == 0 also 10 | enum With = true; 11 | else static if (!is(U[0] : T[0])) 12 | enum With = false; 13 | else 14 | enum With = CheckCompatibility!(T[1..$]).With!(U[1..$]); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /utils/makemember.d: -------------------------------------------------------------------------------- 1 | module makemember; 2 | public import member; 3 | import nameof; 4 | 5 | template MakeMember(alias member) 6 | { 7 | mixin( "alias Member!(\"" 8 | ~ nameOf!member 9 | ~ "\", typeof(member)) MakeMember;"); 10 | } 11 | 12 | template MakeNamedMember(string name) 13 | { 14 | template MakeNamedMember(alias member) 15 | { 16 | mixin( "alias Member!(\"" 17 | ~ name 18 | ~ "\", typeof(member)) MakeNamedMember;"); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /utils/usingnamedtuple.d: -------------------------------------------------------------------------------- 1 | module usingnamedtuple; 2 | import namedtuple; 3 | 4 | void main() 5 | { 6 | auto myCounter = tuple!("counter", "name") 7 | (-1, "Who's his Daddy's counter?"); 8 | 9 | myCounter.counter = 1; 10 | 11 | // Or even: 12 | alias tuple!("counter", "name") makeCounter; 13 | 14 | auto c1 = makeCounter(0, "I count ints!"); 15 | auto c2 = makeCounter("Hello", "I'm a strange one, using strings"); 16 | 17 | c2.counter ~= " World!"; 18 | } 19 | -------------------------------------------------------------------------------- /utils/allmembersmodule.d: -------------------------------------------------------------------------------- 1 | module allmembersmodule; 2 | import std.algorithm; 3 | import std.compiler; 4 | 5 | // Huuuge list of names 6 | enum algos = [__traits(allMembers, std.algorithm)]; 7 | // A bit shorter 8 | enum compiler = [__traits(allMembers, std.compiler)]; 9 | 10 | void main() 11 | { 12 | assert(compiler == ["object", "name", 13 | "Vendor", "vendor", 14 | "version_major", "version_minor", 15 | "D_major", "D_minor"]); 16 | } 17 | -------------------------------------------------------------------------------- /utils/rangewrapper.d: -------------------------------------------------------------------------------- 1 | module rangewrapper; 2 | import std.range; 3 | 4 | struct RangeWrapper(Range) 5 | // Does Range comply with the input range 'concept'? 6 | if (isInputRange!Range) 7 | { 8 | /* Here we know that Range has at least three member functions: 9 | .front(), .popFront() and .empty(). We can use them happily.*/ 10 | } 11 | 12 | // In the factory function too. 13 | auto rangeWrapper(Range)(Range range) if (isInputRange!Range) 14 | { 15 | return RangeWrapper!(Range)(range); 16 | } 17 | -------------------------------------------------------------------------------- /utils/usingmemoize1.d: -------------------------------------------------------------------------------- 1 | module usingmemoize1; 2 | import memoize1; 3 | 4 | int veryLongCalc(int i, double d, string s) 5 | { 6 | /* ... cheating here ... */ 7 | return i; 8 | } 9 | 10 | void main() 11 | { 12 | auto vlcMemo = memoize!(veryLongCalc); 13 | 14 | // calculate veryLongCalc(1, 3.14, "abc") 15 | // takes minutes! 16 | int res1 = vlcMemo(1, 3.14, "abc"); 17 | int res2 = vlcMemo(2, 2.718, "def");// minutes again! 18 | int res3 = vlcMemo(1, 3.14, "abc"); // a few ms to get res3 19 | } 20 | -------------------------------------------------------------------------------- /utils/number.d: -------------------------------------------------------------------------------- 1 | module number; 2 | import std.traits; 3 | 4 | struct Number(T) if (isNumeric!T) 5 | { 6 | T num; 7 | 8 | auto opBinary(string op, U)(U u) 9 | if ((op == "+" || op == "-" || op == "*" || op == "/") 10 | && ((isNumeric!U) || is(U u == Number!V, V))) 11 | { 12 | mixin("alias typeof(a" ~ op ~ "b) Result; 13 | static if (isNumeric!U) 14 | return Number!Result(a"~op~"b); 15 | else 16 | return Number!Result(a"~op~"b.num);"); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /utils/variadic.d: -------------------------------------------------------------------------------- 1 | module variadic; 2 | 3 | string toStrings(string sep = ", ", Args...)(Args args) 4 | { 5 | import std.conv; 6 | string result; 7 | foreach(index, argument; args) 8 | { 9 | result ~= to!string(argument); 10 | if (index != args.length - 1) 11 | result ~= sep; // not for the last one 12 | } 13 | return result; 14 | } 15 | 16 | unittest 17 | { 18 | assert( toStrings(1, "abc", 3.14, 'a', [1,2,3]) 19 | == "1, abc, 3.14, a, [1, 2, 3]"); 20 | } 21 | -------------------------------------------------------------------------------- /utils/specialization2.d: -------------------------------------------------------------------------------- 1 | module specialization2; 2 | 3 | template InnerType(T : U*, U) // Specialization for pointers 4 | { 5 | alias U InnerType; 6 | } 7 | 8 | template InnerType(T : U[], U) // Specialization for dyn. arrays 9 | { /*...*/ } 10 | 11 | template InnerType(T) // Standard, default case 12 | { /*...*/ } 13 | 14 | void main() 15 | { 16 | int* p; 17 | int i; 18 | alias InnerType!(typeof(p)) Pointer; // pointer spec. selected 19 | alias InnerType!(typeof(i)) Default; // standard template selected 20 | } 21 | -------------------------------------------------------------------------------- /utils/function_declaration2.d: -------------------------------------------------------------------------------- 1 | module function_declaration2; 2 | import std.conv:to; 3 | 4 | string concatenate(A,B)(A a, B b) 5 | { 6 | return to!string(a) ~ to!string(b); 7 | } 8 | 9 | Arg select(string how = "max", Arg)(Arg arg0, Arg arg1) 10 | { 11 | static if (how == "max") 12 | return (arg0 < arg1) ? arg1 : arg0; 13 | else static if (how == "min") 14 | return (arg0 < arg1) ? arg0 : arg1; 15 | else 16 | static assert(0, 17 | "select: string 'how' must be either \"max\" or \"min\"."); 18 | } 19 | -------------------------------------------------------------------------------- /utils/staticscan.d: -------------------------------------------------------------------------------- 1 | module staticscan; 2 | import std.typetuple; 3 | 4 | /** 5 | Gives the TypeTuple resulting from the successive applications of F to reduce 6 | the T list. 7 | */ 8 | template StaticScan(alias F, T...) 9 | { 10 | static if (T.length == 0) 11 | alias TypeTuple!() StaticScan; // This case should never happen with normal use 12 | static if (T.length == 1) 13 | alias TypeTuple!(T[0]) StaticScan; 14 | else 15 | alias TypeTuple!(T[0], StaticScan!(F, F!(T[0], T[1]), T[2..$])) StaticScan; 16 | } 17 | -------------------------------------------------------------------------------- /utils/debugger.d: -------------------------------------------------------------------------------- 1 | module debugger; 2 | 3 | /** Usage: 4 | * Debug!(templateToBeTested).With!(Argument0, Argument1, Argument2); 5 | */ 6 | template Debug(alias toTest, string file = __FILE__, size_t line = __LINE__) 7 | { 8 | template With(Args...) 9 | { 10 | static if (is( toTest!Args )) 11 | alias toTest!Args With; 12 | else 13 | static assert(0, "Error: " ~ to!string(toTest) 14 | ~ " called withs arguments: " 15 | ~ Args.stringof); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /utils/innerconcatenate.d: -------------------------------------------------------------------------------- 1 | module innerconcatenate; 2 | import std.conv; 3 | 4 | auto concatenate(A)(A a) 5 | { 6 | struct Concatenator 7 | { 8 | A a; 9 | 10 | auto opCall(B)(B b) @trusted 11 | { 12 | return to!string(a) ~ to!string(b); 13 | } 14 | } 15 | 16 | Concatenator c; 17 | c.a = a; // So as not to activate opCall() 18 | 19 | return c; 20 | } 21 | 22 | void main() 23 | { 24 | auto c = concatenate(3.14); 25 | auto cc = c("abc"); 26 | assert(cc == "3.14abc"); 27 | } 28 | -------------------------------------------------------------------------------- /utils/internaldeclarations1.d: -------------------------------------------------------------------------------- 1 | module internaldeclarations1; 2 | import declaration; 3 | 4 | // ArrayType is accessible (it's int[]) 5 | // array is a completly standard dynamic array of ints. 6 | ArrayOf!(int).ArrayType array; 7 | ArrayOf!(int).ElementType element; // the same, element is an int. 8 | 9 | void main() 10 | { 11 | // the transform function is accessible. Instantiated like this, 12 | // it's a function from double to string. 13 | auto s = Transformer!(double,string).transform(3.14159); 14 | assert(is(typeof(s) == string)); // s is a string 15 | } 16 | -------------------------------------------------------------------------------- /utils/usingscopename.d: -------------------------------------------------------------------------------- 1 | module usingscopename; 2 | import std.stdio; 3 | import scopename; 4 | 5 | class C 6 | { 7 | mixin getScopeName; // 1 8 | 9 | int i; 10 | int foo(int j) 11 | { 12 | int k; 13 | mixin getScopeName; // 2 14 | writeln(scopeName); 15 | return i+k; 16 | } 17 | } 18 | 19 | void main() 20 | { 21 | auto c = new C(); 22 | writeln(c.scopeName); // "test.C" (1) 23 | c.foo(1); // "test.C.foo" (2) 24 | 25 | mixin getScopeName; // 3 26 | writeln(scopeName); // "test.main" (3) 27 | } 28 | -------------------------------------------------------------------------------- /utils/buildsortingcode.d: -------------------------------------------------------------------------------- 1 | module buildsortingcode; 2 | import stringinterpolation; 3 | import sortingnetwork; 4 | 5 | string buildSortingCode(size_t l)() 6 | { 7 | enum network = sortingNetwork!(l); 8 | string result; 9 | foreach(elem; network) result ~= 10 | interpolate!( 11 | "t1 = input[#0]; 12 | t2 = input[#1]; 13 | if (!binaryFun!pred(t1, t2)) 14 | { 15 | auto temp = t2; 16 | input[#1] = t1; 17 | input[#0] = temp; 18 | }\n")(elem[0], elem[1]); 19 | return result; 20 | } 21 | -------------------------------------------------------------------------------- /utils/noduplicates.d: -------------------------------------------------------------------------------- 1 | module noduplicates; 2 | import std.typetuple; 3 | import eliminate; 4 | 5 | template NoDuplicates(Types...) 6 | { 7 | static if (Types.length == 0) 8 | alias Types NoDuplicates; // No type, nothing to do. 9 | else 10 | alias TypeTuple!( 11 | Types[0] 12 | , NoDuplicates!(Eliminate!(Types[0], Types[1..$])) 13 | ) NoDuplicates; 14 | } 15 | 16 | static assert(is( NoDuplicates!(int,double,int,string,double) 17 | == TypeTuple!(int,double,string))); 18 | -------------------------------------------------------------------------------- /utils/tupledemonstration.d: -------------------------------------------------------------------------------- 1 | module tupledemonstration; 2 | 3 | template TupleDemonstration(T...) 4 | { 5 | alias T TupleDemonstration; 6 | } 7 | 8 | unittest 9 | { 10 | TupleDemonstration!(string, int, double) t; 11 | 12 | assert(t.length == 3); 13 | t[0] = "abc"; 14 | t[1] = 1; 15 | t[2] = 3.14; 16 | auto t2 = t[1..$]; 17 | assert(t2[0] == 1); 18 | assert(t2[1] == 3.14); 19 | 20 | void foo(int i, double d) {} 21 | foo(t2); // OK. 22 | 23 | double[] array = [t2]; // see, between [ and ] 24 | assert(array == [1.0, 3.14]); 25 | } 26 | -------------------------------------------------------------------------------- /utils/inordertree.d: -------------------------------------------------------------------------------- 1 | module inordertree; 2 | import std.algorithm; 3 | import tree5; 4 | 5 | T[] inOrderL(T, S)(T value, S seed) 6 | { 7 | return [value] ~ seed; 8 | } 9 | 10 | T[] inOrderB(T)(T value, T[][] inOrderChildren) 11 | { 12 | return [value] ~ reduce!"a~b"(inOrderChildren); 13 | } 14 | 15 | void main() 16 | { 17 | auto t0 = tree(0); 18 | auto t1 = tree(1, [t0,t0]); 19 | auto t2 = tree(2, [t1, t0, tree(3)]); 20 | 21 | int[] seed; // empty array 22 | auto inOrder = t2.fold!(inOrderL, inOrderB)(seed); 23 | assert(inOrder == [2, 1, 0, 0, 0, 3]); 24 | } 25 | -------------------------------------------------------------------------------- /utils/networksort.d: -------------------------------------------------------------------------------- 1 | module networksort; 2 | import std.range; 3 | import std.functional; 4 | import std.exception; 5 | import buildsortingcode; 6 | import stringinterpolation; 7 | 8 | template networkSort(size_t l) 9 | { 10 | mixin( 11 | interpolate!( 12 | "void networkSort(alias pred = \"a < b\", R)(ref R input) 13 | if (isRandomAccessRange!R) 14 | { 15 | enforce(input.length >= #, 16 | \"Calling networkSort!# with a range of less than # elements\"); 17 | ElementType!R t1, t2;")(l) 18 | ~ buildSortingCode!(l) 19 | ~ "}"); 20 | } 21 | -------------------------------------------------------------------------------- /utils/staticreduce.d: -------------------------------------------------------------------------------- 1 | module staticreduce; 2 | 3 | template staticReduce(alias bin, Types...) // Types[0] is the seed 4 | { 5 | static if (Types.length < 2) 6 | static assert(0, "staticReduce: tuple " 7 | ~ Types.stringof ~ " has not enough elements (min: 2 elements)"); 8 | else static if (Types.length == 2) // end of recursion 9 | alias bin!(Types[0], Types[1]) staticReduce; 10 | else // recurse 11 | alias staticReduce!(bin, bin!(Types[0], Types[1]) 12 | , Types[2..$]) 13 | staticReduce; 14 | } 15 | -------------------------------------------------------------------------------- /utils/popallfronts.d: -------------------------------------------------------------------------------- 1 | module popallfronts; 2 | import std.range, std.algorithm; 3 | import areallranges; 4 | 5 | void popAllFronts(Ranges...)(ref Ranges ranges) 6 | if(areAllRanges!Ranges) 7 | { 8 | foreach(index, range; ranges) 9 | ranges[index].popFront; // to get a ref access 10 | } 11 | 12 | unittest 13 | { 14 | auto arr1 = [0,1,2]; 15 | auto arr2 = "Hello, World!"; 16 | auto arr3 = map!"a*a"(arr1); 17 | 18 | popAllFronts(arr1, arr2, arr3); 19 | 20 | assert(arr1 == [1,2]); 21 | assert(arr2 == "ello, World!"); 22 | assert(equal( arr3, [1,4])); 23 | } 24 | -------------------------------------------------------------------------------- /utils/anonymous_function2.d: -------------------------------------------------------------------------------- 1 | module anonymous_function2; 2 | 3 | auto adder(T)(T a) 4 | { 5 | return (T b) { return a+b;}; 6 | } 7 | 8 | unittest 9 | { 10 | auto add1f = adder(1.0); // add1f is an float delegate(float) 11 | assert(add1f(2.0) == 3.0); 12 | 13 | import std.bigint; 14 | 15 | // addBigOne accepts a BigInt and returns a BigInt 16 | auto addBigOne = adder(BigInt("1000000000000000")); 17 | assert(addBigOne(BigInt("1")) == BigInt("1000000000000001")); 18 | 19 | // But: 20 | // auto error = add1(3.14); // Error! Waiting for an int, getting a double. 21 | } 22 | -------------------------------------------------------------------------------- /utils/summingtree.d: -------------------------------------------------------------------------------- 1 | module summingtree; 2 | import std.algorithm; 3 | import tree5; 4 | 5 | typeof(T.init + S.init) 6 | sumLeaf(T, S)(T value, S seed) 7 | { 8 | return value + seed; 9 | } 10 | 11 | T sumBranch(T)(T value, T[] summedChildren) 12 | { 13 | return value + reduce!"a+b"(summedChildren); 14 | } 15 | 16 | import std.stdio; 17 | 18 | void main() 19 | { 20 | auto t0 = tree(0); 21 | auto t1 = tree(1, [t0,t0]); 22 | auto t2 = tree(2, [t1, t0, tree(3)]); 23 | 24 | int sum = t2.fold!(sumLeaf, sumBranch)(0); 25 | assert(sum == 2 + (1 + 0 + 0) + (0) + (3)); 26 | } 27 | 28 | -------------------------------------------------------------------------------- /utils/maptuple.d: -------------------------------------------------------------------------------- 1 | module maptuple; 2 | import std.typecons; 3 | import std.typetuple; 4 | import std.functional; 5 | 6 | /** 7 | * Helper template to get a template function return type. 8 | */ 9 | template RT(alias fun) 10 | { 11 | template RT(T) 12 | { 13 | alias typeof(fun(T.init)) RT; 14 | } 15 | } 16 | 17 | /// Maps on a tuple, using a polymorphic function. Produces another tuple. 18 | Tuple!(staticMap!(RT!fun, T)) mapTuple(alias fun, T...)(Tuple!T tup) 19 | { 20 | StaticMap!(RT!fun, T) res; 21 | foreach(i, Type; T) res[i] = unaryFun!fun(tup.field[i]); 22 | return tuple(res); 23 | } 24 | -------------------------------------------------------------------------------- /utils/myclass.d: -------------------------------------------------------------------------------- 1 | module myclass; 2 | 3 | class MyClass 4 | { 5 | int i; // field 6 | alias i j; // symbol alias 7 | 8 | alias int Int; // type alias 9 | 10 | struct Inner {} // Inner type 11 | 12 | template Temp(T) { alias T Temp;} // template 13 | 14 | this() { i = 0;} // constructor #1 15 | this(int j) { i = j;} // constructor #2 16 | ~this() { } 17 | 18 | void foo(int j) { ++i;} // foo overload #1 19 | int foo(int j, int k = 0) { return i+j;} // foo overload #2 20 | 21 | alias foo bar; // symbol alias 22 | 23 | unittest 24 | { 25 | int i; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /utils/constrained.d: -------------------------------------------------------------------------------- 1 | module constrained; 2 | 3 | template Constrained(T) 4 | if (is(T : int)) { /*...*/ } // #1 5 | template Constrained(T) 6 | if (is(T : string)) { /*...*/ } // #2 7 | template Constrained(T,U) 8 | if (is(T : int) && !is(U : float)) { /*...*/ } // #3 9 | template Constrained(T,U) 10 | if (is(T : int) && is(U : float)) { /*...*/ } // #4 11 | 12 | alias Constrained!(int) C1; // #1 13 | // alias Constrained!(string) C2; // Error, no declaration fits (string) 14 | alias Constrained!(int,string) C3;// #3 and #4 considered, but #4 is dropped. 15 | // So #3 it is. 16 | -------------------------------------------------------------------------------- /utils/descriptor.d: -------------------------------------------------------------------------------- 1 | module descriptor; 2 | import std.stdio; 3 | 4 | struct Descriptor(T) 5 | { 6 | T value; 7 | alias value this; 8 | 9 | string description() @property 10 | { 11 | import std.conv; 12 | 13 | return "Descriptor holding a " ~ T.stringof 14 | ~ " of value " ~ to!string(value) ~ ".\n" 15 | ~ "(sizeof: " ~ to!string(T.sizeof) ~ " bytes)"; 16 | } 17 | } 18 | 19 | void main() 20 | { 21 | auto d = Descriptor!double(1.0); 22 | writeln(d.description); // "Descriptor holding a double of value 1 23 | // (sizeof: 8 bytes)" 24 | } 25 | -------------------------------------------------------------------------------- /utils/usingallmembers2.d: -------------------------------------------------------------------------------- 1 | module usingallmembers2; 2 | import std.typetuple; 3 | import std.stdio; 4 | import myclass; 5 | import allmembers; 6 | 7 | void main() 8 | { 9 | alias AllMembers!(MyClass) O; 10 | writeln(O.stringof); 11 | 12 | foreach(o; O) 13 | writeln(o.name, ", of type: " ~ o.Type.stringof); 14 | 15 | /* 16 | prints: 17 | i, of type: int 18 | j, of type: int 19 | Int, of type: int 20 | (...) 21 | __ctor, of type: MyClass() 22 | __ctor, of type: MyClass(int j) 23 | (...) 24 | foo, of type: void(int j) 25 | foo, of type: int(int j, int k = 0) 26 | (...) 27 | */ 28 | } 29 | -------------------------------------------------------------------------------- /utils/compare.d: -------------------------------------------------------------------------------- 1 | module compare; 2 | 3 | template Compare(First...) 4 | { 5 | template With(Second...) 6 | { 7 | static if (First.length != Second.length) 8 | enum With = false; 9 | else static if (First.length == 0) // End of comparison 10 | enum With = true; 11 | else static if (!is(First[0] == Second[0])) 12 | enum With = false; 13 | else 14 | enum With = Compare!(First[1..$]).With!(Second[1..$]); 15 | } 16 | } 17 | 18 | //Usage: 19 | unittest 20 | { 21 | alias Compare!(int, double, string).With!(int, double, char) C; 22 | static assert(C == false); 23 | } 24 | -------------------------------------------------------------------------------- /utils/interfacelist.d: -------------------------------------------------------------------------------- 1 | module interfacelist; 2 | import std.typetuple; 3 | 4 | interface I {} 5 | interface J {} 6 | interface K {} 7 | interface L {} 8 | 9 | class BaseA {} 10 | class BaseB {} 11 | 12 | template Inheritance(Base) if (is(Base == class)) 13 | { 14 | static if (is(Base : BaseA)) 15 | alias TypeTuple!(Base, I, J, K) Inheritance; 16 | else static if (is(Base : BaseB)) 17 | alias TypeTuple!(Base, L) Inheritance; 18 | else 19 | alias Base Inheritance; 20 | } 21 | 22 | // Inherits from Base 23 | class MyClass : Inheritance!BaseA { /*...*/ } 24 | class MyOtherClass : Inheritance!BaseB { /*...*/ } 25 | -------------------------------------------------------------------------------- /utils/tree4.d: -------------------------------------------------------------------------------- 1 | module tree4; 2 | import std.array; 3 | 4 | auto tree(T)(T value, Tree!T[] children = null) 5 | { 6 | return Tree!(T)(value, children); 7 | } 8 | 9 | struct Tree(T) 10 | { 11 | alias T Type; 12 | T value; 13 | Tree[] children; 14 | 15 | bool isLeaf() @property { return children.empty;} 16 | 17 | Tree!(typeof(fun(T.init))) map(alias fun)() 18 | { 19 | alias typeof(fun(T.init)) MappedType; 20 | MappedType mappedValue = fun(value); 21 | Tree!(MappedType)[] mappedChildren; 22 | foreach(child; children) mappedChildren ~= child.map!(fun); 23 | return tree(mappedValue, mappedChildren); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /utils/dispatcher.d: -------------------------------------------------------------------------------- 1 | module dispatcher; 2 | import std.typetuple; 3 | 4 | struct Dispatcher 5 | { 6 | int foo(int i) { return i*i;} 7 | string opDispatch(string name, T...)(T t) 8 | { 9 | return "Dispatch activated: " ~ name ~ ":" ~ TypeTuple!(T).stringof; 10 | } 11 | } 12 | 13 | void main() 14 | { 15 | Dispatcher d; 16 | 17 | auto i = d.foo(1); // compiler finds foo, calls foo. 18 | auto s1 = d.register("abc"); // no register member -> opDispatch activated; 19 | assert(s1 == "Dispatch activated: register:(string)"); 20 | 21 | auto s2 = d.empty; // no empty member, no argument. 22 | assert(s2 == "Dispatch activated: empty:()"); 23 | } 24 | -------------------------------------------------------------------------------- /utils/usingtransparent.d: -------------------------------------------------------------------------------- 1 | module usingtransparent; 2 | import transp; 3 | 4 | void main() 5 | { 6 | auto i = transparent(10); 7 | assert(i == 10); // equality testing 8 | 9 | i = 1; // Assignment from an int 10 | 11 | ++i; // ++ acts on i.value 12 | assert(i == 2); 13 | 14 | // int-accepting function 15 | int foo(int ii) { return ii+1;} 16 | 17 | assert(foo(i) == 3); // function calls 18 | 19 | int trueInt = i; // transmits its value 20 | 21 | assert(trueInt == 2); 22 | assert(i == 2); 23 | assert(i == trueInt); 24 | 25 | // Successive calls all collapse into one Transparent. 26 | i = transparent(transparent(i)); 27 | } 28 | -------------------------------------------------------------------------------- /utils/juxtapose.d: -------------------------------------------------------------------------------- 1 | module juxtapose; 2 | import juxtaposehelper; 3 | 4 | template juxtapose(Funs...) 5 | { 6 | Tuple!(staticFilter!(isNotVoid, ReturnTypes!Funs)) 7 | juxtapose(ParameterTypeTuples!Funs params) 8 | { 9 | typeof(return) result; 10 | alias SumOfArities!Funs arities; 11 | alias SumOfReturns!Funs returns; 12 | foreach(i, Fun; Funs) 13 | { 14 | enum firstParam = arities[i]; 15 | enum lastParam = firstParam + arity!(Fun); 16 | static if (returns[i] != returns[i+1]) 17 | result.field[returns[i]] = Fun(params[firstParam..lastParam]); 18 | } 19 | return result; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /utils/usingallmembers1.d: -------------------------------------------------------------------------------- 1 | module usingallmembers1; 2 | 3 | class MyClass 4 | { 5 | int i; 6 | 7 | this() { i = 0;} 8 | this(int j) { i = j;} 9 | ~this() { } 10 | 11 | void foo() { ++i;} 12 | int foo(int j) { return i+j;} 13 | } 14 | 15 | void main() 16 | { 17 | // Put in an array for a more human-readable printing 18 | enum myMembers = [__traits(allMembers, MyClass)]; 19 | 20 | // See "i" and "foo" in the middle of standard class members 21 | // "foo" appears only once, despite it being overloaded. 22 | assert(myMembers == ["i", "__ctor", "__dtor", "foo", "toString", 23 | "toHash", "opCmp", "opEquals", "Monitor", "factory"]); 24 | } 25 | -------------------------------------------------------------------------------- /utils/eliminate.d: -------------------------------------------------------------------------------- 1 | module eliminate; 2 | import std.typetuple; 3 | 4 | template Eliminate(Type, TargetTuple...) 5 | { 6 | static if (TargetTuple.length == 0) // Tuple exhausted, 7 | alias TargetTuple 8 | Eliminate; // job done. 9 | else static if (is(TargetTuple[0] : Type)) 10 | alias Eliminate!(Type, TargetTuple[1..$]) 11 | Eliminate; 12 | else 13 | alias TypeTuple!(TargetTuple[0], Eliminate!(Type, TargetTuple[1..$])) 14 | Eliminate; 15 | } 16 | 17 | unittest 18 | { 19 | alias TypeTuple!(int,double,int,string) Target; 20 | alias Eliminate!(int, Target) NoInts; 21 | static assert(is( NoInts == TypeTuple!(double, string) )); 22 | } 23 | -------------------------------------------------------------------------------- /utils/basicTree2.d: -------------------------------------------------------------------------------- 1 | module basicTree2; 2 | 3 | struct IntTree { 4 | int value; 5 | IntTree[] children; 6 | 7 | size_t size() { 8 | size_t s = 1; 9 | foreach(child; children) 10 | s += child.size(); 11 | return s; 12 | } 13 | 14 | bool isLeaf() @property { 15 | return children.length == 0; 16 | } 17 | } 18 | 19 | struct FloatTree { 20 | float value; 21 | FloatTree[] children; 22 | 23 | size_t size() { 24 | size_t s = 1; 25 | foreach(child; children) 26 | s += child.size(); 27 | return s; 28 | } 29 | 30 | bool isLeaf() @property { 31 | return children.length == 0; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /utils/anonymousclass.d: -------------------------------------------------------------------------------- 1 | module anonymousclass; 2 | 3 | // stores a function and a default return value. 4 | auto acceptor(alias fun, D)(D defaultValue) 5 | { 6 | return new class 7 | { 8 | this() {} 9 | 10 | auto opCall(T)(T t) 11 | { 12 | static if (__traits(compiles, fun(T.init))) 13 | return fun(t); 14 | else 15 | return defaultValue; 16 | } 17 | }; 18 | } 19 | 20 | unittest 21 | { 22 | int add1(int i) { return i+1;} 23 | auto accept = acceptor!(add1)(-1); 24 | 25 | auto test1 = accept(10); 26 | assert(test1 == 11); 27 | 28 | auto test2 = accept("abc"); 29 | assert(test2 == -1); // default value 30 | } 31 | -------------------------------------------------------------------------------- /utils/makecounter.d: -------------------------------------------------------------------------------- 1 | module makecounter; 2 | import std.traits; 3 | import std.typecons; 4 | 5 | auto makeCounter(T)(T _counter = T.init) if (isNumeric!T) 6 | { 7 | bool sense = true; 8 | auto changeSense = () { sense = !sense;}; 9 | auto inc = (T increment) 10 | { _counter += (sense ? increment : -increment); }; 11 | auto dec = (T decrement) 12 | { _counter += (sense ? -decrement : decrement); }; 13 | auto counter = (){ return _counter;}; 14 | 15 | return Tuple!( typeof(changeSense), "changeSense" 16 | , typeof(inc), "inc" 17 | , typeof(dec), "dec" 18 | , typeof(counter), "counter") 19 | (changeSense, inc, dec, counter); 20 | } 21 | -------------------------------------------------------------------------------- /utils/flatten3.d: -------------------------------------------------------------------------------- 1 | module flatten3; 2 | import std.range; 3 | 4 | import rank2; 5 | 6 | struct Flatten(Range) 7 | { 8 | alias ElementType!Range SubRange; 9 | alias ElementType!SubRange Element; 10 | 11 | Range range; 12 | SubRange subRange; 13 | 14 | this(Range _range) { 15 | range = _range; 16 | if (!range.empty) subRange = range.front; 17 | } 18 | 19 | Element front() { return subRange.front;} 20 | 21 | bool empty() { return range.empty;} 22 | 23 | void popFront() { 24 | if (!subRange.empty) subRange.popFront; 25 | while(subRange.empty && !range.empty) { 26 | range.popFront; 27 | if (!range.empty) subRange = range.front; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /utils/usingfriends.d: -------------------------------------------------------------------------------- 1 | module usingfriends; 2 | import friends; 3 | 4 | void main() 5 | { 6 | auto p = new FriendStack(); 7 | auto p2 = new ExtFriendStack(); 8 | 9 | // Register some subscribers. 10 | p.register( &twitter ); 11 | p2.register( &twitter ); 12 | p2.register( &blog ); 13 | p2.register( &blog ); 14 | 15 | // Push and Pop 16 | p.pushFriend( "Alex", 19 ); 17 | p.pushFriend( "Tommy", 55); 18 | p2.pushFriend( "Hans", 42, false); 19 | p2.pushFriend( "Walt", 101, true); 20 | 21 | p.popFriend(); 22 | p2.popFriend(); 23 | p2.popFriend(); 24 | 25 | p.unRegister( &twitter ); 26 | p2.unRegister( &twitter ); 27 | p.register( &blog ); 28 | p.pushFriend( "Alexej", 33 ); 29 | } 30 | -------------------------------------------------------------------------------- /utils/superlist.d: -------------------------------------------------------------------------------- 1 | module superlist; 2 | import std.typetuple; 3 | 4 | template SuperList(Class) if (is(Class == class)) 5 | { 6 | static if (is(Class Parent == super)) 7 | alias TypeTuple!(Parent, SuperList!Parent) SuperList; 8 | } 9 | 10 | // for Object, is(Object Parent == super)) gives an empty typetuple 11 | template SuperList() 12 | { 13 | alias TypeTuple!() SuperList; 14 | } 15 | 16 | unittest 17 | { 18 | class A {} 19 | class B : A {} 20 | class C : A {} 21 | class D : C {} 22 | 23 | static assert(is(SuperList!Object == TypeTuple!())); 24 | static assert(is(SuperList!A == TypeTuple!(Object))); 25 | static assert(is(SuperList!B == TypeTuple!(A, Object))); 26 | static assert(is(SuperList!D == TypeTuple!(C, A, Object))); 27 | } 28 | -------------------------------------------------------------------------------- /utils/fieldsof.d: -------------------------------------------------------------------------------- 1 | module fieldsof; 2 | 3 | /** 4 | * Evaluates to an array of strings containing 5 | * the names of the fields in the given type 6 | */ 7 | template fieldsOf (T) 8 | { 9 | const fieldsOf = fieldsOfImpl!(T, 0); 10 | } 11 | 12 | /** 13 | * Implementation for fieldsOf 14 | * 15 | * Returns: an array of strings containing the names of the fields in the given type 16 | */ 17 | template fieldsOfImpl (T, size_t i) 18 | { 19 | static if (T.tupleof.length == 0) 20 | enum fieldsOfImpl = [""]; 21 | 22 | else static if (T.tupleof.length - 1 == i) 23 | enum fieldsOfImpl = [T.tupleof[i].stringof[1 + T.stringof.length + 2 .. $]]; 24 | 25 | else 26 | enum fieldsOfImpl = T.tupleof[i].stringof[1 + T.stringof.length + 2 .. $] ~ fieldsOfImpl!(T, i + 1); 27 | } 28 | -------------------------------------------------------------------------------- /utils/usingrelational.d: -------------------------------------------------------------------------------- 1 | module usingrelational; 2 | import std.stdio; 3 | import relational; 4 | 5 | alias Entry!("Name", string 6 | ,"EmployId", int 7 | ,"Dept", string) Employee; 8 | 9 | alias Entry!("DeptName", string 10 | ,"Manager", string) Dept; 11 | 12 | void main() 13 | { 14 | auto e = entry!("Name", "EmployId", "DeptName")("John", 1, "Tech"); 15 | auto e2 = Employee("Susan", 2, "Financial"); 16 | auto e3 = Employee("Bob", 3, "Financial"); 17 | auto e4 = Employee("Sri", 4, "Tech"); 18 | 19 | auto d1 = Dept("Tech", "Sri"); 20 | auto d2 = Dept("Financial", "Bob"); 21 | 22 | auto employees = [e2,e3,e4]; 23 | auto depts = [d1, d2]; 24 | 25 | writeln(employees); 26 | 27 | writeln(rename!("Dept", "DN")(employees)); 28 | } 29 | -------------------------------------------------------------------------------- /utils/interleave.d: -------------------------------------------------------------------------------- 1 | module interleave; 2 | import std.typetuple; 3 | 4 | /** 5 | * Given (T0, T1, T2, ..., Tn) and (U0, U1, ..., Um) will returns 6 | * the interleaving of the first part with the second part: 7 | * 8 | * (T0, U0, T1, U1, ... 9 | * 10 | * If one of the inputs is shorter than the other, 11 | * the longer part is put at the end of the interleaving. 12 | */ 13 | template Interleave(First...) 14 | { 15 | template With(Second...) 16 | { 17 | static if (First.length == 0) 18 | alias Second With; 19 | else static if (Second.length == 0) 20 | alias First With; 21 | else 22 | alias TypeTuple!( First[0], Second[0] 23 | , Interleave!(First[1..$]).With!(Second[1..$])) 24 | With; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /utils/memoize1.d: -------------------------------------------------------------------------------- 1 | module memoize1; 2 | import std.traits; 3 | import std.typecons; 4 | 5 | struct Memoize(alias fun) 6 | { 7 | alias ReturnType!fun RT; 8 | alias ParameterTypeTuple!fun PTT; 9 | RT[Tuple!(PTT)] memo; // stores the result, indexed by arguments. 10 | 11 | RT opCall(PTT args) 12 | { 13 | if (tuple(args) in memo) // Have we already seen these args? 14 | { 15 | return memo[tuple(args)]; // if yes, use the stored result 16 | } 17 | else // if not, compute the result and store it. 18 | { 19 | RT result = fun(args); 20 | memo[tuple(args)] = result; 21 | return result; 22 | } 23 | } 24 | } 25 | 26 | Memoize!fun memoize(alias fun)() 27 | { 28 | Memoize!fun memo; 29 | return memo; 30 | } 31 | -------------------------------------------------------------------------------- /utils/validcall.d: -------------------------------------------------------------------------------- 1 | module validcall; 2 | import std.conv; 3 | 4 | bool validCall(alias fun, Args...)(Args args) 5 | { 6 | return is( typeof({ /* code to test */ 7 | fun(args); 8 | /* end of code to test */ 9 | }())); 10 | } 11 | 12 | // Usage: 13 | T add(T)(T a, T b) { return a+b;} 14 | string conc(A,B)(A a, B b) { return to!string(a) ~ to!string(b);} 15 | 16 | void main() 17 | { 18 | assert( validCall!add(1, 2)); // generates add!(int) 19 | assert(!validCall!add(1, "abc")); // no template instantiation possible 20 | 21 | assert( validCall!conc(1, "abc")); // conc!(int, string) is OK. 22 | assert(!validCall!conc(1) ); // no 1-argument version for conc 23 | 24 | struct S {} 25 | 26 | assert(!validCall!S(1, 2.3)); // S is not callable 27 | } 28 | -------------------------------------------------------------------------------- /utils/tree5.d: -------------------------------------------------------------------------------- 1 | module tree5; 2 | import std.array; 3 | 4 | Tree!(T) tree(T)(T value, Tree!T[] children = null) 5 | { 6 | return Tree!(T)(value, children); 7 | } 8 | 9 | struct Tree(T) 10 | { 11 | alias T Type; 12 | T value; 13 | Tree[] children; 14 | 15 | bool isLeaf() @property { return children.empty;} 16 | 17 | typeof(ifLeaf(T.init, S.init)) 18 | fold(alias ifLeaf, alias ifBranch = ifLeaf, S)(S seed) 19 | { 20 | if (isLeaf) 21 | { 22 | return ifLeaf(value, seed); 23 | } 24 | else 25 | { 26 | typeof(Tree.init.fold!(ifLeaf, ifBranch)(seed))[] foldedChildren; 27 | foreach(child; children) 28 | foldedChildren ~= child.fold!(ifLeaf, ifBranch)(seed); 29 | return ifBranch(value, foldedChildren); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /utils/maker.d: -------------------------------------------------------------------------------- 1 | module maker; 2 | import std.algorithm; 3 | import std.conv; 4 | 5 | template make(A) 6 | if (is(A a == class ) 7 | || is(A a == struct)) 8 | { 9 | auto make(Args...)(Args args) 10 | { 11 | static if (is(A a == class)) 12 | return new A(args); 13 | else 14 | return A(args); 15 | } 16 | } 17 | 18 | struct S {int i;} 19 | class C 20 | { 21 | int i; 22 | this(int ii) { i = ii;} 23 | override string toString() @property 24 | { 25 | return "C("~to!string(i)~")"; 26 | } 27 | } 28 | 29 | void main() 30 | { 31 | auto array = [0,1,2,3]; 32 | 33 | auto structRange = map!( make!S )(array); 34 | auto classRange = map!( make!C )(array); 35 | 36 | assert(equal(structRange, [S(0), S(1), S(2), S(3)])); 37 | assert(classRange.front.toString == "C(0)"); 38 | } 39 | -------------------------------------------------------------------------------- /utils/staticswitch.d: -------------------------------------------------------------------------------- 1 | module staticswitch; 2 | 3 | template staticSwitch(List...) // List[0] is the value commanding the switching 4 | // It can be a type or a symbol. 5 | { 6 | static if (List.length == 1) // No slot left: error 7 | static assert(0, "StaticSwitch: no match for " ~ List[0].stringof); 8 | else static if (List.length == 2) // One slot left: default case 9 | enum staticSwitch = List[1]; 10 | else static if (is(List[0] == List[1]) // Comparison on types 11 | || ( !is(List[0]) // Comparison on values 12 | && !is(List[1]) 13 | && is(typeof(List[0] == List[1])) 14 | && (List[0] == List[1]))) 15 | enum staticSwitch = List[2]; 16 | else 17 | enum staticSwitch = staticSwitch!(List[0], List[3..$]); 18 | } 19 | -------------------------------------------------------------------------------- /utils/half.d: -------------------------------------------------------------------------------- 1 | module half; 2 | import std.typetuple; 3 | 4 | template Half(T...) 5 | { 6 | static if (T.length == 0) 7 | alias TypeTuple!() Half; 8 | else static if (T.length == 1) 9 | alias TypeTuple!(T[0]) Half; 10 | else 11 | alias TypeTuple!(T[0], Half!(T[2..$])) Half; 12 | } 13 | 14 | unittest 15 | { 16 | alias TypeTuple!() Test0; 17 | alias TypeTuple!(int) Test1; 18 | alias TypeTuple!(int, float) Test2; 19 | alias TypeTuple!(int, float, string) Test3; 20 | alias TypeTuple!(int, float, string, double) Test4; 21 | 22 | static assert(is(Half!Test0 == TypeTuple!())); 23 | static assert(is(Half!Test1 == TypeTuple!(int))); 24 | static assert(is(Half!Test2 == TypeTuple!(int))); 25 | static assert(is(Half!Test3 == TypeTuple!(int, string))); 26 | static assert(is(Half!Test4 == TypeTuple!(int, string))); 27 | } 28 | -------------------------------------------------------------------------------- /utils/using_power.d: -------------------------------------------------------------------------------- 1 | module using_power; 2 | import repeatedcomposition; 3 | 4 | // standard function 5 | string foo(string s) { return s ~ s;} 6 | 7 | // function templates. You'll see them soon. 8 | Arr[] makeArray(Arr)(Arr array) { return [array,array];} 9 | 10 | void main() 11 | { 12 | // power!(foo, n) is a function. 13 | assert(power!(foo, 0)("a") == "a"); // identity function 14 | assert(power!(foo, 1)("a") == foo("a")); // "aa" 15 | assert(power!(foo, 2)("a") == foo(foo("a"))); // "aaaa" 16 | assert(power!(foo, 3)("a") == foo(foo(foo("a")))); // "aaaaaaaa" 17 | 18 | // It's even better with function templates: 19 | assert(power!(makeArray, 0)(1) == 1); 20 | assert(power!(makeArray, 1)(1) == [1,1]); 21 | assert(power!(makeArray, 2)(1) == [[1,1],[1,1]]); 22 | assert(power!(makeArray, 3)(1) == [[[1,1],[1,1]],[[1,1],[1,1]]]); 23 | } 24 | -------------------------------------------------------------------------------- /utils/hasarithmeticoperations.d: -------------------------------------------------------------------------------- 1 | module hasarithmeticoperations; 2 | 3 | template hasArithmeticOperations(Type) 4 | { 5 | static if (__traits(compiles, 6 | { 7 | Type t, result; 8 | result = t + t; // addition 9 | result = t - t; // substraction 10 | result = t * t; // multiplication 11 | result = t / t; // division 12 | result = +t; // unary + 13 | result = -t; // unary - 14 | })) 15 | enum bool hasArithmeticOperations = true; 16 | else 17 | enum bool hasArithmeticOperations = false; 18 | } 19 | 20 | static assert(hasArithmeticOperations!int); 21 | static assert(hasArithmeticOperations!double); 22 | 23 | struct S {} 24 | static assert(!hasArithmeticOperations!S); 25 | -------------------------------------------------------------------------------- /utils/sortingnetwork.d: -------------------------------------------------------------------------------- 1 | module sortingnetwork; 2 | 3 | int ceilLog2(int n) 4 | { 5 | int i; 6 | if ((n & (n-1)) == 0) i = -1; 7 | while (n > 0) { ++i; n/= 2;} 8 | return i; 9 | } 10 | 11 | /** 12 | * Given a length n, returns an array of indices pairs 13 | * corresponding to a sorting network for length n. 14 | * Looks a bit like C code, isn't it? 15 | */ 16 | int[2][] sortingNetwork(int n) 17 | { 18 | int[2][] network; 19 | auto t = ceilLog2(n); 20 | auto p = 1 << (t-1); 21 | while (p > 0) 22 | { 23 | auto q = 1 << (t-1); 24 | auto r = 0; 25 | auto d = p; 26 | while (d > 0) 27 | { 28 | for(int i = 0; i<=(n-d-1); ++i) 29 | { 30 | if (r == (i & p)) network ~= [i, i+d]; 31 | } 32 | d = q-p; 33 | q /= 2; 34 | r = p; 35 | } 36 | p /= 2; 37 | } 38 | return network; 39 | } 40 | -------------------------------------------------------------------------------- /utils/ttiteration.d: -------------------------------------------------------------------------------- 1 | module ttiteration; 2 | 3 | import std.typetuple; 4 | 5 | unittest 6 | { 7 | alias TypeTuple!(string, int, double) T; 8 | T t; 9 | t[0] = "abc"; 10 | t[1] = 1; 11 | t[2] = 3.14; 12 | 13 | string[T.length] s; 14 | 15 | foreach(index, Type; T) // Iteration on types. 16 | // Type is a different, er, type at each position 17 | { 18 | static if(is(Type == double)) 19 | s[index] = Type.stringof; 20 | } 21 | assert(s == ["", "", "double"]); 22 | 23 | void bar(T)(ref T d) { T t; d = t;} 24 | 25 | foreach(index, value; t) // Iteration on values. 26 | // value has a different type at each position! 27 | { 28 | bar(t[index]); // use t[iindex], not 'value' to get a ref access 29 | } 30 | 31 | assert(t[0] == ""); 32 | assert(t[1] == 0); 33 | 34 | import std.math; 35 | assert(std.math.isnan(t[2])); 36 | } 37 | -------------------------------------------------------------------------------- /utils/using_tree4.d: -------------------------------------------------------------------------------- 1 | module using_tree4; 2 | import std.conv; 3 | import tree4; 4 | 5 | int addOne(int a) { return a+1;} 6 | 7 | void main() 8 | { 9 | auto t0 = tree(0); 10 | auto t1 = tree(1, [t0,t0]); 11 | auto t2 = tree(2, [t1, t0, tree(3)]); 12 | 13 | /* t2 is 2 14 | / | \ 15 | 1 0 3 16 | / \ 17 | 0 0 18 | */ 19 | 20 | // t2 is a Tree!(int) 21 | static assert(is( t2.Type == int )); 22 | 23 | // Adding one to all values 24 | 25 | auto t3 = t2.map!(addOne); 26 | 27 | /* t3 is 3 28 | / | \ 29 | 2 1 4 30 | / \ 31 | 1 1 32 | */ 33 | 34 | assert(t3.value == 3); 35 | 36 | // Converting all values to strings 37 | auto ts = t2.map!(to!string); // we convert every value into a string; 38 | 39 | /* ts is "2" 40 | / | \ 41 | "1""0""3" 42 | / \ 43 | "0" "0" 44 | */ 45 | 46 | assert(is( ts.Type == string )); 47 | assert(ts.value == "2"); 48 | } 49 | -------------------------------------------------------------------------------- /utils/fields.d: -------------------------------------------------------------------------------- 1 | module fields; 2 | import std.typetuple; 3 | import isastringliteral; 4 | 5 | mixin template Fields(T, fields...) 6 | if (allSatisfy!(isAStringLiteral, fields)) 7 | { 8 | alias typeof(this) This; 9 | 10 | static string __makeFields(T, fields...)() 11 | { 12 | string res; 13 | foreach(field; fields) res ~= T.stringof~ " " ~ field ~ ";\n"; 14 | return res; 15 | } 16 | 17 | static string __makeOpBinaryFields(string op, fields...)() 18 | { 19 | string res; 20 | foreach(field; fields) 21 | res ~= "res." ~ field 22 | ~ " = this." ~ field ~ op ~ " rhs." ~ field ~ ";\n"; 23 | return res; 24 | } 25 | 26 | mixin(__makeFields!(T, fields)()); 27 | 28 | This opBinary(string op)(This rhs) 29 | { 30 | This res; 31 | mixin(__makeOpBinaryFields!(op, fields)()); 32 | return res; 33 | } 34 | 35 | void opOpAssign(string op)(This rhs) 36 | { 37 | mixin("this = this " ~ op ~ " rhs;"); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /utils/stringinterpolation.d: -------------------------------------------------------------------------------- 1 | module stringinterpolation; 2 | import std.conv; 3 | 4 | template interpolate(string code) 5 | { 6 | string interpolate(Args...)(Args args) { 7 | string[] stringified; 8 | foreach(index, arg; args) stringified ~= to!string(arg); 9 | 10 | string result; 11 | int i; 12 | int zero = to!int('0'); 13 | 14 | while (i < code.length) { 15 | if (code[i] == '#') { 16 | int j = 1; 17 | int index; 18 | while (i+j < code.length 19 | && to!int(code[i+j])-zero >= 0 20 | && to!int(code[i+j])-zero <= 9) 21 | { 22 | index = index*10 + to!int(code[i+j])-zero; 23 | ++j; 24 | } 25 | 26 | result ~= stringified[index]; 27 | i += j; 28 | } 29 | else { 30 | result ~= code[i]; 31 | ++i; 32 | } 33 | } 34 | 35 | return result; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /utils/qualified.d: -------------------------------------------------------------------------------- 1 | module qualified; 2 | import std.typetuple; 3 | 4 | /** 5 | * Given a type T, generates all qualified versions of T 6 | * that you find interesting (eleven versions all in all). 7 | */ 8 | template Qualified(T) 9 | { 10 | alias TypeTuple!( 11 | T, const(T), immutable(T), shared(T), 12 | T[],const(T)[],immutable(T)[], shared(T)[], 13 | const(T[]), immutable(T[]), shared(T[]) 14 | ) Qualified; 15 | } 16 | 17 | // All 16 built-in types you're interested in. 18 | alias TypeTuple!( 19 | bool, 20 | ubyte,byte, 21 | ushort,short, 22 | uint,int, 23 | ulong,long, 24 | float,double,real, 25 | char,wchar,dchar 26 | ) ValueTypes; 27 | 28 | // Bang, 11*16 types generated. 29 | alias staticMap!(Qualified,ValueTypes) QualifiedTypes; 30 | 31 | // If you're really a pervert (note that there will be duplicates) 32 | alias staticMap!(Qualified, QualifiedTypes) DoublyQualifiedTypes; 33 | -------------------------------------------------------------------------------- /utils/notify.d: -------------------------------------------------------------------------------- 1 | module notify; 2 | import std.conv; 3 | 4 | struct Notify(T) 5 | { 6 | alias void delegate(ref T) OnEventFunc; 7 | OnEventFunc onEvent; 8 | 9 | void init(OnEventFunc func) { 10 | onEvent = func; 11 | } 12 | 13 | string toString() 14 | { 15 | return to!string(raw); 16 | } 17 | 18 | auto opEquals(T)(T rhs) 19 | { 20 | return rhs == rhs; 21 | } 22 | 23 | void opAssign(T)(T rhs) 24 | { 25 | if (rhs == raw) 26 | return; // avoid infinite loops 27 | 28 | // temp used for ref 29 | auto temp = rhs; 30 | onEvent(temp); 31 | } 32 | 33 | auto opBinary(string op, T)(T rhs) 34 | { 35 | mixin("return raw " ~ op ~ " rhs;"); 36 | } 37 | 38 | void opOpAssign(string op, T)(T rhs) 39 | { 40 | // temp used for ref 41 | mixin("auto temp = raw " ~ op ~ " rhs;"); 42 | 43 | if (temp == raw) 44 | return; // avoid infinite loops 45 | 46 | onEvent(temp); 47 | } 48 | 49 | public T raw; // raw access when we don't want to invoke event() 50 | alias raw this; 51 | } 52 | -------------------------------------------------------------------------------- /utils/implements.d: -------------------------------------------------------------------------------- 1 | module implements; 2 | import std.typetuple; 3 | import allmembers; 4 | 5 | /** 6 | * Statically check if symbol 'a' implements interface I 7 | * (that is, if all members of I are found in members of a. 8 | */ 9 | template implements(alias a, I) if (is(I == interface)) 10 | { 11 | alias implementsImpl!(a, AllMembers!I) implements; 12 | } 13 | 14 | template implementsImpl(alias a, Items...) 15 | { 16 | static if (Items.length == 0) 17 | enum implementsImpl = true; 18 | else static if (staticIndexOf!(Items[0], AllMembers!a) == -1) 19 | enum implementsImpl = false; 20 | else 21 | enum implementsImpl = implementsImpl!(a, Items[1..$]); 22 | } 23 | 24 | interface I 25 | { 26 | int foo(int i); 27 | void foo(); 28 | 29 | string toString(); 30 | } 31 | 32 | class Bad 33 | { 34 | void foo(int i) {} 35 | } 36 | 37 | struct Good 38 | { 39 | int field; 40 | 41 | int foo(int i) { return i;} 42 | void foo() { field = 1;} 43 | 44 | string toString() { return "I'm a good struct!";} 45 | } 46 | 47 | unittest 48 | { 49 | assert( implements!(Good, I)); 50 | assert(!implements!(Bad, I)); 51 | } 52 | -------------------------------------------------------------------------------- /utils/declaration.d: -------------------------------------------------------------------------------- 1 | module declaration; 2 | 3 | template ArrayOf(T) // T is a type 4 | { 5 | alias ArrayType = T[]; 6 | alias ElementType = T; 7 | } 8 | 9 | template Transformer(From, To) // From and To are types, too 10 | { 11 | To transform(From from) 12 | { 13 | import std.conv; 14 | return to!(To)(from); 15 | } 16 | 17 | class Modificator 18 | { 19 | From f; 20 | To t; 21 | this(From f) { /*...*/ } 22 | } 23 | } 24 | 25 | template nameOf(alias a) 26 | { 27 | enum string name = a.stringof; // enum: manifest constant 28 | // determined at compile-time. 29 | // See below. 30 | } 31 | 32 | template ComplicatedOne(T, string s, alias a, bool b, int i) 33 | { /* some code using T, s, a, b and i */ } 34 | 35 | template Minimalist() {} // Zero-parameter template declaration. 36 | 37 | template OneOrMore(FirstType, Rest...) // Rest is a tuple. 38 | { /*...*/ } 39 | 40 | template ZeroOrMore(Types...) // Types is a tuple. 41 | { /*...*/ } 42 | 43 | template Multiple(T) { /*...*/ } // One arg version. 44 | template Multiple(T,U) { /*...*/ } // Two args, 45 | template Multiple(T,U,V) { /*...*/ } // and three. 46 | -------------------------------------------------------------------------------- /utils/librarytypedef.d: -------------------------------------------------------------------------------- 1 | module librarytypedef; 2 | 3 | enum Relationship 4 | { 5 | Independent, 6 | Super, 7 | Sub, 8 | Parallel, 9 | } 10 | 11 | struct Typedef( Target, 12 | Relationship relation = Relationship.Sub, 13 | Target init = Target.init, 14 | string _f = __FILE__, 15 | int _l = __LINE__ ) 16 | { 17 | Target payload = init; 18 | 19 | static if ( relation != Relationship.Independent ) 20 | this( Target value ) 21 | { 22 | payload = value; 23 | } 24 | 25 | static if ( relation == Relationship.Sub) 26 | // typedef int foo; foo f; 27 | // f.opCast!(t)() == cast(t) f 28 | Target opCast(Target)() 29 | { 30 | return payload; 31 | } 32 | 33 | static if ( relation == Relationship.Sub 34 | || relation == Relationship.Parallel ) 35 | alias payload this; 36 | 37 | static if ( relation == Relationship.Super ) 38 | typeof( this ) opAssign( Target value ) 39 | { 40 | payload = value; 41 | return this; 42 | } 43 | else static if ( relation == Relationship.Sub ) 44 | @disable void opAssign( Target value ); 45 | } 46 | -------------------------------------------------------------------------------- /utils/overloads2.d: -------------------------------------------------------------------------------- 1 | module overloads2; 2 | import std.typetuple; 3 | import makemember; 4 | 5 | /** 6 | * Gets the overloads of a given member, as a Member type tuple. 7 | */ 8 | template Overloads(alias a, string member) 9 | { 10 | // a.member is a method 11 | static if (__traits(compiles, __traits(getOverloads, a, member)) 12 | && __traits(getOverloads, a, member).length > 0) 13 | alias staticMap!(MakeNamedMember!(member), __traits(getOverloads, a, member)) 14 | Overloads; 15 | else // field or alias 16 | // a.member is a field, or a symbol alias 17 | static if (is(typeof(__traits(getMember, a, member)))) 18 | mixin( "alias Member!(\"" 19 | ~ member 20 | ~ "\", typeof(__traits(getMember, a, member))) Overloads;"); 21 | // a.member is a type alias 22 | else static if (mixin( "is(Member!(\"" 23 | ~ member 24 | ~ "\", __traits(getMember, a, member)))")) 25 | mixin( "alias Member!(\"" 26 | ~ member 27 | ~ "\", __traits(getMember, a, member)) Overloads;"); 28 | // a.member is template 29 | else 30 | mixin( "alias Member!(\"" 31 | ~ member 32 | ~ "\", void) Overloads;"); 33 | } 34 | -------------------------------------------------------------------------------- /utils/curry.d: -------------------------------------------------------------------------------- 1 | module curry; 2 | import std.traits; 3 | import checkcompatibility; 4 | 5 | struct Curry(alias fun, int index = 0) 6 | { 7 | alias ReturnType!fun RT; 8 | alias ParameterTypeTuple!fun PTT; 9 | PTT args; 10 | 11 | auto opCall(V...)(V values) 12 | if (V.length > 0 13 | && V.length + index <= PTT.length) 14 | { 15 | // Is fun directly callable with the provided arguments? 16 | static if (__traits(compiles, fun(args[0..index], values))) 17 | return fun(args[0..index], values); 18 | // If not, the new args will be stored. We check their types. 19 | else static if (!CheckCompatibility!(PTT[index..index + V.length]).With!(V)) 20 | static assert(0, "curry: bad arguments. Waited for " 21 | ~ PTT[index..index + V.length].stringof 22 | ~ " but got " ~ V.stringof); 23 | // not enough args yet. We store them. 24 | else 25 | { 26 | Curry!(fun, index+V.length) c; 27 | foreach(i,a; args[0..index]) c.args[i] = a; 28 | foreach(i,v; values) c.args[index+i] = v; 29 | return c; 30 | } 31 | } 32 | } 33 | 34 | auto curry(alias fun)() 35 | { 36 | Curry!(fun,0) c; 37 | return c; 38 | } 39 | -------------------------------------------------------------------------------- /utils/juxtaposehelper.d: -------------------------------------------------------------------------------- 1 | module juxtaposehelper; 2 | import std.traits; 3 | import functionarity; 4 | import staticscan; 5 | import maponalias; 6 | 7 | template isNotVoid(T) 8 | { 9 | enum bool isNotVoid = !is(T == void); 10 | } 11 | 12 | /** 13 | * Given a bunch of functions names, gives the typetuple of their return types. 14 | * Used by juxtapose. 15 | */ 16 | template ReturnTypes(Funs...) 17 | { 18 | alias MapOnAlias!(ReturnType, Funs) ReturnTypes; 19 | } 20 | 21 | /** 22 | * Given a bunch of functions names, gives the (flattened) typetuple 23 | * of their return values. Used by juxtapose. 24 | */ 25 | template ParameterTypeTuples(alias fun, Rest...) 26 | { 27 | alias MapOnAlias!(ParameterTypeTuple, fun, Rest) ParameterTypeTuples; 28 | } 29 | 30 | template SumOfArity(size_t zero, alias fun) 31 | { 32 | enum size_t SumOfArity = zero + arity!fun; 33 | } 34 | 35 | template SumOfArities(F...) 36 | { 37 | alias StaticScan!(SumOfArity, 0, F) SumOfArities; 38 | } 39 | 40 | template SumOfReturn(size_t zero, alias fun) 41 | { 42 | static if (is(ReturnType!fun == void)) 43 | enum size_t SumOfReturn = zero; 44 | else 45 | enum size_t SumOfReturn = zero + 1; 46 | } 47 | 48 | template SumOfReturns(Funs...) 49 | { 50 | alias StaticScan!(SumOfReturn, 0, Funs) SumOfReturns; 51 | } 52 | -------------------------------------------------------------------------------- /utils/sorttypes.d: -------------------------------------------------------------------------------- 1 | module sorttypes; 2 | import std.typecons; 3 | import staticreduce; 4 | 5 | template Max(T1, T2) 6 | { 7 | static if (T1.stringof >= T2.stringof) 8 | alias T1 Max; 9 | else 10 | alias T2 Max; 11 | } 12 | 13 | template AddToSorted(Sorted, Type) 14 | { 15 | // Length 0: already sorted 16 | static if (Sorted.Types.length == 0) 17 | alias Tuple!(Type) AddToSorted; 18 | // Smaller than the first one: put Type in first place 19 | else static if (is(Max!(Sorted.Types[0], Type) == Sorted.Types[0])) 20 | alias Tuple!(Type, Sorted.Types) AddToSorted; 21 | // Bigger than the last one: put Type at the end 22 | else static if (is(Max!(Sorted.Types[$-1], Type) == Type)) 23 | alias Tuple!(Sorted.Types, Type) AddToSorted; 24 | // Else, compare to the middle type and recurse left or right of it 25 | else static if (is(Max!(Sorted.Types[$/2], Type) == Type)) 26 | alias Tuple!(Sorted.Types[0..$/2], 27 | AddToSorted!(Tuple!(Sorted.Types[$/2..$]),Type).Types) 28 | AddToSorted; 29 | else 30 | alias Tuple!(AddToSorted!(Tuple!(Sorted.Types[0..$/2]),Type).Types, 31 | Sorted.Types[$/2..$]) 32 | AddToSorted; 33 | } 34 | 35 | template Sort(Types...) 36 | { 37 | alias staticReduce!(AddToSorted, Tuple!(), Types) Sort; 38 | } 39 | -------------------------------------------------------------------------------- /utils/verifychecks.d: -------------------------------------------------------------------------------- 1 | module verifychecks; 2 | import std.conv; 3 | import std.traits; 4 | import std.typetuple; 5 | import isanytype; 6 | import getformatters; 7 | 8 | template ArgsChecks(alias a) if (isSomeString!(typeof(a))) 9 | { 10 | mixin(getFormatters(a)); 11 | } 12 | 13 | template VerifyChecks(int which, Checks...) 14 | { 15 | template on(Args...) 16 | { 17 | static if (Checks.length != Args.length) 18 | static assert( 0 19 | , "ctwrite bad number of args: waited for " 20 | ~ to!string(Checks.length) 21 | ~ " args, got " 22 | ~ to!string(Args.length) 23 | ~ "."); 24 | else static if (Checks.length == 0) // end of process 25 | enum on = true; 26 | else static if ({ alias Checks[0] C; return C!(Args[0]);}()) // recurse 27 | enum on = VerifyChecks!(which+1, Checks[1..$]).on!(Args[1..$]); 28 | else 29 | static assert( 0 30 | , "cwrite bad arg: arg #" 31 | ~ to!string(which) 32 | ~ " of type " 33 | ~ Args[0].stringof 34 | ~ " does not verify check " 35 | ~ __traits(identifier, Checks[0])); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /utils/memoize3.d: -------------------------------------------------------------------------------- 1 | module memoize3; 2 | import memoize2; 3 | 4 | // No runtime arg -> always store 5 | Memoize!(fun, Storing.always, Discarding.all) 6 | memoize(alias fun)() 7 | { 8 | Memoize!(fun, 9 | Storing.always, 10 | Discarding.all) result; 11 | return result; 12 | } 13 | 14 | // One runtime size_t arg -> maximum store / discarding all 15 | Memoize!(fun, Storing.maximum, Discarding.all) 16 | memoize(alias fun)(size_t max) 17 | { 18 | Memoize!(fun, 19 | Storing.maximum, 20 | Discarding.all) result; 21 | result.maxNumStored = max; 22 | return result; 23 | } 24 | 25 | // Two runtime args (size_t, double) -> maximum store / discarding a fraction 26 | Memoize!(fun, Storing.maximum, Discarding.fraction) 27 | memoize(alias fun)(size_t max, double fraction) 28 | { 29 | Memoize!(fun, 30 | Storing.maximum, 31 | Discarding.fraction) result; 32 | result.maxNumStored = max; 33 | result.fraction = fraction; 34 | return result; 35 | } 36 | 37 | // One compile-time argument (discarding oldest), one runtime argument (max) 38 | Memoize!(fun, Storing.maximum, discarding) 39 | memoize(alias fun, Discarding discarding = Discarding.oldest) 40 | (size_t max) 41 | { 42 | Memoize!(fun, 43 | Storing.maximum, 44 | Discarding.oldest) result; 45 | result.maxNumStored = max; 46 | return result; 47 | } 48 | -------------------------------------------------------------------------------- /utils/alist.d: -------------------------------------------------------------------------------- 1 | module alist; 2 | import std.typetuple; 3 | import std.stdio; 4 | import half; 5 | 6 | struct AList(T...) 7 | { 8 | static if (T.length >= 2 && T.length % 2 == 0) 9 | alias Half!T Keys; 10 | else static if (T.length >= 2 && T.length % 2 == 1) 11 | alias Half!(T[0..$-1]) Keys; 12 | else 13 | alias TypeTuple!() Keys; 14 | 15 | static if (T.length >= 2) 16 | alias Half!(T[1..$]) Values; 17 | else 18 | alias TypeTuple!() Values; 19 | 20 | template at(alias a) 21 | { 22 | // key not found, but default value present 23 | static if ((staticIndexOf!(a, Keys) == -1) && (T.length % 2 == 1)) 24 | enum at = T[$-1]; // default value 25 | else static if ((staticIndexOf!(a, Keys) == -1) && (T.length % 2 == 0)) 26 | static assert(0, "AList: no key equal to " ~ a.stringof); 27 | else //static if (Keys[staticIndexOf!(a, Keys)] == a) 28 | enum at = Values[staticIndexOf!(a, Keys)]; 29 | } 30 | } 31 | 32 | void main() 33 | { 34 | alias AList!( 1, "abc" 35 | , 2, 'd' 36 | , 3, "def" 37 | , "foo", 3.14 38 | , "Default") al; 39 | 40 | writeln("Keys: ", al.Keys.stringof); 41 | writeln("Values: ", al.Values.stringof); 42 | writeln("at!1: ", al.at!(1)); 43 | writeln("at!2: ", al.at!(2)); 44 | writeln("at!\"foo\": ", al.at!("foo")); 45 | writeln("Default: ", al.at!4); 46 | } 47 | -------------------------------------------------------------------------------- /utils/instantiation.d: -------------------------------------------------------------------------------- 1 | module instantiation; 2 | import declaration; 3 | 4 | void main() 5 | { 6 | ArrayOf!(int).ArrayType myArray; 7 | 8 | // From is an alias for the type double 9 | // To for the type int 10 | alias transfo = Transformer!(double,int); 11 | 12 | struct MyStruct { /*...*/ } 13 | 14 | // "MyStruct" is a identifier -> captured by alias 15 | auto name = nameOf!(MyStruct).name; 16 | 17 | alias complicatedExample = 18 | ComplicatedOne!( int[] // a type 19 | , "Hello" // a string literal 20 | , ArrayOf // a name 21 | , true // a boolean literal 22 | , 1+2 // calculated to be the integral '3'. 23 | ); 24 | 25 | alias min1 = Minimalist!(); // No argument 26 | 27 | // FirstType is 'int' 28 | // Rest is 'double,string,"abc"' 29 | alias oneOrMore = 30 | OneOrMore!( int 31 | , double, string, "abc" 32 | ); 33 | 34 | // Types is a 1-element tuple: (int) 35 | alias zero1 = ZeroOrMore!(int); 36 | // Types is (int,double,string) 37 | alias zero2 = ZeroOrMore!(int,double,string); 38 | // Types is the empty tuple: () 39 | alias zero3 = ZeroOrMore!(); 40 | 41 | // Selects the one-arg version 42 | alias mult1 = Multiple!(int); 43 | // The three args version. 44 | alias mult2 = Multiple!(int,double,string); 45 | // Error! No 0-arg version 46 | //alias mult3 = Multiple!(); 47 | } 48 | -------------------------------------------------------------------------------- /utils/getset3.d: -------------------------------------------------------------------------------- 1 | module getset3; 2 | import std.conv; 3 | 4 | enum GetSet { no, yes} 5 | 6 | string priv(string type, string index) 7 | { 8 | return 9 | "private "~type~" value"~index~";\n" 10 | ~ type~" get"~index~"() @property { return value"~index~";}\n" 11 | ~ "void set"~index~"("~type~" _value) { value"~index~" = _value;}"; 12 | } 13 | 14 | string pub(string type, string index) 15 | { 16 | return type ~ "value" ~ index ~ ";"; 17 | } 18 | 19 | string GenerateS(GetSet getset = GetSet.no, T...)() 20 | { 21 | string result; 22 | foreach(index, Type; T) 23 | static if (getset == GetSet.yes) 24 | result ~= priv(Type.stringof, to!string(index)); 25 | else 26 | result ~= pub(Type.stringof, to!string(index)); 27 | return result; 28 | } 29 | 30 | struct S(GetSet getset = GetSet.no, T...) 31 | { 32 | mixin(GenerateS!(getset,T)); 33 | } 34 | 35 | void main() 36 | { 37 | S!(GetSet.yes, int, string, int) gs; 38 | 39 | /* Generates: 40 | struct S!(GetSet.yes, int, string, int) 41 | { 42 | private int value0; 43 | int get0() @property { return value0;} 44 | void set0(int _value) { value0 = _value;} 45 | 46 | private string value1; 47 | string get1() @property { return value1;} 48 | void set1(string _value) { value1 = _value;} 49 | 50 | private int value2; 51 | int get2() @property { return value2;} 52 | void set2(int _value) { value2 = _value;} 53 | } 54 | */ 55 | 56 | gs.set1("abc"); 57 | assert(gs.get1 == "abc"); 58 | } 59 | -------------------------------------------------------------------------------- /utils/getset.d: -------------------------------------------------------------------------------- 1 | module getset; 2 | 3 | class GetSet 4 | { 5 | private int i; 6 | private int j; 7 | private double d; 8 | private string theString; 9 | 10 | auto opDispatch(string name)() // no arg version -> getter 11 | if (name.length > 3 && name[0..3] == "get") 12 | { 13 | enum string member = name[3..$]; // "getXXX" -> "XXX" 14 | // We test if "XXX" exists here: ie if is(typeof(this.XXX)) is true 15 | static if (__traits(compiles, 16 | mixin("is(typeof(this." ~ member ~ "))"))) 17 | mixin("return " ~ member ~ ";"); 18 | else 19 | static assert(0, "GetSet Error: no member called " ~ member); 20 | } 21 | 22 | auto opDispatch(string name, Arg)(Arg arg) // setter 23 | if (name.length > 3 && name[0..3] == "set") 24 | { 25 | enum string member = name[3..$]; // "setXXX" -> "XXX" 26 | // We test if "member" can be assigned to. this.member = Arg.init 27 | static if (__traits(compiles, mixin("{" ~ member ~ " = Arg.init;}"))) 28 | { 29 | mixin(member ~ " = arg;"); 30 | mixin("return " ~ member ~ ";"); 31 | } 32 | else 33 | static assert(0, "GetSet Error: no member called" ~ member); 34 | } 35 | } 36 | 37 | unittest 38 | { 39 | auto gs = new GetSet(); 40 | gs.seti(3); 41 | auto i = gs.geti; 42 | assert(i == 3); 43 | 44 | gs.settheString("abc"); 45 | assert(gs.gettheString == "abc"); // "abc" 46 | } 47 | -------------------------------------------------------------------------------- /utils/using_flatten4.d: -------------------------------------------------------------------------------- 1 | module using_flatten4; 2 | import std.algorithm; 3 | import std.range; 4 | import std.string; 5 | import rank2; 6 | import flatten4; 7 | 8 | void main() 9 | { 10 | auto rank3 = [[[0,1,2],[3,4,5],[6] ] 11 | ,[[7],[],[8,9],[10,11]] 12 | ,[[],[12] ] 13 | ,[[13] ]]; 14 | 15 | auto rank1 = flatten(rank3); 16 | assert(rank!(typeof(rank1)) == 1); // Yup, it's a linear range 17 | assert(equal( rank1, [0,1,2,3,4,5,6,7,8,9,10,11,12,13] )); 18 | 19 | auto stillRank1 = flatten(rank1); 20 | assert(equal( stillRank1, rank1 )); // No need to insist 21 | 22 | auto text = 23 | "Sing, O goddess, the anger of Achilles son of Peleus, 24 | that brought countless ills upon the Achaeans. 25 | Many a brave soul did it send hurrying down to Hades, 26 | and many a hero did it yield a prey to dogs and vultures, 27 | for so were the counsels of Jove fulfilled 28 | from the day on which the son of Atreus, king of men, 29 | and great Achilles, first fell out with one another."; 30 | 31 | auto lines = text.splitLines; // array of strings 32 | string[][] words; 33 | foreach(line; lines) words ~= array(splitter(line, ' ')); 34 | assert( rank!(typeof(words)) == 3); // range of range of strings 35 | // range of range of array of chars 36 | auto flat = flatten(words); 37 | 38 | assert(equal(take(flat, 50), 39 | "Sing,Ogoddess,theangerofAchillessonofPeleus,thatbr")); 40 | } 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # D Template Tutorial 2 | 3 | 4 | ## What's it's about 5 | 6 | This project is about a wonderful part of the [D programming language](www.dlang.org "D Website"): templates. 7 | It contains a markdown document on templates aiming to be a kind of tutorial. 8 | 9 | It's divided in 6 chapters: 10 | 11 | * `Introduction` is just, well, the introduction text, explaining the goal of this document and the formatting conventions used. 12 | * `Basics` is about templates syntax, basic building blocks (`static if`, eponymous trick) and function, struct and class templates. 13 | * `Some More Advanced Considerations` is about more advanced ideas, like constraints, tuples or operator overloading. 14 | * `Around Templates` deals with other metaprogramming constructs interacting with templates: traits, compile-time function evaluation (CTFE) and string mixins. 15 | * `Examples` presents some more detailed examples of what can be done with D templates. 16 | * The `Appendix` gives some explanation on the `is` expression and links on other templates resources. 17 | 18 | 19 | If you find any inexactitude, plain error or missing subject, don't hesitate to open an issue on github! 20 | 21 | 22 | ## Other formats 23 | 24 | The markdown syntax used for the doc is the extended version used by Pandoc (mainly for tables or code sections). 25 | Using markdown files and [Pandoc](http://johnmacfarlane.net/pandoc/), I generate the HTML, pdf and epub versions. Feel free to comment on them also. 26 | 27 | 28 | ## Utils 29 | 30 | The `utils` folder contains a small D script to extract the hundreds of modules present in the text and test their compilation. You can also find there the extracted and tested modules. -------------------------------------------------------------------------------- /utils/filtertuple.d: -------------------------------------------------------------------------------- 1 | module filtertuple; 2 | import std.typecons; 3 | import std.typetuple; 4 | 5 | template FilterTupleTypes(alias pred, alias tup) 6 | { 7 | static if (tup.field.length) 8 | { 9 | static if (pred(tup.field[0])) 10 | alias TypeTuple!(tup.Types[0], FilterTupleTypes!(pred, tuple(tup.expand[1..$]))) 11 | FilterTupleTypes; 12 | else 13 | alias FilterTupleTypes!(pred, tuple(tup.expand[1..$])) 14 | FilterTupleTypes; 15 | } 16 | else 17 | { 18 | alias TypeTuple!() FilterTupleTypes; 19 | } 20 | 21 | } 22 | 23 | template FilterTupleIndices(alias pred, alias tup, size_t ind) 24 | { 25 | static if (tup.field.length) 26 | { 27 | static if (pred(tup.field[0])) 28 | alias TypeTuple!( ind 29 | , FilterTupleIndices!( pred 30 | , tuple(tup.expand[1..$]) 31 | , ind+1 32 | ) 33 | ) FilterTupleIndices; 34 | else 35 | alias FilterTupleIndices!( pred 36 | , tuple(tup.expand[1..$]) 37 | , ind+1 38 | ) FilterTupleIndices; 39 | } 40 | else 41 | { 42 | alias TypeTuple!() FilterTupleIndices; 43 | } 44 | 45 | } 46 | 47 | /// Filter a tuple on its values. 48 | Tuple!(FilterTupleTypes!(pred, tup)) filterTuple(alias pred, alias tup)() 49 | { 50 | FilterTupleTypes!(pred, tup) result; 51 | alias FilterTupleIndices!(pred, tup, 0) indices; 52 | foreach(i, ind; indices) 53 | { 54 | result[i] = tup.field[ind]; 55 | } 56 | return tuple(result); 57 | } 58 | -------------------------------------------------------------------------------- /utils/annotation.d: -------------------------------------------------------------------------------- 1 | module annotation; 2 | import std.typetuple; 3 | 4 | struct Meta(string Name, alias Data) 5 | { 6 | enum name = Name; 7 | alias Data data; 8 | } 9 | 10 | template isMeta(T) 11 | { 12 | static if (__traits(hasMember, T, "name") 13 | && __traits(hasMember, T, "data")) 14 | enum isMeta = true; 15 | else 16 | enum isMeta = false; 17 | } 18 | 19 | template GetName(alias a) 20 | { 21 | enum string GetName = a.name; 22 | } 23 | 24 | template isAnnotated(T) 25 | { 26 | static if (__traits(compiles, T.Annotations)) 27 | enum bool isAnnotated = true; 28 | else 29 | enum bool isAnnotated = false; 30 | } 31 | 32 | string getNames(Metadata...)() @property 33 | { 34 | alias staticMap!(GetName, Metadata) names; 35 | string result; 36 | foreach(name; names) 37 | result ~= "\""~name~"\","; 38 | if (names.length) result = result[0..$-1]; 39 | return "alias TypeTuple!(" ~ result ~ ") names;"; 40 | } 41 | 42 | struct Annotated(T, Metadata...) 43 | if (allSatisfy!(isMeta, Metadata)) 44 | { 45 | T value; 46 | alias value this; 47 | mixin(getNames!(Metadata)); 48 | Metadata metadata; 49 | 50 | auto property(string s)() @property 51 | { 52 | static if (staticIndexOf!(s, names) != -1) 53 | return metadata[staticIndexOf!(s, names)]; 54 | else 55 | static assert(false, "Unknown property: " ~ s); 56 | } 57 | 58 | bool hasAnnotation(string name) @property 59 | { 60 | foreach(n; names) 61 | if (name == n) return true; 62 | return false; 63 | } 64 | } 65 | 66 | // auto annotated(T)(T value) 67 | // { 68 | // return Annotated!(T)(value); 69 | // } 70 | 71 | template annotated(Metadata...) if (Metadata.length) 72 | { 73 | auto annotated(T)(T value) 74 | { 75 | // alias TypeTuple!(Metadata) MetaTypes; 76 | static if (isAnnotated!(T)) 77 | return Annotated!(T.AnnotatedType, T.Annotations, Metadata)(value.value); 78 | else 79 | { 80 | Annotated!(T, Metadata) a; 81 | a.value = value; 82 | return a; 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /utils/publisher.d: -------------------------------------------------------------------------------- 1 | module publisher; 2 | 3 | public mixin template PublisherMixin() 4 | { 5 | import std.functional : toDelegate; 6 | import std.stdio; 7 | 8 | alias void delegate(Object sender, string event) CallBack; 9 | alias void function(Object sender, string event) CallBackFun; 10 | 11 | 12 | bool[CallBack] callBacks; // int[0][CallBack] may be even smaller 13 | 14 | //Register subscriber 15 | void register(CallBack callBack) 16 | { 17 | // Ensure subscriber is not yet registered. 18 | if (callBack in callBacks) 19 | writeln("Subscriber is already registered."); 20 | else 21 | callBacks[callBack] = true; //from; 22 | } 23 | 24 | // Register Subscriber via function ptr. 25 | void register(CallBackFun callBackFun) 26 | { 27 | register( toDelegate(callBackFun) ); 28 | } 29 | 30 | // Remove Subscriber 31 | void unRegister(CallBack callBack) 32 | { 33 | if (callBack in callBacks) 34 | callBacks.remove(callBack); 35 | else 36 | writeln("Trying to remove an unknown callback."); 37 | } 38 | 39 | // Remove Subscriber via function ptr. 40 | void unRegister(CallBackFun callBackFun) 41 | { 42 | unRegister(toDelegate(callBackFun)); 43 | } 44 | 45 | // Notify ALL Subscribers 46 | void notify(Object from, string evt) 47 | { 48 | foreach ( CallBack cb, bool origin ; callBacks ) 49 | { 50 | cb( from, evt ); 51 | } 52 | } 53 | } 54 | 55 | mixin template StackMixin() 56 | { 57 | // get parent type 58 | alias typeof(this) Me; 59 | static Me[] stack; 60 | 61 | protected: 62 | 63 | @property bool empty() { return stack.length == 0; } 64 | @property size_t count() { return stack.length; } 65 | 66 | void push(Me element) 67 | { 68 | stack ~= element; 69 | } 70 | 71 | Me pop() 72 | { 73 | Me el = peek(); 74 | stack.length -= 1; 75 | return el; 76 | } 77 | 78 | Me peek() 79 | { 80 | if ( stack.length == 0 ) 81 | throw new Exception("peek on an empty statck."); 82 | 83 | Me el = stack[stack.length-1]; 84 | return el; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # TODO 2 | 3 | ## Document 4 | 5 | * Update `utils/codesamples.d` to extract the modules from the markdown master file. 6 | It fitlers the .tex files right now, this should be changed. 7 | 8 | ## New topics 9 | 10 | These are the changes for templates in 2012-2013, that should be added to the tutorial: 11 | 12 | So, here is my own small list: 13 | 14 | * is(Type name = A!(Args), Args...) now exists. The Args... part is new. 15 | * the new (a,b) => a+b syntax was introduced 16 | * the eponymous trick works even when other non-eponymous members are defined 17 | * error reporting got better 18 | * CTFE got better. 19 | * auto ref? 20 | * __ctfe. I think it arrived just when I wrote the doc. I've now used it and it works great! 21 | * UFCS: not a template feature per se, but quite useful in conjunction with templates. 22 | * UDA. ditto, except I know zilch about them. But, type & value manipulation at compile-time, them I know. 23 | * __LINE__ and __FILE__ are described on dlang.org. Link it. 24 | * the isPOD __traits 25 | * Now there is a way to peek at function parameter identifiers (!): http://dlang.org/phobos/std_traits.html#.ParameterIdentifierTuple 26 | * Some goodies I might forgot in std.traits, it's worth revisiting 27 | 28 | ## New subjects: 29 | 30 | * juxtaposing functions, 31 | * mapping n ranges in parallel, 32 | * Generating random values, whatever the type, 33 | * grouping functions, 34 | * a simple compile-time state machine? (to parse something, for example) 35 | 36 | 37 | ## Miscellaneous 38 | 39 | From the D mailing lists, related to templates (to be put somewhere in the text): 40 | 41 | "You can't use methods (delegates) for template parameters, because they need a context, which is not known at compile-time." 42 | 43 | "If exactly one of two equally good matched functions is a templated one, the other one is chosen. Now that you have templated the second function, both are an equally good match and both are templated." 44 | 45 | "When you put a unittest inside the definition of a class/struct, it gets run for every instantiation of said class, and has access to "T". This is good for writing generic tests for the current T type. This can be useful to test things that depend on T, such as making sure some functions are indeed safe, or whatnot." (monarch_dodra) -------------------------------------------------------------------------------- /utils/inheritanceexample.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Timon Gehr timon.gehr@gmx.ch via puremagic.com 3 | */ 4 | module inheritanceexample; 5 | 6 | import std.stdio; 7 | 8 | abstract class Cell(T) 9 | { 10 | abstract void set(T value); 11 | abstract const(T) get(); 12 | private: 13 | T field; 14 | } 15 | 16 | class AddSetter(C: Cell!T,T): C 17 | { 18 | override void set(T value){field = value;} 19 | } 20 | 21 | class AddGetter(C: Cell!T,T): C 22 | { 23 | override const(T) get(){return field;} 24 | } 25 | 26 | class DoubleCell(C: Cell!T,T): C 27 | { 28 | override void set(T value){super.set(2*value);} 29 | } 30 | 31 | class OneUpCell(C: Cell!T,T): C 32 | { 33 | override void set(T value){super.set(value+1);} 34 | } 35 | 36 | class SetterLogger(C:Cell!T,T): C 37 | { 38 | override void set(T value) 39 | { 40 | super.set(value); 41 | writeln("cell has been set to '",value,"'!"); 42 | } 43 | } 44 | 45 | class GetterLogger(C:Cell!T,T): C 46 | { 47 | override const(T) get() 48 | { 49 | auto value = super.get(); 50 | writeln("'",value,"' has been retrieved!"); 51 | return value; 52 | } 53 | } 54 | 55 | // ConcreteCell has a 'true' getter and a 'true' setter 56 | class ConcreteCell(T): AddGetter!(AddSetter!(Cell!T)){} 57 | 58 | // OneUpDoubleSetter has a setter that adds 1 to the stored value 59 | // and then doubles it 60 | class OneUpDoubleSetter(T): OneUpCell!(DoubleCell!(AddSetter!(Cell!T))){} 61 | 62 | // doubleOneUpSetter has a setter that doubles the stored value and add 1 63 | class DoubleOneUpSetter(T): DoubleCell!(OneUpCell!(AddSetter!(Cell!T))){} 64 | 65 | void main() 66 | { 67 | Cell!string x; 68 | x = new ConcreteCell!string; 69 | x.set("hello"); 70 | writeln(x.get()); 71 | 72 | Cell!int y; 73 | y = new SetterLogger!(ConcreteCell!int); 74 | y.set(123); // prints: "cell has been set to '123'! 75 | 76 | y = new GetterLogger!(DoubleCell!(ConcreteCell!int)); 77 | y.set(1234); 78 | y.get(); // prints "'2468' has been retrieved!" 79 | 80 | y = new AddGetter!(OneUpDoubleSetter!int); 81 | y.set(100); 82 | writeln(y.get()); // prints "202" 83 | y = new AddGetter!(DoubleOneUpSetter!int); 84 | y.set(100); 85 | writeln(y.get()); // prints "201" 86 | } 87 | -------------------------------------------------------------------------------- /utils/getformatters.d: -------------------------------------------------------------------------------- 1 | module getformatters; 2 | import std.conv; 3 | import std.traits; 4 | 5 | string getFormatters(S)(S s) if (isSomeString!S) 6 | { 7 | dstring ds = to!dstring(s); 8 | bool afterPercent = false; 9 | bool error; 10 | string result = "alias TypeTuple!("; 11 | foreach(elem; ds) 12 | { 13 | if (error) break; 14 | if (afterPercent) 15 | { 16 | switch (elem) 17 | { 18 | case '%': 19 | afterPercent = false; 20 | break; 21 | case 'd': 22 | case 'i': 23 | result ~= "isIntegral,"; // integers 24 | afterPercent = false; 25 | break; 26 | case 'u': 27 | case 'x': 28 | case 'X': 29 | case 'o': 30 | result ~= "isUnsigned,"; // unsigned integral 31 | afterPercent = false; 32 | break; 33 | case 'f': 34 | case 'F': 35 | case 'e': 36 | case 'E': 37 | case 'g': 38 | case 'G': 39 | result ~= "isFloatingPoint,"; // floating point 40 | afterPercent = false; 41 | break; 42 | case 'c': 43 | result ~= "isSomeChar,"; // char 44 | afterPercent = false; 45 | break; 46 | case 's': 47 | result ~= "isAnyType,"; // any string-convertible type 48 | afterPercent = false; 49 | break; 50 | /* flags, width, */ 51 | case '+': 52 | case '-': 53 | case '#': 54 | case '.': 55 | case ' ': 56 | case '0': 57 | .. 58 | case '9': 59 | break; 60 | default: 61 | error = true; // Error! 62 | break; 63 | } 64 | } 65 | else 66 | { 67 | if (elem == '%') afterPercent = true; 68 | } 69 | } 70 | 71 | // Get rid of the last comma: 72 | if (result.length > 17) result = result[0..$-1]; 73 | // finishing the alias code 74 | result ~= ") ArgsChecks;"; 75 | 76 | if (afterPercent // finished the string but still in "afterPercent" mode 77 | || error) 78 | result = "static assert(0, \"Bad format string: \" ~ a);"; 79 | 80 | return result; 81 | } 82 | -------------------------------------------------------------------------------- /utils/memoize2.d: -------------------------------------------------------------------------------- 1 | module memoize2; 2 | import std.traits; 3 | import std.typecons; 4 | 5 | enum Storing { 6 | always, // there is no tomorrow 7 | maximum // sustainable growth 8 | } 9 | 10 | enum Discarding { 11 | oldest, // only discard the oldest result 12 | fraction, // discard a fraction (0.5 == 50%) 13 | all // burn, burn! 14 | } 15 | 16 | struct Memoize(alias fun, 17 | Storing storing, 18 | Discarding discarding) 19 | { 20 | alias ReturnType!fun RT; 21 | alias ParameterTypeTuple!fun PTT; 22 | 23 | static if (storing == Storing.maximum) 24 | { 25 | Tuple!(PTT)[] argsQueue; 26 | size_t maxNumStored; 27 | } 28 | 29 | static if (discarding == Discarding.fraction) 30 | float fraction; 31 | 32 | RT[Tuple!(PTT)] memo; // stores the result, indexed by arguments. 33 | 34 | RT opCall(PTT args) 35 | { 36 | if (tuple(args) in memo) // Have we already seen these args? 37 | { 38 | return memo[tuple(args)]; // if yes, use the stored result 39 | } 40 | else // if not, 41 | { 42 | static if (storing == Storing.always) 43 | { 44 | RT result = fun(args);// compute the result and store it. 45 | memo[tuple(args)] = result; 46 | return result; 47 | } 48 | else // Storing.maximum 49 | { 50 | if (argsQueue.length >= maxNumStored) 51 | { 52 | static if (discarding == Discarding.oldest) 53 | { 54 | memo.remove(argsQueue[0]); 55 | argsQueue = argsQueue[1..$]; 56 | } 57 | else static if (discarding == Discarding.fraction) 58 | { 59 | auto num = to!size_t(argsQueue.length * fraction); 60 | foreach(elem; argsQueue[0..num]) 61 | memo.remove(elem); 62 | argsQueue = argsQueue[num..$]; 63 | } 64 | else static if (discarding == Discarding.all) 65 | { 66 | memo = null; 67 | argsQueue.length = 0; 68 | } 69 | } 70 | 71 | RT result = fun(args);// compute the result and store it. 72 | memo[tuple(args)] = result; 73 | argsQueue ~= tuple(args); 74 | return result; 75 | } 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /utils/friends.d: -------------------------------------------------------------------------------- 1 | module friends; 2 | import std.stdio; 3 | import publisher; 4 | 5 | class FriendStack 6 | { 7 | private string name; 8 | private int age; 9 | 10 | // Our Mixins 11 | mixin StackMixin; 12 | mixin PublisherMixin; 13 | 14 | void pushFriend(string name, int age) 15 | { 16 | // Create new instance for the Stack. 17 | auto person = new FriendStack(); 18 | person.name = name; 19 | person.age = age; 20 | 21 | push(person); 22 | 23 | // Notify all subscribers 24 | notify(person, "Push"); 25 | } 26 | 27 | //Pop 28 | void popFriend() 29 | { 30 | auto person = pop(); 31 | notify( person, "Pop"); 32 | } 33 | 34 | // Subscriber method 35 | void inHouseInfo(Object sender, string msg) 36 | { 37 | auto p = cast(FriendStack)sender; 38 | writefln("Subscriber: in House , Name: %s, Age: %s, Message: %s \n", 39 | p.name, p.age, msg); 40 | } 41 | } 42 | 43 | class ExtFriendStack : FriendStack // our VIPs 44 | { 45 | private bool isDeveloper; 46 | 47 | // Push 48 | void pushFriend(string name, int age, bool D) 49 | { 50 | // Create new instance for the Stack. 51 | auto xperson = new ExtFriendStack(); 52 | xperson.name = name; 53 | xperson.age = age; 54 | xperson.isDeveloper = D; 55 | 56 | push(xperson); 57 | 58 | // Notify all subscribers 59 | notify(xperson, "Push"); 60 | } 61 | } 62 | 63 | /** 64 | * 65 | * FRIENDSTACK Subscriber functions - Used by FriendStack AND ExtFriendStack. 66 | */ 67 | void twitter(Object sender, string msg) 68 | { 69 | auto p = cast(FriendStack)sender; 70 | writefln("Subscriber: Twitter, Name: %s, Age: %s, Message: %s \n", 71 | p.name, p.age, msg); 72 | } 73 | 74 | void reddit(Object sender, string msg) 75 | { 76 | auto p = cast(FriendStack)sender; 77 | writefln("Subscriber: Reddit, Name: %s, Age: %s, Message: %s \n", 78 | p.name, p.age, msg); 79 | } 80 | 81 | void mail(Object sender, string msg) 82 | { 83 | auto p = cast(FriendStack)sender; 84 | writefln("Subscriber: eMail, Name: %s, Age: %s, Message: %s \n", 85 | p.name, p.age, msg); 86 | } 87 | 88 | /** 89 | * 90 | * EXTENDED FRIENDSTACK Subscriber functions 91 | * contains additional --isDeveloper-- information. 92 | */ 93 | void blog(Object sender, string msg) 94 | { 95 | if ( cast(ExtFriendStack)sender ) 96 | { 97 | auto p = cast(ExtFriendStack)sender; 98 | writefln("Subscriber: Blog, Name: %s, Age: %s, Is Developer ?: %s, Message: %s \n", 99 | p.name, p.age, p.isDeveloper, msg); 100 | } 101 | else 102 | { 103 | writeln("----- Blog is for VIPs only ------ Message rooted to email"); 104 | mail(sender, msg); 105 | 106 | // Downcast is also possible 107 | //auto p = cast(FriendStack)sender; 108 | //writefln("Subscriber: Blog, Name: %s, Age: %s, Message: %s \n", 109 | // p.name, p.age, msg); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /utils/relational.d: -------------------------------------------------------------------------------- 1 | module relational; 2 | import std.traits; 3 | import std.typetuple; 4 | import std.typecons; 5 | import std.range; 6 | import std.conv; 7 | import isastringliteral; 8 | import istype; 9 | import half; 10 | import interleave; 11 | 12 | struct Entry(Data...) 13 | if ( (Data.length % 2 == 0) 14 | && (allSatisfy!(isAStringLiteral, Half!Data)) 15 | && (allSatisfy!(isType, Half!(Data[1..$], void)))) 16 | { 17 | alias Half!Data Headers; 18 | alias Half!(Data[1..$], void) Values; 19 | alias data this; 20 | 21 | Tuple!(Interleave!(Values).With!(Headers)) data; 22 | 23 | this(Values values) 24 | { 25 | foreach(i, Unused; Values) data[i] = values[i]; 26 | } 27 | 28 | string toString() @property 29 | { 30 | string s = "["; 31 | foreach(i, Unused; Values) 32 | s ~= Headers[i] ~ ":" ~ to!string(data[i]) ~ ", "; 33 | return s[0..$-2] ~ "]"; 34 | } 35 | } 36 | 37 | template entry(Headers...) 38 | if (allSatisfy!(isAStringLiteral, Headers)) 39 | { 40 | Entry!(Interleave!(Headers).With!(Values)) entry(Values...)(Values values) 41 | if (Values.length == Headers.length) 42 | { 43 | return typeof(return)(values); 44 | } 45 | } 46 | 47 | template isEntry(E) 48 | { 49 | enum isEntry = __traits(compiles, 50 | { 51 | void fun(T...)(Entry!T e) {} 52 | fun(E.init); 53 | }); 54 | } 55 | 56 | auto rename(string from, string to, E)(E e) 57 | if (isEntry!E) 58 | { 59 | enum index = staticIndexOf!(from, E.Headers); 60 | static if (index == -1) 61 | static assert(false, "Bad index in rename: no header called " 62 | ~ from ~ " in " ~ E.Headers.stringof); 63 | else 64 | return entry!(E.Headers[0..index], 65 | to, 66 | E.Headers[index+1..$])(e.data.expand); 67 | } 68 | 69 | auto rename(string from, string to, D)(D db) 70 | if (isDatabase!D) 71 | { 72 | ReturnType!(rename!(from, to, ElementType!D))[] result; 73 | foreach(i, elem; db) 74 | result ~= rename!(from, to)(elem); 75 | return result; 76 | } 77 | 78 | 79 | template isDatabase(D) 80 | { 81 | static if (isDynamicArray!D && isEntry!(ElementType!D)) 82 | enum bool isDatabase = true; 83 | else 84 | enum bool isDatabase = false; 85 | } 86 | 87 | template isSomeHeader(E) 88 | if (isEntry!E) 89 | { 90 | template isSomeHeader(string s) 91 | { 92 | static if (staticIndexOf!(s, E.Headers) != -1) 93 | enum bool isSomeHeader = true; 94 | else 95 | enum bool isSomeHeader = false; 96 | } 97 | } 98 | 99 | template HeaderValue(E) 100 | if (isEntry!E) 101 | { 102 | template HeaderValue(string header) 103 | if (staticIndexOf!(header, E.Headers) != -1) 104 | { 105 | alias TypeTuple!(header, E.Values[staticIndexOf!(header, E.Headers)]) 106 | HeaderValue; 107 | } 108 | } 109 | 110 | template project(Headers...) 111 | if (Headers.length > 0) 112 | { 113 | auto project(E)(E e) 114 | { 115 | static if (isEntry!E && allSatisfy!(isSomeHeader!E, Headers)) 116 | { 117 | alias staticMap!(HeaderValue!E, Headers) 118 | HeadersAndValues; 119 | Entry!(HeadersAndValues) result; 120 | foreach(i, Unused; Headers) 121 | mixin("result." ~ Headers[i] ~ " = e." ~ Headers[i] ~ ";"); 122 | return result; 123 | } 124 | else static if (isDatabase!E 125 | && allSatisfy!(isSomeHeader!(ElementType!E), Headers)) 126 | { 127 | alias staticMap!(HeaderValue!(ElementType!E), Headers) 128 | HeadersAndValues; 129 | 130 | Entry!(HeadersAndValues)[] result; 131 | Entry!(HeadersAndValues) elem; 132 | 133 | foreach(i,Unused; e) 134 | { 135 | foreach(j, Unused2; Headers) 136 | mixin("elem." ~ Headers[j] ~ " = e[i]." ~ Headers[j] ~ ";"); 137 | result ~= elem; 138 | } 139 | return result; 140 | } 141 | else 142 | static assert(0, "Cannot project on " ~ Headers.stringof[5..$] 143 | ~ " for type " ~ E.stringof); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /utils/codesamples.d: -------------------------------------------------------------------------------- 1 | /** 2 | Extract D code samples from the md file. 3 | 4 | Usage: ./codesamples.d D-templates-tutorial.md 5 | */ 6 | module codesamples; 7 | 8 | import std.algorithm: startsWith, endsWith; 9 | //import std.array; 10 | import std.conv: to; 11 | import std.exception; 12 | //import std.file; 13 | //import std.format; 14 | //import std.path; 15 | import std.process: system; 16 | import std.stdio; 17 | //import std.range; 18 | import std.regex: regex, match; 19 | 20 | void main(string[] args) 21 | { 22 | immutable string samplesDir = "code"; 23 | enum modName = regex("module (.+?);"); 24 | enforce(args.length == 2, "Need an input file name."); 25 | string fileName = args[1]; 26 | //if (!exists(samplesDir)) mkdir(samplesDir); 27 | auto compilationResults = File("results.txt", "w"); 28 | auto inputFile = File(fileName,"r"); 29 | 30 | string[] fileNames; 31 | string[][string] sampleNames; 32 | bool[string] gotMain; 33 | 34 | bool inCode; 35 | string accumulator; 36 | string sampleName; 37 | int anonymousSamples; 38 | writeln("Scanning ", inputFile, "..."); 39 | foreach(line; inputFile.byLine) // KeepTerminator.yes doesn't work? 40 | { 41 | if (line.startsWith("```{.d")) 42 | { 43 | inCode = true; 44 | continue; 45 | } 46 | 47 | if (inCode && line.startsWith("module ")) 48 | { 49 | auto m = match(line, modName); 50 | sampleName = to!string(m.captures[1]); 51 | } 52 | 53 | if (inCode && line.startsWith("void main()") && sampleName != "") 54 | gotMain[sampleName~".d"] = true; 55 | 56 | if (inCode && line.startsWith("```")) 57 | { 58 | if (sampleName.length) 59 | { 60 | File sampleFile = File(sampleName ~ ".d", "w"); 61 | sampleFile.write(accumulator); 62 | sampleFile.close(); 63 | sampleNames[fileName] ~= (sampleName~".d"); 64 | if ((sampleName~".d") !in gotMain) 65 | gotMain[sampleName~".d"] = false; 66 | } 67 | else 68 | { 69 | anonymousSamples++; 70 | } 71 | 72 | inCode = false; 73 | accumulator = ""; 74 | sampleName = ""; 75 | } 76 | 77 | if (inCode) accumulator ~= line ~ "\n"; 78 | } 79 | size_t named = sampleNames[fileName].length; 80 | writeln("Scanning done. ", named, " named samples found. ", anonymousSamples, " anonymous samples found."); 81 | 82 | // Now we have all samples extracted from all files. Let's compile them. 83 | writeln("Attempting global compilation round."); 84 | int success; 85 | compilationResults.write("\n************", fileName, " **************************\n"); 86 | compilationResults.write("Found " ~ to!string(named) ~ " named samples.\n"); 87 | 88 | foreach(sample; sampleNames[fileName]) 89 | { 90 | write("Compiling ", sample, "... "); 91 | int compilationResult; 92 | 93 | if (sample in gotMain && gotMain[sample]) //got main 94 | { 95 | compilationResult = system("rdmd -w -wi " ~ sample); 96 | } 97 | else 98 | { 99 | compilationResult = system("rdmd --main -w -wi " ~ sample); 100 | } 101 | 102 | if (compilationResult == 0) // success 103 | { 104 | if (!sample.endsWith("_error.d")) 105 | { 106 | writeln("OK."); 107 | compilationResults.write(sample ~ ": OK\n"); 108 | ++success; 109 | } 110 | else 111 | { 112 | writeln("*** ERROR *** (compiled OK, but should fail)."); 113 | compilationResults.write(sample ~ ": *** ERROR *** (compiled OK, but should fail)\n"); 114 | } 115 | } 116 | else // failure 117 | { 118 | if (sample.endsWith("_error.d")) 119 | { 120 | writeln("OK (fail as expected)."); 121 | compilationResults.write(sample ~ ": OK (fail as expected).\n"); 122 | ++success; 123 | } 124 | else 125 | { 126 | writeln("*** ERROR! ***"); 127 | compilationResults.write(sample ~ ": *** ERROR! ***\n"); 128 | } 129 | } 130 | } 131 | 132 | writeln("Successful compilation for " ~ to!string(success) ~ " / " ~ to!string(named)); 133 | compilationResults.write("\n"); 134 | compilationResults.write("Successful compilation for " ~ to!string(success) ~ " / " ~ to!string(named) ~ "\n"); 135 | compilationResults.write("\n"); 136 | compilationResults.write("Found " ~ to!string(anonymousSamples) ~ " anonymous samples (no compilation attempted).\n"); 137 | compilationResults.write("Total of " ~ to!string(anonymousSamples+named) ~ " samples found.\n"); 138 | compilationResults.write("********************************************************\n\n"); 139 | 140 | } -------------------------------------------------------------------------------- /utils/results.txt: -------------------------------------------------------------------------------- 1 | 2 | ************../D-templates-tutorial.md ************************** 3 | Found 208 named samples. 4 | intro.d: OK 5 | basicTree1.d: OK 6 | usingBasicTree1.d: OK 7 | basicTree2.d: OK 8 | genericTree.d: OK 9 | declaration.d: OK 10 | instantiation.d: OK 11 | internaldeclarations1.d: OK 12 | internaldeclarations2.d: OK 13 | differentinstantiations.d: OK 14 | pair.d: OK 15 | nameof1.d: OK 16 | record.d: OK 17 | using_record.d: OK 18 | allarrays.d: OK 19 | isdynamicarray.d: OK 20 | selector.d: OK 21 | rank1.d: OK 22 | using_rank1.d: OK 23 | rank2.d: OK 24 | baseelementtype.d: OK 25 | ndim.d: OK 26 | using_ndim.d: OK 27 | using_power.d: OK 28 | repeatedcomposition.d: OK 29 | specialization1.d: OK 30 | specialization2.d: OK 31 | def.d: OK 32 | deduced.d: OK 33 | function_declaration1.d: OK 34 | function_declaration2.d: OK 35 | morph.d: OK 36 | ifti.d: OK 37 | using_flatten1.d: OK 38 | flatten1.d: OK 39 | anonymous_function1.d: OK 40 | anonymous_function2.d: OK 41 | calltwice.d: OK 42 | using_calltwice.d: OK 43 | makecounter.d: OK 44 | using_makecounter.d: OK 45 | storage.d: OK 46 | init.d: OK 47 | inoutclauses.d: OK 48 | acceptingtuple.d: OK 49 | nmap.d: OK 50 | nmap2.d: OK 51 | nfilter.d: OK 52 | tree1.d: OK 53 | using_tree.d: OK 54 | heap1.d: OK 55 | tree2.d: OK 56 | tree3.d: OK 57 | tree4.d: OK 58 | using_tree4.d: OK 59 | tree5.d: OK 60 | summingtree.d: OK 61 | inordertree.d: OK 62 | templatedconstructors.d: OK 63 | holder.d: OK 64 | heap2.d: OK 65 | anonymous_error.d: OK (fail as expected). 66 | innerconcatenate.d: OK 67 | templatedinner.d: OK 68 | flatten2.d: OK 69 | flatten3.d: OK 70 | flatten4.d: OK 71 | using_flatten4.d: OK 72 | classsyntax1.d: OK 73 | classsyntax2.d: OK 74 | classsyntax3.d: OK 75 | classinvariant.d: OK 76 | anonymousclass.d: OK 77 | parametrizedbaseclass.d: OK 78 | serializetemplate.d: OK 79 | inheritanceexample.d: OK 80 | crtp.d: OK 81 | interfacesyntax.d: OK 82 | unionsyntax.d: OK 83 | enumsyntax.d: OK 84 | constrained.d: OK 85 | constraintsyntax.d: OK 86 | ctvalue.d: OK 87 | rangewrapper.d: OK 88 | constraints_error.d: OK (fail as expected). 89 | isserializable.d: OK 90 | hasarithmeticoperations.d: OK 91 | dropfront.d: OK 92 | tupledemonstration.d: OK 93 | ttflatten.d: OK 94 | ttiteration.d: OK 95 | emptytuple.d: OK 96 | variadic.d: OK 97 | popallfronts.d: OK 98 | areallranges.d: OK 99 | nameof2.d: OK 100 | nameof3.d: OK 101 | interfacelist.d: OK 102 | eliminate.d: OK 103 | noduplicates.d: OK 104 | superlist.d: OK 105 | checkedinheritance.d: OK 106 | number.d: OK 107 | mixinconcatenate.d: OK 108 | usingmixinconcatenate.d: OK 109 | publisher.d: OK 110 | friends.d: OK 111 | usingfriends.d: OK 112 | dispatcher.d: OK 113 | getset.d: OK 114 | transp.d: OK 115 | usingtransparent.d: OK 116 | transp2.d: OK 117 | descriptor.d: OK 118 | librarytypedef.d: OK 119 | compare.d: OK 120 | usingtuple.d: OK 121 | usingnamedtuple.d: OK 122 | isastringliteral.d: OK 123 | namedtuple.d: OK 124 | filelinetagging.d: OK 125 | usingunique.d: OK 126 | debugger.d: OK 127 | usingmystruct1.d: OK 128 | mystruct1.d: OK 129 | mystruct2.d: OK 130 | usingmystruct2.d: OK 131 | mystruct3.d: OK 132 | getset2.d: OK 133 | getset3.d: OK 134 | stringinterpolation.d: OK 135 | sortingnetwork.d: OK 136 | buildsortingcode.d: OK 137 | networksort.d: OK 138 | nameof.d: OK 139 | usingallmembers1.d: OK 140 | allmemberstemplate.d: OK 141 | allmemberstemplate2.d: OK 142 | templateintrospection.d: OK 143 | allmembersmodule.d: OK 144 | member.d: OK 145 | makemember.d: OK 146 | overloads1.d: OK 147 | myclass.d: OK 148 | usingoverloads1.d: OK 149 | overloads2.d: OK 150 | allmembers.d: OK 151 | usingallmembers2.d: OK 152 | implements.d: OK 153 | cclass.d: OK 154 | parent.d: OK 155 | qualifiedname.d: OK 156 | usingqualifiedname.d: OK 157 | scopename.d: OK 158 | usingscopename.d: *** ERROR! *** 159 | staticmap.d: OK 160 | qualified.d: OK 161 | tester.d: OK 162 | staticfilter.d: OK 163 | usingstaticfilter1.d: OK 164 | istype.d: OK 165 | isbuiltintype.d: OK 166 | usingstaticfilter2.d: OK 167 | staticreduce.d: OK 168 | maxtemplate.d: OK 169 | usingmax.d: OK 170 | variant_error.d: OK (fail as expected). 171 | sorttypes.d: OK 172 | sortingtypes.d: OK 173 | staticscan.d: OK 174 | interleave.d: OK 175 | annotation.d: OK 176 | maptuple.d: OK 177 | filtertuple.d: OK 178 | functionarity.d: OK 179 | memoize1.d: OK 180 | usingmemoize1.d: OK 181 | memoize2.d: OK 182 | memoize3.d: OK 183 | checkcompatibility.d: OK 184 | curry.d: OK 185 | juxtapose.d: OK 186 | juxtaposehelper.d: OK 187 | maponalias.d: OK 188 | relational.d: OK 189 | half.d: OK 190 | usingrelational.d: OK 191 | fields.d: OK 192 | usingfields.d: OK 193 | notify.d: OK 194 | usingnotify.d: OK 195 | fieldsof.d: OK 196 | enumdefasstring.d: OK 197 | extendenum.d: OK 198 | staticswitch.d: OK 199 | gobbler.d: OK 200 | usinggobbler.d: OK 201 | alist.d: OK 202 | isanytype.d: OK 203 | usingcheckedwrite.d: OK 204 | getformatters.d: OK 205 | verifychecks.d: OK 206 | checkedwrite.d: OK 207 | forwarder.d: OK 208 | canbeinstantiated.d: OK 209 | validcall.d: OK 210 | istuple.d: OK 211 | maker.d: OK 212 | 213 | Successful compilation for 207 / 208 214 | 215 | Found 100 anonymous samples (no compilation attempted). 216 | Total of 308 samples found. 217 | ******************************************************** 218 | 219 | --------------------------------------------------------------------------------