@@ -206,12 +206,16 @@ template hasElaborateCopyConstructor(S)
206206 {
207207 static foreach (f; __traits (getOverloads , S, " __ctor" ))
208208 {{
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 .. $])))
210212 {
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+ }));
215219 if (r) return true ;
216220 }
217221 }}
@@ -225,7 +229,7 @@ template hasElaborateCopyConstructor(S)
225229 }
226230}
227231
228- unittest
232+ @safe unittest
229233{
230234 static struct S
231235 {
@@ -243,6 +247,15 @@ unittest
243247 }
244248
245249 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 );
246259}
247260
248261template hasElaborateAssign (S)
@@ -263,6 +276,205 @@ template hasElaborateAssign(S)
263276 }
264277}
265278
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+
266478// std.meta.Filter
267479template Filter (alias pred, TList... )
268480{
0 commit comments