Skip to content

Commit 055b63b

Browse files
committed
Merge remote-tracking branch 'upstream/master' into stable
2 parents 03975f6 + 2dc152d commit 055b63b

33 files changed

+967
-462
lines changed

.circleci/config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ jobs:
44
working_directory: ~/dlang.org
55
docker:
66
- image: cimg/base:current-20.04
7+
resource_class: medium+
78
parallelism: 1
89
steps:
910
- checkout

.htaccess

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ Redirect 301 /donate.html https://dlang.org/foundation/donate.html
7171
Redirect 301 /articles.html /articles/index.html
7272
Redirect 301 /builtin.html /articles/builtin.html
7373
Redirect 301 /code_coverage.html /articles/code_coverage.html
74+
Redirect 301 /concepts.html /articles/constraints.html
7475
Redirect 301 /const-faq.html /articles/const-faq.html
7576
Redirect 301 /cppcontracts.html /articles/cppcontracts.html
7677
Redirect 301 /cpptod.html /articles/cpptod.html

ads.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
google.com, pub-7775438694241734, DIRECT, f08c47fec0942fa0

concepts.dd renamed to articles/constraints.dd

Lines changed: 127 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -4,33 +4,44 @@ $(D_S Template Constraints,
44

55
$(P Templates are normally overloaded and matched based on the
66
template arguments being matched to the template parameters.
7-
The template parameters can specify specializations, so that
7+
The template parameters can specify
8+
$(DDSUBLINK spec/template, parameters_specialization, specializations), so that
89
the template argument must match particular type patterns.
910
Similarly, template value arguments can be constrained to
1011
match particular types.)
1112

13+
---
14+
template Foo(T) { ... }
15+
template Foo(T : T*) { ... }
16+
template Foo(T : T[]) { ... }
17+
18+
alias f1 = Foo!(int); // picks Foo(T)
19+
alias f2 = Foo!(int*); // picks Foo(T : T*)
20+
alias f3 = Foo!(int[]); // picks Foo(T : T[])
21+
---
22+
1223
$(P But this has its limitations. Many times there are
1324
arbitrarily more
1425
complex criteria for what should be accepted by the template.
15-
This can be used to:
26+
Such criteria could be to:
1627
)
1728

1829
$(UL
1930
$(LI more finely discriminate about which
2031
template gets instantiated for given arguments)
21-
$(LI provides better self-documentation about what
32+
$(LI provide better self-documentation about what
2233
characteristics template parameters must have)
23-
$(LI can provide better diagnostics when arguments don't match,
34+
$(LI provide better diagnostics when arguments don't match,
2435
rather than an obscure error message based on the irrelevant
2536
(to the user) internal details of the template implementation)
2637
)
2738

28-
$(P Constraints address this by simply providing an
29-
expression that must evaluate at compile time to true
39+
$(P Constraints address this by simply providing a boolean
40+
expression that is evaluated at compile-time,
3041
after the arguments are matched to the parameters.
31-
If it is true, then that template is a valid match for
32-
the arguments, if not, then it is not and is passed over
33-
during overload matching.)
42+
If that boolean is true, then the template is a valid match for
43+
the arguments, if not, then the template does not match and
44+
is passed over during overload matching.)
3445

3546
$(P The constraint expression follows the template declaration
3647
and the $(CODE if) keyword:)
@@ -45,20 +56,27 @@ template Foo(int N)
4556

4657
$(P which constrains the template $(CODE Foo) to match only if its
4758
argument
48-
is an odd integer. Arbitrarily complex criteria can be used, as
59+
is an odd integer.)
60+
61+
$(H2 $(LNAME2 predicates, Predicate Functions))
62+
63+
$(P Arbitrarily complex criteria can be used, as
4964
long as it can be computed at compile time. For example, here's
5065
a template that only accepts prime numbers:
5166
)
5267

68+
$(RUNNABLE_EXAMPLE_COMPILE
5369
---
5470
bool isPrime(int n)
5571
{
5672
if (n == 2)
5773
return true;
74+
// 0, negative and even numbers are not prime
5875
if (n < 1 || (n & 1) == 0)
5976
return false;
6077
if (n > 3)
6178
{
79+
// check possible odd integer denominators
6280
for (auto i = 3; i * i <= n; i += 2)
6381
{
6482
if ((n % i) == 0)
@@ -71,16 +89,22 @@ bool isPrime(int n)
7189
template Foo(int N)
7290
if (isPrime(N))
7391
{
74-
...
92+
// ...
7593
}
7694

77-
Foo!(5) // ok, 5 is prime
78-
Foo!(6) // no match for Foo
95+
alias f1 = Foo!(5); // ok, 5 is prime
96+
//alias f2 = Foo!(6); // error: no match for Foo
97+
//alias f3 = Foo!(9); // error: no match for Foo
7998
---
99+
)
100+
101+
$(NOTE `isPrime` is called using $(DDSUBLINK spec/function, interpretation, Compile-Time Function Evaluation).)
80102

81-
$(P Type constraints can be complex, too. For example, a template
82-
Bar that will accept any floating point type using the traditional
83-
type specializations:
103+
$(H2 $(LNAME2 is, `is` Expressions))
104+
105+
$(P Type constraints can be complex, too. With type specialization alone, a template
106+
`Bar` that will accept any type that implicitly converts to a built-in floating
107+
point type must use template overloads:
84108
)
85109
---
86110
template Bar(T:float)
@@ -102,84 +126,127 @@ template Bar(T:real)
102126
)
103127
---
104128
template Bar(T)
105-
if (is(T == float) || is(T == double) || is(T == real))
129+
if (is(T : float) || is(T : double) || is(T : real))
106130
{
107131
...
108132
}
109133
---
110-
$(P This can be simplified by using the $(CODE isFloatingPoint)
111-
template in library module $(CODE std.traits):
134+
$(P Unlike with parameter specialization, types with implicit conversion to
135+
floating point can be ruled out with a different constraint:)
136+
137+
$(RUNNABLE_EXAMPLE_COMPILE
138+
---
139+
template Bar(T)
140+
if (is(T == float) || is(T == double) || is(T == real))
141+
{
142+
// ...
143+
}
144+
145+
alias b1 = Bar!float; // OK
146+
//alias b2 = Bar!int; // error
147+
---
148+
)
149+
$(P See $(GLINK2 expression, IsExpression) for more tests.)
150+
151+
$(P The above example can be simplified by using the $(CODE isFloatingPoint)
152+
template in library module $(MREF std, traits):
112153
)
113154
---
114155
import std.traits;
156+
115157
template Bar(T)
116158
if (isFloatingPoint!(T))
117159
{
118160
...
119161
}
120162
---
121163

164+
$(H2 $(LNAME2 traits, `__traits`))
165+
122166
$(P Characteristics of types can be tested, such as if
123-
a type can be added:
167+
a type instance can be added:
124168
)
125169

170+
$(RUNNABLE_EXAMPLE
126171
---
127172
// Returns true if instances of type T can be added
128-
template isAddable(T)
129-
{
130-
// Works by attempting to add two instances of type T
131-
const isAddable = __traits(compiles, (T t) { return t + t; });
132-
}
173+
// Works by attempting to add two instances of type T
174+
const isAddable(T) = __traits(compiles, (T t) { return t + t; });
133175

134-
int Foo(T)(T t)
176+
auto twice(T)(T t)
135177
if (isAddable!(T))
136178
{
137-
return 3;
179+
return t + t;
138180
}
139181

182+
// an addable struct type
140183
struct S
141184
{
142-
void opAdd(S s) { } // an addable struct type
185+
int i;
186+
187+
S opBinary(string op : "+")(S s)
188+
{
189+
return S(i + s.i);
190+
}
143191
}
144192

145193
void main()
146194
{
147-
Foo(4); // succeeds
148-
S s;
149-
Foo(s); // succeeds
150-
Foo("a"); // fails to match
195+
assert(twice(4) == 8);
196+
S s = {2};
197+
assert(twice(s).i == 4);
198+
//twice("a"); // fails to match
151199
}
152200
---
201+
)
202+
203+
$(P $(DDSUBLINK spec/traits, compiles, `__traits(compiles)`) is
204+
used to check if a function literal successfully compiles. Other
205+
expressions can be used instead of a function literal. The expression
206+
is not evaluated.
207+
Other compile-time `__traits` $(DDLINK spec/traits, Traits, are available).)
208+
209+
$(NOTE The function literal above declares an argument of type
210+
`T` to obtain an instance of `T` without having to construct it.)
153211

154212
$(P Since any expression that can be computed at compile time
155213
is allowed as a constraint, constraints can be composed:
156214
)
157215

158216
---
159-
int Foo(T)(T t)
217+
T foo(T)(T t)
160218
if (isAddable!(T) && isMultipliable!(T))
161219
{
162-
return 3;
220+
return t + t * t;
163221
}
164222
---
165223

166-
$(P A more complex constraint can specify a list of operations
167-
that must be doable with the type, such as $(CODE isStack) which
168-
specifies the constraints that a stack type must have:)
224+
$(P Constraints can deal with multiple parameters:)
169225

170-
----
171-
template isStack(T)
226+
---
227+
template Foo(T, int N)
228+
if (isAddable!(T) && isPrime(N))
172229
{
173-
const isStack =
174-
__traits(compiles,
175-
(T t)
176-
{
177-
T.value_type v = top(t);
178-
push(t, v);
179-
pop(t);
180-
if (empty(t)) { }
181-
});
230+
...
182231
}
232+
---
233+
234+
$(P A more complex constraint can specify a list of operations
235+
that must be doable with the type, such as evaluating template $(CODE isStack) which
236+
requires that the type has a type property `ValueType`, and that 4 functions
237+
exist which take an instance of the type, 2 of which return certain
238+
values:)
239+
240+
----
241+
const isStack(T) =
242+
__traits(compiles,
243+
(T t)
244+
{
245+
T.ValueType v = top(t);
246+
push(t, v);
247+
pop(t);
248+
if (empty(t)) { }
249+
});
183250

184251
template Foo(T)
185252
if (isStack!(T))
@@ -188,17 +255,7 @@ template Foo(T)
188255
}
189256
----
190257

191-
$(P and constraints can deal with multiple parameters:)
192-
193-
---
194-
template Foo(T, int N)
195-
if (isAddable!(T) && isprime(N))
196-
{
197-
...
198-
}
199-
---
200-
201-
$(H2 Overloading based on Constraints)
258+
$(H2 $(LNAME2 overloading, Overloading based on Constraints))
202259

203260
$(P Given a list of overloaded templates with the same name,
204261
constraints act as a yes/no filter to determine the list
@@ -216,6 +273,17 @@ Foo!(3) // instantiates A
216273
Foo!(64) // instantiates B
217274
---
218275

276+
$(P Note the above 2 templates could be combined using
277+
$(DDSUBLINK spec/version, staticif, `static if`):)
278+
---
279+
template Foo(int N)
280+
{
281+
static if (N & 1)
282+
// body of A
283+
else
284+
// body of B
285+
}
286+
---
219287
$(P Constraints are not involved with determining which
220288
template is more specialized than another.
221289
)

articles/index.dd

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -128,20 +128,35 @@ $(D_S Articles,
128128
$(P Walter Bright writes about how D improves upon C++
129129
templates.)
130130
)
131+
$(DIVC item,
132+
$(H4 $(LINK2 $(ROOT_DIR)articles/constraints.html,
133+
Template Constraints))
134+
$(P A template can be constrained to only apply when a compile-time
135+
evaluable boolean expression is true.)
136+
)
137+
)
138+
$(DIVC row,
131139
$(DIVC item,
132140
$(H4 $(LINK2 $(ROOT_DIR)articles/ctarguments.html, Compile-time Sequences))
133141
$(P A compile-time sequence is a sequence of compile-time entities -
134142
types, symbols (names) and values. This
135143
article shows how to work with them.)
136144
)
137-
)
138-
$(DIVC row,
139145
$(DIVC item,
140146
$(H4 $(LINK2 $(ROOT_DIR)articles/variadic-function-templates.html,
141147
Variadic Templates))
142148
$(P This article is about the D idiom of implementing variadic
143149
functions with variadic templates.)
144150
)
151+
)
152+
$(DIVC row,
153+
$(DIVC item,
154+
$(H4 $(LINK2 $(ROOT_DIR)articles/template-comparison.html,
155+
Template Comparison))
156+
$(P
157+
A comparison between D's and C++'s templates.
158+
)
159+
)
145160
$(DIVC item,
146161
$(H4 $(LINK2 $(ROOT_DIR)articles/d-array-article.html, D Slices))
147162
$(P Steven Schveighoffer writes about slices and dynamic arrays
@@ -162,15 +177,6 @@ $(D_S Articles,
162177
A comparison between D's and C++'s contract programming.
163178
)
164179
)
165-
$(DIVC item,
166-
$(H4 $(LINK2 $(ROOT_DIR)articles/template-comparison.html,
167-
Template Comparison))
168-
$(P
169-
A comparison between D's and C++'s templates.
170-
)
171-
)
172-
)
173-
$(DIVC row,
174180
$(DIVC item,
175181
$(H4 $(LINK2 $(ROOT_DIR)articles/dll-linux.html,
176182
Writing Shared Libraries on Linux))

0 commit comments

Comments
 (0)