@@ -258,14 +258,64 @@ template hasElaborateCopyConstructor(S)
258
258
}
259
259
else static if (is (S == struct ))
260
260
{
261
- enum hasElaborateCopyConstructor = __traits(hasMember, S, " __xpostblit" );
261
+ enum hasElaborateCopyConstructor = __traits(hasMember, S, " __xpostblit" ) ||
262
+ () {
263
+ static if (__traits(hasMember, S, " __ctor" ))
264
+ {
265
+ static foreach (f; __traits (getOverloads , S, " __ctor" ))
266
+ {{
267
+ enum isVoid (alias T) = is (T == void );
268
+ static if (Parameters! f.length == 1 ||
269
+ (Parameters! f.length > 1 && ! anySatisfy! (isVoid, ParameterDefaults! f[1 .. $])))
270
+ {
271
+ bool r = is (typeof ((Parameters! f x) {
272
+ static if (! (__traits(isRef, x[0 ]) && is (Parameters! f[0 ] : S)))
273
+ {
274
+ static assert (0 );
275
+ }
276
+ }));
277
+ if (r) return true ;
278
+ }
279
+ }}
280
+ }
281
+ return false ;
282
+ }();
262
283
}
263
284
else
264
285
{
265
286
enum bool hasElaborateCopyConstructor = false ;
266
287
}
267
288
}
268
289
290
+ @safe unittest
291
+ {
292
+ static struct S
293
+ {
294
+ int x;
295
+ this (return scope ref typeof (this ) rhs) { }
296
+ this (int x, int y) {}
297
+ }
298
+
299
+ static assert (hasElaborateCopyConstructor! S);
300
+
301
+ static struct S2
302
+ {
303
+ int x;
304
+ this (int x, int y) {}
305
+ }
306
+
307
+ static assert (! hasElaborateCopyConstructor! S2 );
308
+
309
+ static struct S3
310
+ {
311
+ int x;
312
+ this (return scope ref typeof (this ) rhs, int x = 42 ) { }
313
+ this (int x, int y) {}
314
+ }
315
+
316
+ static assert (hasElaborateCopyConstructor! S3 );
317
+ }
318
+
269
319
template hasElaborateAssign (S)
270
320
{
271
321
static if (__traits(isStaticArray, S) && S.length)
@@ -284,6 +334,205 @@ template hasElaborateAssign(S)
284
334
}
285
335
}
286
336
337
+ // std.traits.isFunctionPointer
338
+ /**
339
+ Detect whether symbol or type `T` is a function pointer.
340
+ */
341
+ template isFunctionPointer (T... )
342
+ if (T.length == 1 )
343
+ {
344
+ static if (is (T[0 ] U) || is (typeof (T[0 ]) U))
345
+ {
346
+ static if (is (U F : F* ) && is (F == function ))
347
+ enum bool isFunctionPointer = true ;
348
+ else
349
+ enum bool isFunctionPointer = false ;
350
+ }
351
+ else
352
+ enum bool isFunctionPointer = false ;
353
+ }
354
+
355
+ // /
356
+ @safe unittest
357
+ {
358
+ static void foo () {}
359
+ void bar () {}
360
+
361
+ auto fpfoo = &foo;
362
+ static assert ( isFunctionPointer! fpfoo);
363
+ static assert ( isFunctionPointer! (void function ()));
364
+
365
+ auto dgbar = &bar;
366
+ static assert (! isFunctionPointer! dgbar);
367
+ static assert (! isFunctionPointer! (void delegate ()));
368
+ static assert (! isFunctionPointer! foo);
369
+ static assert (! isFunctionPointer! bar);
370
+
371
+ static assert ( isFunctionPointer! ((int a) {}));
372
+ }
373
+
374
+ // std.traits.isDelegate
375
+ /**
376
+ Detect whether symbol or type `T` is a delegate.
377
+ */
378
+ template isDelegate (T... )
379
+ if (T.length == 1 )
380
+ {
381
+ static if (is (typeof (& T[0 ]) U : U* ) && is (typeof (& T[0 ]) U == delegate ))
382
+ {
383
+ // T is a (nested) function symbol.
384
+ enum bool isDelegate = true ;
385
+ }
386
+ else static if (is (T[0 ] W) || is (typeof (T[0 ]) W))
387
+ {
388
+ // T is an expression or a type. Take the type of it and examine.
389
+ enum bool isDelegate = is (W == delegate );
390
+ }
391
+ else
392
+ enum bool isDelegate = false ;
393
+ }
394
+
395
+ // /
396
+ @safe unittest
397
+ {
398
+ static void sfunc () { }
399
+ int x;
400
+ void func () { x++ ; }
401
+
402
+ int delegate () dg;
403
+ assert (isDelegate! dg);
404
+ assert (isDelegate! (int delegate ()));
405
+ assert (isDelegate! (typeof (&func)));
406
+
407
+ int function () fp;
408
+ assert (! isDelegate! fp);
409
+ assert (! isDelegate! (int function ()));
410
+ assert (! isDelegate! (typeof (&sfunc)));
411
+ }
412
+
413
+ // std.traits.ParameterIdentifierTuple
414
+ /**
415
+ Get, as a tuple, the identifiers of the parameters to a function symbol.
416
+ */
417
+ template ParameterIdentifierTuple (func... )
418
+ if (func.length == 1 /* && isCallable!func*/ )
419
+ {
420
+ static if (is (FunctionTypeOf! func PT == __parameters ))
421
+ {
422
+ template Get (size_t i)
423
+ {
424
+ static if (! isFunctionPointer! func && ! isDelegate! func
425
+ // Unnamed parameters yield CT error.
426
+ && is (typeof (__traits(identifier, PT [i .. i+ 1 ])))
427
+ // Filter out unnamed args, which look like (Type) instead of (Type name).
428
+ && PT [i].stringof != PT [i .. i+ 1 ].stringof[1 .. $- 1 ])
429
+ {
430
+ enum Get = __traits(identifier, PT [i .. i+ 1 ]);
431
+ }
432
+ else
433
+ {
434
+ enum Get = " " ;
435
+ }
436
+ }
437
+ }
438
+ else
439
+ {
440
+ static assert (0 , func[0 ].stringof ~ " is not a function" );
441
+
442
+ // Define dummy entities to avoid pointless errors
443
+ template Get (size_t i) { enum Get = " " ; }
444
+ alias PT = AliasSeq! ();
445
+ }
446
+
447
+ template Impl (size_t i = 0 )
448
+ {
449
+ static if (i == PT .length)
450
+ alias Impl = AliasSeq! ();
451
+ else
452
+ alias Impl = AliasSeq! (Get! i, Impl! (i+ 1 ));
453
+ }
454
+
455
+ alias ParameterIdentifierTuple = Impl! ();
456
+ }
457
+
458
+ // /
459
+ @safe unittest
460
+ {
461
+ int foo (int num, string name, int );
462
+ static assert ([ParameterIdentifierTuple! foo] == [" num" , " name" , " " ]);
463
+ }
464
+
465
+ // std.traits.ParameterDefaults
466
+ /**
467
+ Get, as a tuple, the default value of the parameters to a function symbol.
468
+ If a parameter doesn't have the default value, `void` is returned instead.
469
+ */
470
+ template ParameterDefaults (func... )
471
+ if (func.length == 1 /* && isCallable!func*/ )
472
+ {
473
+ alias param_names = ParameterIdentifierTuple! func;
474
+ static if (is (FunctionTypeOf! (func[0 ]) PT == __parameters ))
475
+ {
476
+ template Get (size_t i)
477
+ {
478
+ // `PT[i .. i+1]` declares a parameter with an arbitrary name.
479
+ // To avoid a name clash, generate local names that are distinct
480
+ // from the parameter name, and mix them in.
481
+ enum name = param_names[i];
482
+ enum args = " args" ~ (name == " args" ? " _" : " " );
483
+ enum val = " val" ~ (name == " val" ? " _" : " " );
484
+ enum ptr = " ptr" ~ (name == " ptr" ? " _" : " " );
485
+ mixin ("
486
+ // workaround scope escape check, see
487
+ // https://issues.dlang.org/show_bug.cgi?id=16582
488
+ // should use return scope once available
489
+ enum get = (PT[i .. i+1] " ~ args ~ " ) @trusted
490
+ {
491
+ // If the parameter is lazy, we force it to be evaluated
492
+ // like this.
493
+ auto " ~ val ~ " = " ~ args ~ " [0];
494
+ auto " ~ ptr ~ " = &" ~ val ~ " ;
495
+ // workaround Bugzilla 16582
496
+ return *" ~ ptr ~ " ;
497
+ };
498
+ " );
499
+ static if (is (typeof (get ())))
500
+ enum Get = get ();
501
+ else
502
+ alias Get = void ;
503
+ // If default arg doesn't exist, returns void instead.
504
+ }
505
+ }
506
+ else
507
+ {
508
+ static assert (0 , func[0 ].stringof ~ " is not a function" );
509
+
510
+ // Define dummy entities to avoid pointless errors
511
+ template Get (size_t i) { enum Get = " " ; }
512
+ alias PT = AliasSeq! ();
513
+ }
514
+
515
+ template Impl (size_t i = 0 )
516
+ {
517
+ static if (i == PT .length)
518
+ alias Impl = AliasSeq! ();
519
+ else
520
+ alias Impl = AliasSeq! (Get! i, Impl! (i+ 1 ));
521
+ }
522
+
523
+ alias ParameterDefaults = Impl! ();
524
+ }
525
+
526
+ // /
527
+ @safe unittest
528
+ {
529
+ int foo (int num, string name = " hello" , int [] = [1 ,2 ,3 ], lazy int x = 0 );
530
+ static assert (is (ParameterDefaults! foo[0 ] == void ));
531
+ static assert ( ParameterDefaults! foo[1 ] == " hello" );
532
+ static assert ( ParameterDefaults! foo[2 ] == [1 ,2 ,3 ]);
533
+ static assert ( ParameterDefaults! foo[3 ] == 0 );
534
+ }
535
+
287
536
// std.meta.Filter
288
537
template Filter (alias pred, TList... )
289
538
{
0 commit comments