1 /*******************************************************************************
2 
3     Templates to define types with modified qualifiers based on some input
4     types.
5 
6     Many of helper templates here have been added because of D1 to D2 migration
7     to hide behind them qualifiers not supported in D1 (const, immutable,
8     inout). Others, like `Unqual`, are generally useful even outside of
9     migration context.
10 
11     NB: because this module is often used as purely compile-time dependency it
12         used built-in asserts instead of `ocean.core.Test` to reduce amount of
13         cyclic imports. `ocean.meta` modules in general are not supposed to
14         import anything outside of `ocean.meta`.
15 
16     Copyright:
17         Copyright (C) 2017 dunnhumby Germany GmbH. All rights reserved.
18 
19     License:
20         Boost Software License Version 1.0. See LICENSE_BOOST.txt for details.
21         Alternatively, this file may be distributed under the terms of the Tango
22         3-Clause BSD License (see LICENSE_BSD.txt for details).
23 
24 *******************************************************************************/
25 
26 module ocean.meta.types.Qualifiers;
27 
28 /*******************************************************************************
29 
30     Convenience string type aliases.
31 
32     Initially defined to help with D2 migration but proved themselves as useful
33     shortcuts to reduce visual code clutter.
34 
35 *******************************************************************************/
36 
37 alias Immut!(char)[] istring;
38 alias Const!(char)[] cstring;
39 alias char[]         mstring;
40 
41 /*******************************************************************************
42 
43     Helper template to be used instead of plain types in function parameter
44     list when one will need to be const-qualified in D2 world - usually this is
45     necessary if function needs to handle string literals.
46 
47     This should be used instead of istring/cstring aliases in generic array
48     processing functions as opposed to string-specific code.
49 
50     Example:
51 
52     ---
53     void foo(Element)(Const!(Element)[] buf)
54     {
55     }
56 
57     foo!(char)("aaa"); // will work in both D1 and D2
58     ---
59 
60 *******************************************************************************/
61 
62 template Const(T)
63 {
64     alias const(T) Const;;
65 }
66 
67 unittest
68 {
69     alias Const!(int[]) Int;
70 
71     static assert (is(Int));
72 
73     static assert (is(Int == const));
74 }
75 
76 /*******************************************************************************
77 
78     Same as Const!(T) but for immutable
79 
80     Example:
81 
82     ---
83     Immut!(char)[] foo()
84     {
85         return "aaa"; // ok, immutable
86         return new char[]; // error, mutable
87     }
88     ---
89 
90 *******************************************************************************/
91 
92 template Immut(T)
93 {
94     alias immutable(T) Immut;
95 }
96 
97 unittest
98 {
99     alias Immut!(int[]) Int;
100 
101     static assert (is(Int));
102 
103     static assert (is(Int == immutable));
104 }
105 
106 /*******************************************************************************
107 
108     Same as Const!(T) but for inout
109 
110     Example:
111 
112     ---
113     Inout!(char[]) foo(Inout!(char[]) arg)
114     {
115         return arg;
116     }
117 
118     mstring = foo("aaa"); // error
119     istring = foo("aaa"); // ok
120     mstring = foo("aaa".dup); // ok
121     ---
122 
123 *******************************************************************************/
124 
125 template Inout(T)
126 {
127     alias inout(T) Inout;
128 }
129 
130 unittest
131 {
132     alias Inout!(char[]) Str;
133 
134     Str foo ( Str arg ) { return arg; }
135 
136     char[] s1 = foo("aaa".dup);
137     Immut!(char)[] s2 = foo("aaa");
138 }
139 
140 /*******************************************************************************
141 
142     In D1 does nothing. In D2 strips top-most type qualifier.
143 
144     This is a small helper useful for adapting templated code where template
145     parameter can possibly be deduced as const or immutable. Using this type
146     directly in implementation will result in unmodifiable variables which isn't
147     always wanted.
148 
149     Example:
150 
151     ---
152     void foo(Element)(Element[] buf)
153     {
154         // this causes an error with D2 if element
155         // gets deduced as const
156         Element tmp;
157         tmp = Element.init;
158 
159         // this is ok in both d1 and D2
160         Unqual!(Element) tmp;
161         tmp = Element.init;
162     }
163     ---
164 
165 *******************************************************************************/
166 
167 template Unqual(T)
168 {
169     static if (is(T U == const U))
170     {
171         alias U Unqual;
172     }
173     else static if (is(T U == immutable U))
174     {
175         alias U Unqual;
176     }
177     else
178     {
179         alias T Unqual;
180     }
181 }
182 
183 unittest
184 {
185     static assert (is(Unqual!(typeof("a"[0])) == char));
186 }