Template constraints for reference/value types?

Jonathan M Davis via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue Sep 6 17:40:27 PDT 2016


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



More information about the Digitalmars-d-learn mailing list