/** * $(SCRIPT inhibitQuickIndex = 1;) * $(DIVC quickindex, * $(BOOKTABLE, * $(TR $(TH Category) $(TH Symbols)) * $(TR $(TD Arrays) $(TD * $(MYREF assumeSafeAppend) * $(MYREF capacity) * $(A #.dup.2, $(TT dup)) * $(MYREF idup) * $(MYREF reserve) * )) * $(TR $(TD Associative arrays) $(TD * $(MYREF byKey) * $(MYREF byKeyValue) * $(MYREF byValue) * $(MYREF clear) * $(MYREF dup) * $(MYREF get) * $(MYREF keys) * $(MYREF rehash) * $(MYREF require) * $(MYREF update) * $(MYREF values) * )) * $(TR $(TD General) $(TD * $(MYREF destroy) * $(MYREF hashOf) * $(MYREF imported) * $(MYREF noreturn) * )) * $(TR $(TD Classes) $(TD * $(MYREF Error) * $(MYREF Exception) * $(MYREF Object) * $(MYREF opEquals) * $(MYREF Throwable) * )) * $(TR $(TD Type info) $(TD * $(MYREF Interface) * $(MYREF ModuleInfo) * $(MYREF OffsetTypeInfo) * $(MYREF RTInfoImpl) * $(MYREF rtinfoNoPointers) * $(MYREF TypeInfo) * $(MYREF TypeInfo_Class) * )) * )) * * Forms the symbols available to all D programs. Includes Object, which is * the root of the class object hierarchy. This module is implicitly * imported. * * Copyright: Copyright Digital Mars 2000 - 2011. * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). * Authors: Walter Bright, Sean Kelly * Source: $(DRUNTIMESRC object.d) */ module object; alias size_t = typeof(int.sizeof);alias ptrdiff_t = typeof(cast(void*)0 - cast(void*)0); alias sizediff_t = ptrdiff_t; // For backwards compatibility only./** * Bottom type. * See $(DDSUBLINK spec/type, noreturn, `noreturn`). */alias noreturn = typeof(*null); alias hash_t = size_t; // For backwards compatibility only.alias equals_t = bool; // For backwards compatibility only. alias string = immutable(char)[];alias wstring = immutable(wchar)[];alias dstring = immutable(dchar)[]; version (D_ObjectiveC){ deprecated("explicitly import `selector` instead using: `import core.attribute : selector;`") public import core.attribute : selector;}version (Posix) public import core.attribute : gnuAbiTag; // Some ABIs use a complex varargs implementation requiring TypeInfo.argTypes().version (GNU){ // No TypeInfo-based core.vararg.va_arg().}else version (X86_64){ version (DigitalMars) version = WithArgTypes; else version (Windows) { /* no need for Win64 ABI */ } else version = WithArgTypes;}else version (AArch64){ // Apple uses a trivial varargs implementation version (DigitalMars) version = WithArgTypes; // is this needed? else version (OSX) {} else version (iOS) {} else version (TVOS) {} else version (WatchOS) {} else version = WithArgTypes;} /** * All D class objects inherit from Object. */class Object{ /** * Convert Object to a human readable string. */ string toString() { return typeid(this).name; } @system unittest { enum unittest_sym_name = __traits(identifier, __traits(parent, (){})); enum fqn_unittest = "object.Object." ~ unittest_sym_name; // object.__unittest_LX_CY class C {} Object obj = new Object; C c = new C; assert(obj.toString() == "object.Object"); assert(c.toString() == fqn_unittest ~ ".C"); } /** * Compute hash function for Object. */ size_t toHash() @trusted nothrow { // BUG: this prevents a compacting GC from working, needs to be fixed size_t addr = cast(size_t) cast(void*) this; // The bottom log2((void*).alignof) bits of the address will always // be 0. Moreover it is likely that each Object is allocated with a // separate call to malloc. The alignment of malloc differs from // platform to platform, but rather than having special cases for // each platform it is safe to use a shift of 4. To minimize // collisions in the low bits it is more important for the shift to // not be too small than for the shift to not be too big. return addr ^ (addr >>> 4); } /** * Compare with another Object obj. * Returns: * $(TABLE * $(TR $(TD this < obj) $(TD < 0)) * $(TR $(TD this == obj) $(TD 0)) * $(TR $(TD this > obj) $(TD > 0)) * ) */ int opCmp(Object o) { // BUG: this prevents a compacting GC from working, needs to be fixed //return cast(int)cast(void*)this - cast(int)cast(void*)o; throw new Exception("need opCmp for class " ~ typeid(this).name); //return this !is o; } @system unittest { Object obj = new Object; bool gotCaught; try { obj.opCmp(new Object); } catch (Exception e) { gotCaught = true; assert(e.msg == "need opCmp for class object.Object"); } assert(gotCaught); } /** * Test whether $(D this) is equal to $(D o). * The default implementation only compares by identity (using the $(D is) operator). * Generally, overrides and overloads for $(D opEquals) should attempt to compare objects by their contents. * A class will most likely want to add an overload that takes your specific type as the argument * and does the content comparison. Then you can override this and forward it to your specific * typed overload with a cast. Remember to check for `null` on the typed overload. * * Examples: * --- * class Child { * int contents; * // the typed overload first. It can use all the attribute you want * bool opEquals(const Child c) const @safe pure nothrow @nogc * { * if (c is null) * return false; * return this.contents == c.contents; * } * * // and now the generic override forwards with a cast * override bool opEquals(Object o) * { * return this.opEquals(cast(Child) o); * } * } * --- */ bool opEquals(Object o) { return this is o; } interface Monitor { void lock(); void unlock(); } /** * Create instance of class specified by the fully qualified name * classname. * The class must either have no constructors or have * a default constructor. * Returns: * null if failed * Example: * --- * module foo.bar; * * class C * { * this() { x = 10; } * int x; * } * * void main() * { * auto c = cast(C)Object.factory("foo.bar.C"); * assert(c !is null && c.x == 10); * } * --- */ static Object factory(string classname) { auto ci = TypeInfo_Class.find(classname); if (ci) { return ci.create(); } return null; } @system unittest { Object valid_obj = Object.factory("object.Object"); Object invalid_obj = Object.factory("object.__this_class_doesnt_exist__"); assert(valid_obj !is null); assert(invalid_obj is null); }} /++ Implementation for class opEquals override. Calls the class-defined methods after a null check. Please note this is not nogc right now, even if your implementation is, because of the typeinfo name string compare. This is because of dmd's dll implementation. However, it can infer to @safe if your class' opEquals is.+/bool opEquals(LHS, RHS)(LHS lhs, RHS rhs)if ((is(LHS : const Object) || is(LHS : const shared Object)) && (is(RHS : const Object) || is(RHS : const shared Object))){ static if (__traits(compiles, lhs.opEquals(rhs)) && __traits(compiles, rhs.opEquals(lhs))) { // If aliased to the same object or both null => equal if (lhs is rhs) return true; // If either is null => non-equal if (lhs is null || rhs is null) return false; if (!lhs.opEquals(rhs)) return false; // If same exact type => one call to method opEquals if (typeid(lhs) is typeid(rhs) || !__ctfe && typeid(lhs).opEquals(typeid(rhs))) /* CTFE doesn't like typeid much. 'is' works, but opEquals doesn't: https://issues.dlang.org/show_bug.cgi?id=7147 But CTFE also guarantees that equal TypeInfos are always identical. So, no opEquals needed during CTFE. */ { return true; } // General case => symmetric calls to method opEquals return rhs.opEquals(lhs); } else { // this is a compatibility hack for the old const cast behavior // if none of the new overloads compile, we'll go back plain Object, // including casting away const. It does this through the pointer // to bypass any opCast that may be present on the original class. return .opEquals!(Object, Object)(*cast(Object*) &lhs, *cast(Object*) &rhs); }} /// If aliased to the same object or both null => equal@system unittest // this one is not @safe because it goes through the Object base method{ class F { int flag; this(int flag) { this.flag = flag; } } F f; assert(f == f); // both null f = new F(1); assert(f == f); // both aliased to the same object} /// If either is null => non-equal@system unittest{ class F { int flag; this(int flag) { this.flag = flag; } } F f; assert(!(new F(0) == f)); assert(!(f == new F(0)));} /// If same exact type => one call to method opEquals/// This test passes `@safe` because it defines a new opEquals with `@safe`@safe unittest{ class F { int flag; this(int flag) { this.flag = flag; } bool opEquals(const F o) const @safe nothrow pure { return flag == o.flag; } } F f; assert(new F(0) == new F(0)); assert(!(new F(0) == new F(1)));} /// General case => symmetric calls to method opEquals@safe unittest{ int fEquals, gEquals; class Base { int flag; this(int flag) { this.flag = flag; } } class F : Base { this(int flag) { super(flag); } bool opEquals(const Base o) @safe { fEquals++; return flag == o.flag; } } class G : Base { this(int flag) { super(flag); } bool opEquals(const Base o) @safe { gEquals++; return flag == o.flag; } } assert(new F(1) == new G(1)); assert(fEquals == 1); assert(gEquals == 1);} /++ This test shows an example for a comprehensive inheritance equality chain too.+/unittest{ static class Base { int member; this(int member) pure @safe nothrow @nogc { this.member = member; } override bool opEquals(Object rhs) const { return this.opEquals(cast(Base) rhs); } bool opEquals(const Base rhs) const @nogc pure nothrow @safe { if (rhs is null) return false; return this.member == rhs.member; } } // works through the direct class with attributes enabled, except for pure and nogc in the current TypeInfo implementation bool testThroughBase() nothrow @safe { Base b1 = new Base(0); Base b2 = new Base(0); assert(b1 == b2); Base b3 = new Base(1); assert(b1 != b3); return true; } static assert(testThroughBase()); // also works through the base class interface thanks to the override, but no more attributes bool testThroughObject() { Object o1 = new Base(0); Object o2 = new Base(0); assert(o1 == o2); Object o3 = new Base(1); assert(o1 != o3); return true; } static assert(testThroughObject()); // Each time you make a child, you want to override all old opEquals // and add a new overload for the new child. static class Child : Base { int member2; this(int member, int member2) pure @safe nothrow @nogc { super(member); this.member2 = member2; } // override the whole chain so it works consistently though any base override bool opEquals(Object rhs) const { return this.opEquals(cast(Child) rhs); } override bool opEquals(const Base rhs) const { return this.opEquals(cast(const Child) rhs); } // and then add the new overload, if necessary, to handle new members bool opEquals(const Child rhs) const @nogc pure nothrow @safe { if (rhs is null) return false; // can call back to the devirtualized base test with implicit conversion // then compare the new member too. or we could have just compared the base // member directly here as well. return Base.opEquals(rhs) && this.member2 == rhs.member2; } // a mixin template, of course, could automate this. } bool testThroughChild() { Child a = new Child(0, 0); Child b = new Child(0, 1); assert(a != b); Base ba = a; Base bb = b; assert(ba != bb); Object oa = a; Object ob = b; assert(oa != ob);Lines 1–500 of 4936. Load more
/** * $(SCRIPT inhibitQuickIndex = 1;) * $(DIVC quickindex, * $(BOOKTABLE, * $(TR $(TH Category) $(TH Symbols)) * $(TR $(TD Arrays) $(TD * $(MYREF assumeSafeAppend) * $(MYREF capacity) * $(A #.dup.2, $(TT dup)) * $(MYREF idup) * $(MYREF reserve) * )) * $(TR $(TD Associative arrays) $(TD * $(MYREF byKey) * $(MYREF byKeyValue) * $(MYREF byValue) * $(MYREF clear) * $(MYREF dup) * $(MYREF get) * $(MYREF keys) * $(MYREF rehash) * $(MYREF require) * $(MYREF update) * $(MYREF values) * )) * $(TR $(TD General) $(TD * $(MYREF destroy) * $(MYREF hashOf) * $(MYREF imported) * $(MYREF noreturn) * )) * $(TR $(TD Classes) $(TD * $(MYREF Error) * $(MYREF Exception) * $(MYREF Object) * $(MYREF opEquals) * $(MYREF Throwable) * )) * $(TR $(TD Type info) $(TD * $(MYREF Interface) * $(MYREF ModuleInfo) * $(MYREF OffsetTypeInfo) * $(MYREF RTInfoImpl) * $(MYREF rtinfoNoPointers) * $(MYREF TypeInfo) * $(MYREF TypeInfo_Class) * )) * )) * * Forms the symbols available to all D programs. Includes Object, which is * the root of the class object hierarchy. This module is implicitly * imported. * * Copyright: Copyright Digital Mars 2000 - 2011. * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). * Authors: Walter Bright, Sean Kelly * Source: $(DRUNTIMESRC object.d) */ module object; alias size_t = typeof(int.sizeof); alias ptrdiff_t = typeof(cast(void*)0 - cast(void*)0); alias sizediff_t = ptrdiff_t; // For backwards compatibility only. /** * Bottom type. * See $(DDSUBLINK spec/type, noreturn, `noreturn`). */ alias noreturn = typeof(*null); alias hash_t = size_t; // For backwards compatibility only. alias equals_t = bool; // For backwards compatibility only. alias string = immutable(char)[]; alias wstring = immutable(wchar)[]; alias dstring = immutable(dchar)[]; version (D_ObjectiveC) { deprecated("explicitly import `selector` instead using: `import core.attribute : selector;`") public import core.attribute : selector; } version (Posix) public import core.attribute : gnuAbiTag; // Some ABIs use a complex varargs implementation requiring TypeInfo.argTypes(). version (GNU) { // No TypeInfo-based core.vararg.va_arg(). } else version (X86_64) { version (DigitalMars) version = WithArgTypes; else version (Windows) { /* no need for Win64 ABI */ } else version = WithArgTypes; } else version (AArch64) { // Apple uses a trivial varargs implementation version (DigitalMars) version = WithArgTypes; // is this needed? else version (OSX) {} else version (iOS) {} else version (TVOS) {} else version (WatchOS) {} else version = WithArgTypes; } /** * All D class objects inherit from Object. */ class Object { /** * Convert Object to a human readable string. */ string toString() { return typeid(this).name; } @system unittest { enum unittest_sym_name = __traits(identifier, __traits(parent, (){})); enum fqn_unittest = "object.Object." ~ unittest_sym_name; // object.__unittest_LX_CY class C {} Object obj = new Object; C c = new C; assert(obj.toString() == "object.Object"); assert(c.toString() == fqn_unittest ~ ".C"); } /** * Compute hash function for Object. */ size_t toHash() @trusted nothrow { // BUG: this prevents a compacting GC from working, needs to be fixed size_t addr = cast(size_t) cast(void*) this; // The bottom log2((void*).alignof) bits of the address will always // be 0. Moreover it is likely that each Object is allocated with a // separate call to malloc. The alignment of malloc differs from // platform to platform, but rather than having special cases for // each platform it is safe to use a shift of 4. To minimize // collisions in the low bits it is more important for the shift to // not be too small than for the shift to not be too big. return addr ^ (addr >>> 4); } /** * Compare with another Object obj. * Returns: * $(TABLE * $(TR $(TD this < obj) $(TD < 0)) * $(TR $(TD this == obj) $(TD 0)) * $(TR $(TD this > obj) $(TD > 0)) * ) */ int opCmp(Object o) { // BUG: this prevents a compacting GC from working, needs to be fixed //return cast(int)cast(void*)this - cast(int)cast(void*)o; throw new Exception("need opCmp for class " ~ typeid(this).name); //return this !is o; } @system unittest { Object obj = new Object; bool gotCaught; try { obj.opCmp(new Object); } catch (Exception e) { gotCaught = true; assert(e.msg == "need opCmp for class object.Object"); } assert(gotCaught); } /** * Test whether $(D this) is equal to $(D o). * The default implementation only compares by identity (using the $(D is) operator). * Generally, overrides and overloads for $(D opEquals) should attempt to compare objects by their contents. * A class will most likely want to add an overload that takes your specific type as the argument * and does the content comparison. Then you can override this and forward it to your specific * typed overload with a cast. Remember to check for `null` on the typed overload. * * Examples: * --- * class Child { * int contents; * // the typed overload first. It can use all the attribute you want * bool opEquals(const Child c) const @safe pure nothrow @nogc * { * if (c is null) * return false; * return this.contents == c.contents; * } * * // and now the generic override forwards with a cast * override bool opEquals(Object o) * { * return this.opEquals(cast(Child) o); * } * } * --- */ bool opEquals(Object o) { return this is o; } interface Monitor { void lock(); void unlock(); } /** * Create instance of class specified by the fully qualified name * classname. * The class must either have no constructors or have * a default constructor. * Returns: * null if failed * Example: * --- * module foo.bar; * * class C * { * this() { x = 10; } * int x; * } * * void main() * { * auto c = cast(C)Object.factory("foo.bar.C"); * assert(c !is null && c.x == 10); * } * --- */ static Object factory(string classname) { auto ci = TypeInfo_Class.find(classname); if (ci) { return ci.create(); } return null; } @system unittest { Object valid_obj = Object.factory("object.Object"); Object invalid_obj = Object.factory("object.__this_class_doesnt_exist__"); assert(valid_obj !is null); assert(invalid_obj is null); } } /++ Implementation for class opEquals override. Calls the class-defined methods after a null check. Please note this is not nogc right now, even if your implementation is, because of the typeinfo name string compare. This is because of dmd's dll implementation. However, it can infer to @safe if your class' opEquals is. +/ bool opEquals(LHS, RHS)(LHS lhs, RHS rhs) if ((is(LHS : const Object) || is(LHS : const shared Object)) && (is(RHS : const Object) || is(RHS : const shared Object))) { static if (__traits(compiles, lhs.opEquals(rhs)) && __traits(compiles, rhs.opEquals(lhs))) { // If aliased to the same object or both null => equal if (lhs is rhs) return true; // If either is null => non-equal if (lhs is null || rhs is null) return false; if (!lhs.opEquals(rhs)) return false; // If same exact type => one call to method opEquals if (typeid(lhs) is typeid(rhs) || !__ctfe && typeid(lhs).opEquals(typeid(rhs))) /* CTFE doesn't like typeid much. 'is' works, but opEquals doesn't: https://issues.dlang.org/show_bug.cgi?id=7147 But CTFE also guarantees that equal TypeInfos are always identical. So, no opEquals needed during CTFE. */ { return true; } // General case => symmetric calls to method opEquals return rhs.opEquals(lhs); } else { // this is a compatibility hack for the old const cast behavior // if none of the new overloads compile, we'll go back plain Object, // including casting away const. It does this through the pointer // to bypass any opCast that may be present on the original class. return .opEquals!(Object, Object)(*cast(Object*) &lhs, *cast(Object*) &rhs); } } /// If aliased to the same object or both null => equal @system unittest // this one is not @safe because it goes through the Object base method { class F { int flag; this(int flag) { this.flag = flag; } } F f; assert(f == f); // both null f = new F(1); assert(f == f); // both aliased to the same object } /// If either is null => non-equal @system unittest { class F { int flag; this(int flag) { this.flag = flag; } } F f; assert(!(new F(0) == f)); assert(!(f == new F(0))); } /// If same exact type => one call to method opEquals /// This test passes `@safe` because it defines a new opEquals with `@safe` @safe unittest { class F { int flag; this(int flag) { this.flag = flag; } bool opEquals(const F o) const @safe nothrow pure { return flag == o.flag; } } F f; assert(new F(0) == new F(0)); assert(!(new F(0) == new F(1))); } /// General case => symmetric calls to method opEquals @safe unittest { int fEquals, gEquals; class Base { int flag; this(int flag) { this.flag = flag; } } class F : Base { this(int flag) { super(flag); } bool opEquals(const Base o) @safe { fEquals++; return flag == o.flag; } } class G : Base { this(int flag) { super(flag); } bool opEquals(const Base o) @safe { gEquals++; return flag == o.flag; } } assert(new F(1) == new G(1)); assert(fEquals == 1); assert(gEquals == 1); } /++ This test shows an example for a comprehensive inheritance equality chain too. +/ unittest { static class Base { int member; this(int member) pure @safe nothrow @nogc { this.member = member; } override bool opEquals(Object rhs) const { return this.opEquals(cast(Base) rhs); } bool opEquals(const Base rhs) const @nogc pure nothrow @safe { if (rhs is null) return false; return this.member == rhs.member; } } // works through the direct class with attributes enabled, except for pure and nogc in the current TypeInfo implementation bool testThroughBase() nothrow @safe { Base b1 = new Base(0); Base b2 = new Base(0); assert(b1 == b2); Base b3 = new Base(1); assert(b1 != b3); return true; } static assert(testThroughBase()); // also works through the base class interface thanks to the override, but no more attributes bool testThroughObject() { Object o1 = new Base(0); Object o2 = new Base(0); assert(o1 == o2); Object o3 = new Base(1); assert(o1 != o3); return true; } static assert(testThroughObject()); // Each time you make a child, you want to override all old opEquals // and add a new overload for the new child. static class Child : Base { int member2; this(int member, int member2) pure @safe nothrow @nogc { super(member); this.member2 = member2; } // override the whole chain so it works consistently though any base override bool opEquals(Object rhs) const { return this.opEquals(cast(Child) rhs); } override bool opEquals(const Base rhs) const { return this.opEquals(cast(const Child) rhs); } // and then add the new overload, if necessary, to handle new members bool opEquals(const Child rhs) const @nogc pure nothrow @safe { if (rhs is null) return false; // can call back to the devirtualized base test with implicit conversion // then compare the new member too. or we could have just compared the base // member directly here as well. return Base.opEquals(rhs) && this.member2 == rhs.member2; } // a mixin template, of course, could automate this. } bool testThroughChild() { Child a = new Child(0, 0); Child b = new Child(0, 1); assert(a != b); Base ba = a; Base bb = b; assert(ba != bb); Object oa = a; Object ob = b; assert(oa != ob);