www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Mixins are not inherited?

reply "Namespace" <rswhite4 googlemail.com> writes:
By the following code i get these error messages:

----
Error: template RefTest.Ref.__unittest1.instanceof(T : Object,U : 
Object) cannot deduce template function from argument types 
!(A)(B)

Error: template RefTest.Ref.__unittest1.instanceof does not match 
any function template declaration
	
Error: template instance instanceof!(A) errors instantiating 
template	
----

How is this possible? I thougth that the mixin would be inherited 
and so every subclass would be implicit cast to his super type. 
Isn't that so?
If i write "mixin TRef!(B);" in class B, it works fine. Can 
anyone explain me why do i have to write it in class B?

[code]
unittest {
	bool instanceof(T : Object, U : Object)(const Ref!U obj) {
		const U o = obj.access;

		return const_cast(o).toString() == typeid(T).toString();
	}

	class A {
		mixin TRef!(A);
	}

	class B : A {
		//mixin TRef!(B);
	}

	class C : B {
		//mixin TRef!(C);
	}

	A a1 = new B();
	A a2 = new C();

	assert(instanceof!(A)(a1) == false);
	assert(instanceof!(B)(a1));
	assert(instanceof!(C)(a1) == false);

	writeln(a1);

	B b1 = cast(B) a1;

	assert(instanceof!(A)(b1) == false); // <-- fails

	writeln(b1);

	writeln();
}
[/code]

"TRef" is the same mixin template and "Ref" the same template 
struct as in my last threads.
May 03 2012
next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, May 03, 2012 23:32:50 Namespace wrote:
 By the following code i get these error messages:
 
 ----
 Error: template RefTest.Ref.__unittest1.instanceof(T : Object,U :
 Object) cannot deduce template function from argument types
 !(A)(B)
 
 Error: template RefTest.Ref.__unittest1.instanceof does not match
 any function template declaration
 
 Error: template instance instanceof!(A) errors instantiating
 template
 ----
 
 How is this possible? I thougth that the mixin would be inherited
 and so every subclass would be implicit cast to his super type.
 Isn't that so?
 If i write "mixin TRef!(B);" in class B, it works fine. Can
 anyone explain me why do i have to write it in class B?
 
 [code]
 unittest {
 bool instanceof(T : Object, U : Object)(const Ref!U obj) {
 const U o = obj.access;
 
 return const_cast(o).toString() == typeid(T).toString();
 }
 
 class A {
 mixin TRef!(A);
 }
 
 class B : A {
 //mixin TRef!(B);
 }
 
 class C : B {
 //mixin TRef!(C);
 }
 
 A a1 = new B();
 A a2 = new C();
 
 assert(instanceof!(A)(a1) == false);
 assert(instanceof!(B)(a1));
 assert(instanceof!(C)(a1) == false);
 
 writeln(a1);
 
 B b1 = cast(B) a1;
 
 assert(instanceof!(A)(b1) == false); // <-- fails
 
 writeln(b1);
 
 writeln();
 }
 [/code]
 
 "TRef" is the same mixin template and "Ref" the same template
 struct as in my last threads.

Nothing you put in a base class is automatically in a derived class. If you put a member variable or member function in a base class, it's not in the derived class. It's just that the derived class has access to it as long as it's protected or public. In the case of a mixin, you're essentially copying and pasting code. So, it's in the base class similarly to if you typed it there yourself. However, templated functions aren't virtual, so unlike if you typed them yourself, they won't be virtual if you use a template mixin. So, if you want to mixin something into every class in a hierarchy, you must mix it in to every class in the hierarchy, not just the base class. And if you want to test whether an object is an instance of a specific class, then cast it and check whether the result is null. You don't need to create a function to figure it out for you. e.g. auto c = cast(MyClass)object; if(c is null) writeln("c is NOT an instance of MyClass"); else writeln("c IS an instance of MyClass"); - Jonathan M Davis
May 03 2012
prev sibling parent "Namespace" <rswhite4 googlemail.com> writes:
Very sad, i thougth that was possible.

As regards to "instanceof"

Try this code:

unittest {
	class A {
		mixin TRef!(typeof(this));
	}

	class B : A { }

	class C : B { }

	A a1 = new B();
	A a2 = new C();

	assert(instanceof!(A)(a1) == false);
	assert(instanceof!(B)(a1));
	assert(instanceof!(C)(a1) == false);
}

with my instanceof and then with your version.
May 03 2012