"instanceOf" trait for conditional implementations

monarch_dodra monarchdodra at gmail.com
Thu Oct 4 02:37:18 PDT 2012


One of the issues I've been running into more or less frequently 
lately is the inability to extract an instance of a type when 
trying to do conditional implementation specification.

Let me explain myself. Using T.init is a no go, because:
a) T might be "@disabled this()", making T.init illegal syntax 
(in theory, currently "buggy")
b) T.init is NOT an LValue, making code such is "is(typeof(T.init 
= 5))" invalid
c) You can try to use "T t = void", but you may also run into 
problems:
c)1) If T is immutable, that's illegal.
c)2) The compiler may complain if you use t, due to access to 
uninitialized.

This makes it a pain in the ass, as shown in this thread:
http://forum.dlang.org/thread/mailman.224.1348358069.5162.digitalmars-d-learn@puremagic.com

Or this pull request:
https://github.com/D-Programming-Language/phobos/pull/832

The current implementation for "isAssignable" is
//----
template isAssignable(Lhs, Rhs)
{
     enum bool isAssignable = is(typeof({
         Lhs l = void;
         void f(Rhs r) { l = r; }
         return l;
     }));
}
//----

The code is correct, but when you have to jump through that many 
loops, you have to admit there is probably something wrong.

Imagine you are writting a template "Foo" that only works if it 
is legal to pass an instance of T to a function Bar. Are you 
*really* going to write the same thing as above, inside a single 
conditional if?!

//******************************************
I'd like to propose an "instanceOf(T)" traits template, that 
would return an LValue instance of T. It would be used (strictly) 
for evaluating conditional implementations, or for the 
implementation of traits types.

//----
template instanceOf(T)
{
     static if (is(typeof({T t;})))
         T instanceOf;
     else
         T instanceOf = void;
}
//----

Now, watch this
//----
template isAssignable(T, U)
{
     enum bool isAssignable = is(typeof(instanceOf!T = 
instanceOf!U));
}

struct S
{
     @disable this();
}

void main()
{
     static assert( isAssignable!(int, int));
     static assert( isAssignable!(int, immutable(int)));
     static assert(!isAssignable!(immutable(int), int));
     static assert( isAssignable!(S, immutable(S))); //Tricky test 
BTW
}
//----
See? Easy peasy.

And this is just a "simple" test case: assign-ability. There are 
a bunch of other traits templates which would benefit here.

And that's the "tip of the iceberg": There are a TON of 
algorithms that use .init in their implementation restrictions: 
"if (Range.init.front ...)"

instanceOf would be a convenient way to support any type, 
regardless of construct-ability (or lack thereof).

//--------
That's my idea anyways, they've been consistently destroyed 
recently, so I don't mind again if you think it is a bad idea, or 
the approach is wrong.

I *do* think that being able to extract an instance of a type 
without worrying about how to actually acquire one...


More information about the Digitalmars-d mailing list