@@ -206,12 +206,16 @@ template hasElaborateCopyConstructor(S)
206
206
{
207
207
static foreach (f; __traits (getOverloads , S, " __ctor" ))
208
208
{{
209
- static if (Parameters! f.length == 1 )
209
+ enum isVoid (alias T) = is (T == void );
210
+ static if (Parameters! f.length == 1 ||
211
+ (Parameters! f.length > 1 && ! anySatisfy! (isVoid, ParameterDefaults! f[1 .. $])))
210
212
{
211
- Parameters! f tmp;
212
- bool r = (Parameters! f x) {
213
- return __traits (isRef, x) && is (Parameters! f[0 ] : S);
214
- }(tmp);
213
+ bool r = is (typeof ((Parameters! f x) {
214
+ static if (! (__traits(isRef, x[0 ]) && is (Parameters! f[0 ] : S)))
215
+ {
216
+ static assert (0 );
217
+ }
218
+ }));
215
219
if (r) return true ;
216
220
}
217
221
}}
@@ -225,7 +229,7 @@ template hasElaborateCopyConstructor(S)
225
229
}
226
230
}
227
231
228
- unittest
232
+ @safe unittest
229
233
{
230
234
static struct S
231
235
{
@@ -243,6 +247,15 @@ unittest
243
247
}
244
248
245
249
static assert (! hasElaborateCopyConstructor! S2 );
250
+
251
+ static struct S3
252
+ {
253
+ int x;
254
+ this (return scope ref typeof (this ) rhs, int x = 42 ) { }
255
+ this (int x, int y) {}
256
+ }
257
+
258
+ static assert (hasElaborateCopyConstructor! S3 );
246
259
}
247
260
248
261
template hasElaborateAssign (S)
@@ -263,6 +276,205 @@ template hasElaborateAssign(S)
263
276
}
264
277
}
265
278
279
+ // std.traits.isFunctionPointer
280
+ /**
281
+ Detect whether symbol or type `T` is a function pointer.
282
+ */
283
+ template isFunctionPointer (T... )
284
+ if (T.length == 1 )
285
+ {
286
+ static if (is (T[0 ] U) || is (typeof (T[0 ]) U))
287
+ {
288
+ static if (is (U F : F* ) && is (F == function ))
289
+ enum bool isFunctionPointer = true ;
290
+ else
291
+ enum bool isFunctionPointer = false ;
292
+ }
293
+ else
294
+ enum bool isFunctionPointer = false ;
295
+ }
296
+
297
+ // /
298
+ @safe unittest
299
+ {
300
+ static void foo () {}
301
+ void bar () {}
302
+
303
+ auto fpfoo = &foo;
304
+ static assert ( isFunctionPointer! fpfoo);
305
+ static assert ( isFunctionPointer! (void function ()));
306
+
307
+ auto dgbar = &bar;
308
+ static assert (! isFunctionPointer! dgbar);
309
+ static assert (! isFunctionPointer! (void delegate ()));
310
+ static assert (! isFunctionPointer! foo);
311
+ static assert (! isFunctionPointer! bar);
312
+
313
+ static assert ( isFunctionPointer! ((int a) {}));
314
+ }
315
+
316
+ // std.traits.isDelegate
317
+ /**
318
+ Detect whether symbol or type `T` is a delegate.
319
+ */
320
+ template isDelegate (T... )
321
+ if (T.length == 1 )
322
+ {
323
+ static if (is (typeof (& T[0 ]) U : U* ) && is (typeof (& T[0 ]) U == delegate ))
324
+ {
325
+ // T is a (nested) function symbol.
326
+ enum bool isDelegate = true ;
327
+ }
328
+ else static if (is (T[0 ] W) || is (typeof (T[0 ]) W))
329
+ {
330
+ // T is an expression or a type. Take the type of it and examine.
331
+ enum bool isDelegate = is (W == delegate );
332
+ }
333
+ else
334
+ enum bool isDelegate = false ;
335
+ }
336
+
337
+ // /
338
+ @safe unittest
339
+ {
340
+ static void sfunc () { }
341
+ int x;
342
+ void func () { x++ ; }
343
+
344
+ int delegate () dg;
345
+ assert (isDelegate! dg);
346
+ assert (isDelegate! (int delegate ()));
347
+ assert (isDelegate! (typeof (&func)));
348
+
349
+ int function () fp;
350
+ assert (! isDelegate! fp);
351
+ assert (! isDelegate! (int function ()));
352
+ assert (! isDelegate! (typeof (&sfunc)));
353
+ }
354
+
355
+ // std.traits.ParameterIdentifierTuple
356
+ /**
357
+ Get, as a tuple, the identifiers of the parameters to a function symbol.
358
+ */
359
+ template ParameterIdentifierTuple (func... )
360
+ if (func.length == 1 /* && isCallable!func*/ )
361
+ {
362
+ static if (is (FunctionTypeOf! func PT == __parameters ))
363
+ {
364
+ template Get (size_t i)
365
+ {
366
+ static if (! isFunctionPointer! func && ! isDelegate! func
367
+ // Unnamed parameters yield CT error.
368
+ && is (typeof (__traits(identifier, PT [i .. i+ 1 ])))
369
+ // Filter out unnamed args, which look like (Type) instead of (Type name).
370
+ && PT [i].stringof != PT [i .. i+ 1 ].stringof[1 .. $- 1 ])
371
+ {
372
+ enum Get = __traits(identifier, PT [i .. i+ 1 ]);
373
+ }
374
+ else
375
+ {
376
+ enum Get = " " ;
377
+ }
378
+ }
379
+ }
380
+ else
381
+ {
382
+ static assert (0 , func[0 ].stringof ~ " is not a function" );
383
+
384
+ // Define dummy entities to avoid pointless errors
385
+ template Get (size_t i) { enum Get = " " ; }
386
+ alias PT = AliasSeq! ();
387
+ }
388
+
389
+ template Impl (size_t i = 0 )
390
+ {
391
+ static if (i == PT .length)
392
+ alias Impl = AliasSeq! ();
393
+ else
394
+ alias Impl = AliasSeq! (Get! i, Impl! (i+ 1 ));
395
+ }
396
+
397
+ alias ParameterIdentifierTuple = Impl! ();
398
+ }
399
+
400
+ // /
401
+ @safe unittest
402
+ {
403
+ int foo (int num, string name, int );
404
+ static assert ([ParameterIdentifierTuple! foo] == [" num" , " name" , " " ]);
405
+ }
406
+
407
+ // std.traits.ParameterDefaults
408
+ /**
409
+ Get, as a tuple, the default value of the parameters to a function symbol.
410
+ If a parameter doesn't have the default value, `void` is returned instead.
411
+ */
412
+ template ParameterDefaults (func... )
413
+ if (func.length == 1 /* && isCallable!func*/ )
414
+ {
415
+ alias param_names = ParameterIdentifierTuple! func;
416
+ static if (is (FunctionTypeOf! (func[0 ]) PT == __parameters ))
417
+ {
418
+ template Get (size_t i)
419
+ {
420
+ // `PT[i .. i+1]` declares a parameter with an arbitrary name.
421
+ // To avoid a name clash, generate local names that are distinct
422
+ // from the parameter name, and mix them in.
423
+ enum name = param_names[i];
424
+ enum args = " args" ~ (name == " args" ? " _" : " " );
425
+ enum val = " val" ~ (name == " val" ? " _" : " " );
426
+ enum ptr = " ptr" ~ (name == " ptr" ? " _" : " " );
427
+ mixin ("
428
+ // workaround scope escape check, see
429
+ // https://issues.dlang.org/show_bug.cgi?id=16582
430
+ // should use return scope once available
431
+ enum get = (PT[i .. i+1] " ~ args ~ " ) @trusted
432
+ {
433
+ // If the parameter is lazy, we force it to be evaluated
434
+ // like this.
435
+ auto " ~ val ~ " = " ~ args ~ " [0];
436
+ auto " ~ ptr ~ " = &" ~ val ~ " ;
437
+ // workaround Bugzilla 16582
438
+ return *" ~ ptr ~ " ;
439
+ };
440
+ " );
441
+ static if (is (typeof (get ())))
442
+ enum Get = get ();
443
+ else
444
+ alias Get = void ;
445
+ // If default arg doesn't exist, returns void instead.
446
+ }
447
+ }
448
+ else
449
+ {
450
+ static assert (0 , func[0 ].stringof ~ " is not a function" );
451
+
452
+ // Define dummy entities to avoid pointless errors
453
+ template Get (size_t i) { enum Get = " " ; }
454
+ alias PT = AliasSeq! ();
455
+ }
456
+
457
+ template Impl (size_t i = 0 )
458
+ {
459
+ static if (i == PT .length)
460
+ alias Impl = AliasSeq! ();
461
+ else
462
+ alias Impl = AliasSeq! (Get! i, Impl! (i+ 1 ));
463
+ }
464
+
465
+ alias ParameterDefaults = Impl! ();
466
+ }
467
+
468
+ // /
469
+ @safe unittest
470
+ {
471
+ int foo (int num, string name = " hello" , int [] = [1 ,2 ,3 ], lazy int x = 0 );
472
+ static assert (is (ParameterDefaults! foo[0 ] == void ));
473
+ static assert ( ParameterDefaults! foo[1 ] == " hello" );
474
+ static assert ( ParameterDefaults! foo[2 ] == [1 ,2 ,3 ]);
475
+ static assert ( ParameterDefaults! foo[3 ] == 0 );
476
+ }
477
+
266
478
// std.meta.Filter
267
479
template Filter (alias pred, TList... )
268
480
{
0 commit comments