www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - is(Type:Type) fails to evaluate to true

reply silverclaw <post_message newgroup.com> writes:
I picked up the Matrix class I abandoned some months ago and updated it to the
latest DMD (2.022). However, on the opMulAssign the following check fails where
it should pass:

const Matrix!(Type) opMul(T)(const T multiplier)
{
	static if (is(T:Matrix)) //multiplication by a Matrix
	{ (....) }
	else //multiplication by a scalar
	{ (....) }
}

It used to work on some other compiler version. So, on the main() I made the
following code:

(static) if (is(Matrix:Matrix)) writefln("true");
else writefln("false");

always evaluates to false (prints "false") with or without the "static". As you
may have noticed, it is a template class:

public class Matrix(Type)

As I said, it used to work, I'm going to try to find out with which DMD. Any
suggestions?
Oct 08 2007
next sibling parent Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
silverclaw wrote:
 I picked up the Matrix class I abandoned some months ago and updated it to the
latest DMD (2.022). However, on the opMulAssign the following check fails where
it should pass:
 
 const Matrix!(Type) opMul(T)(const T multiplier)
 {
 	static if (is(T:Matrix)) //multiplication by a Matrix
 	{ (....) }
 	else //multiplication by a scalar
 	{ (....) }
 }
I assume this is a member of your Matrix template?
 It used to work on some other compiler version. So, on the main() I made the
following code:
 
 (static) if (is(Matrix:Matrix)) writefln("true");
 else writefln("false");
 
 always evaluates to false (prints "false") with or without the "static". As
you may have noticed, it is a template class:
 
 public class Matrix(Type)
 
 As I said, it used to work, I'm going to try to find out with which DMD. Any
suggestions?
Are you sure it used to work like this? Notice that inside the Matrix template definition, 'Matrix' refers to the current instantiation of the template, not the template itself. For a matrix multiplication, you may not want either of those behaviors. The current instantiation would only allow matrices of the exact same type (not other, compatible types. consider Matrix!(int) * Matrix!(short) for example). If Matrix referred to the template itself it would simply not work (causing the is() to return false) since a template is not a class (even though an *instance* of that template may be). One simple method to detect whether a type is an instance of Matrix would be to make all template instances derive from a common (non-templated) base class (or interface), and test for that. (Using a class would be most efficient, since interfaces require an extra vtable pointer) Note that you don't even need to declare any members for the base class/interface since you know that any class derived from it should have certain members, and your code uses the actual type T of that class. It's just a tag to tell you "This thing is a Matrix". So then the declaration would start with e.g. --- class MatrixBase {} public class Matrix(Type) : MatrixBase { --- and the test would be something like --- static if (is(T:MatrixBase)) //multiplication by a Matrix ---
Oct 08 2007
prev sibling next sibling parent Daniel Keep <daniel.keep.lists gmail.com> writes:
silverclaw wrote:
 I picked up the Matrix class I abandoned some months ago and updated it to the
latest DMD (2.022). However, on the opMulAssign the following check fails where
it should pass:
 
 const Matrix!(Type) opMul(T)(const T multiplier)
 {
 	static if (is(T:Matrix)) //multiplication by a Matrix
 	{ (....) }
 	else //multiplication by a scalar
 	{ (....) }
 }
 
 It used to work on some other compiler version. So, on the main() I made the
following code:
 
 (static) if (is(Matrix:Matrix)) writefln("true");
 else writefln("false");
 
 always evaluates to false (prints "false") with or without the "static". As
you may have noticed, it is a template class:
 
 public class Matrix(Type)
 
 As I said, it used to work, I'm going to try to find out with which DMD. Any
suggestions?
Does is(T:Matrix!(Type)) work? Considering that a template doesn't exist until you instantiate it, I find it odd that is(T:Matrix) ever worked at all. -- Daniel
Oct 08 2007
prev sibling parent reply silverclaw <post_message newgroup.com> writes:
Frits van Bommel Wrote:

 silverclaw wrote:
 I picked up the Matrix class I abandoned some months ago and updated it to the
latest DMD (2.022). However, on the opMulAssign the following check fails where
it should pass:
 
 const Matrix!(Type) opMul(T)(const T multiplier)
 {
 	static if (is(T:Matrix)) //multiplication by a Matrix
 	{ (....) }
 	else //multiplication by a scalar
 	{ (....) }
 }
I assume this is a member of your Matrix template?
Yes. It's an operator overload, I wonder where else I'd put it <g> :P
 
 It used to work on some other compiler version. So, on the main() I made the
following code:
 
 (static) if (is(Matrix:Matrix)) writefln("true");
 else writefln("false");
 
 always evaluates to false (prints "false") with or without the "static". As
you may have noticed, it is a template class:
 
 public class Matrix(Type)
 
 As I said, it used to work, I'm going to try to find out with which DMD. Any
suggestions?
Are you sure it used to work like this?
Yes, I'm sure. I tried to make a template specialization but failing that, I asked in the webnews for a solution and that was the suggestion. As I said before I dropped this module a while ago. It worked at the time, still with a 1.x version of DMD. Anyway, the solution you suggested is what I'll end up doing anyway although I have no idea of what you meant by a "vtable" or in what way it is related to performance. I'll just put in a private empty interface on the module and use it for the comparison and be done with it.
Oct 08 2007
parent Silverclaw <asdgfasd fsadfa.com> writes:
silverclaw Wrote:

 Frits van Bommel Wrote:
 
 silverclaw wrote:
 I picked up the Matrix class I abandoned some months ago and updated it to the
latest DMD (2.022). However, on the opMulAssign the following check fails where
it should pass:
 
 const Matrix!(Type) opMul(T)(const T multiplier)
 {
 	static if (is(T:Matrix)) //multiplication by a Matrix
 	{ (....) }
 	else //multiplication by a scalar
 	{ (....) }
 }
I assume this is a member of your Matrix template?
Yes. It's an operator overload, I wonder where else I'd put it <g> :P
 
 It used to work on some other compiler version. So, on the main() I made the
following code:
 
 (static) if (is(Matrix:Matrix)) writefln("true");
 else writefln("false");
 
 always evaluates to false (prints "false") with or without the "static". As
you may have noticed, it is a template class:
 
 public class Matrix(Type)
 
 As I said, it used to work, I'm going to try to find out with which DMD. Any
suggestions?
Are you sure it used to work like this?
Yes, I'm sure. I tried to make a template specialization but failing that, I asked in the webnews for a solution and that was the suggestion. As I said before I dropped this module a while ago. It worked at the time, still with a 1.x version of DMD. Anyway, the solution you suggested is what I'll end up doing anyway although I have no idea of what you meant by a "vtable" or in what way it is related to performance. I'll just put in a private empty interface on the module and use it for the comparison and be done with it.
Nope, that didn't do it. It still tries to compare the current inheritance level (Matrix!(Type)) and not it's superclass (BaseMatrix).
Oct 08 2007