@@ -258,14 +258,64 @@ template hasElaborateCopyConstructor(S)
258258 }
259259 else static if (is (S == struct ))
260260 {
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+ }();
262283 }
263284 else
264285 {
265286 enum bool hasElaborateCopyConstructor = false ;
266287 }
267288}
268289
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+
269319template hasElaborateAssign (S)
270320{
271321 static if (__traits(isStaticArray, S) && S.length)
@@ -284,6 +334,205 @@ template hasElaborateAssign(S)
284334 }
285335}
286336
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+
287536// std.meta.Filter
288537template Filter (alias pred, TList... )
289538{
0 commit comments