www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Template constraints for reference/value types?

reply Jon Degenhardt <jond noreply.com> writes:
Is there a way to constrain template arguments to reference or 
value types? I'd like to do something like:

T foo(T)(T x)
     if (isReferenceType!T)
{ ... }

--Jon
Sep 06 2016
parent reply Lodovico Giaretta <lodovico giaretart.net> writes:
On Tuesday, 6 September 2016 at 20:46:54 UTC, Jon Degenhardt 
wrote:
 Is there a way to constrain template arguments to reference or 
 value types? I'd like to do something like:

 T foo(T)(T x)
     if (isReferenceType!T)
 { ... }

 --Jon
You can use `if(is(T : class) || is(T : interface))`. If you also need other types, std.traits contains a bunch of useful templates: isArray, isAssociativeArray, isPointer, ...
Sep 06 2016
parent reply Jon Degenhardt <jond noreply.com> writes:
On Tuesday, 6 September 2016 at 21:00:53 UTC, Lodovico Giaretta 
wrote:
 On Tuesday, 6 September 2016 at 20:46:54 UTC, Jon Degenhardt 
 wrote:
 Is there a way to constrain template arguments to reference or 
 value types? I'd like to do something like:

 T foo(T)(T x)
     if (isReferenceType!T)
 { ... }

 --Jon
You can use `if(is(T : class) || is(T : interface))`. If you also need other types, std.traits contains a bunch of useful templates: isArray, isAssociativeArray, isPointer, ...
Thanks. This looks like a practical approach.
Sep 06 2016
parent reply Jonathan M Davis via Digitalmars-d-learn writes:
On Tuesday, September 06, 2016 21:16:05 Jon Degenhardt via Digitalmars-d-learn 
wrote:
 On Tuesday, 6 September 2016 at 21:00:53 UTC, Lodovico Giaretta

 wrote:
 On Tuesday, 6 September 2016 at 20:46:54 UTC, Jon Degenhardt

 wrote:
 Is there a way to constrain template arguments to reference or
 value types? I'd like to do something like:

 T foo(T)(T x)

     if (isReferenceType!T)

 { ... }

 --Jon
You can use `if(is(T : class) || is(T : interface))`. If you also need other types, std.traits contains a bunch of useful templates: isArray, isAssociativeArray, isPointer, ...
Thanks. This looks like a practical approach.
It'll get you most of the way there, but I don't think that it's actually possible to test for reference types in the general case - the problem being structs with postblit constructors. In many cases, it's possible to detect that a struct has to be a value type, and it's often possible to detect that a struct is a reference type (by looking at the types of the member variables in both cases), but as soon as postblit constructors get involved, it's not possible anymore, because the exact semantics depend on the implementation of the postblit constructor. For instance, struct S { int* i; } is clearly a reference type, but struct S { this(this) { ... } int* i; } may or may not be one. In this particular case, the postblit constructor _probably_ does a deep copy of the member variables, but it might also just print out that the postblit constructor was called or do some other non-obvious thing that the person who wrote it thought that it should do. So, there will be some types where you cannot determine whether they're reference types or value types. And that doesn't even take into consideration types like dynamic arrays or structs like this struct S { int* i; byte b; } which are pseudo-reference types, because part of their state is local and part of it is on the heap. So, depending on what you're trying to do, checking for classes, interfaces, and pointers may get you what you're looking for, and you can get really fancy with trying to determine whether a struct might be a value type or reference type if that suits your purposes, but you're not going to determine the copy semantics of all types. You can figure it out for a lot of them though. - Jonathan M Davis
Sep 06 2016
parent Jon Degenhardt <jond noreply.com> writes:
On Wednesday, 7 September 2016 at 00:40:27 UTC, Jonathan M Davis 
wrote:
 On Tuesday, September 06, 2016 21:16:05 Jon Degenhardt via 
 Digitalmars-d-learn wrote:
 On Tuesday, 6 September 2016 at 21:00:53 UTC, Lodovico Giaretta

 wrote:
 On Tuesday, 6 September 2016 at 20:46:54 UTC, Jon Degenhardt

 wrote:
 Is there a way to constrain template arguments to reference 
 or value types? I'd like to do something like:

 T foo(T)(T x)

     if (isReferenceType!T)

 { ... }

 --Jon
You can use `if(is(T : class) || is(T : interface))`. If you also need other types, std.traits contains a bunch of useful templates: isArray, isAssociativeArray, isPointer, ...
Thanks. This looks like a practical approach.
It'll get you most of the way there, but I don't think that it's actually possible to test for reference types in the general case [snip] - Jonathan M Davis
Thanks, very helpful. I've concluded that what I wanted to do isn't worth pursuing at the moment (see the thread on associative arrays in the General forum). However, your description is helpful to understand the details involved.
Sep 06 2016