www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Suggestion: Walter Bright, why not to implement multiple inheritance in D?

reply Arlen Albert Keshabyan <arlen.albert gmail.com> writes:
Recently, I've started the subject about multiple inheritance in D. I've got
the answers. But those solutions are not enough suitable for my purposes. Then
I thought, why not to implement the feature which is on demand by programmers
in D? Multiple inheritance is needed indeed just only by seeing the attempts
of programmers to emulate it in D. It means they need it. Multiple inheritance
is really not that bad thing which is supposed to be got rid of. Just a linear
multiple inheritance with possibility to get to the every level of its
hierarchy is enough, I think. Moreover, I'll help to port many useful C++ code
into D much easier than now.

I know two approaches by now, but both are restrictive to feel the freedom of
multiple inheritance.

First approach is excellent, but does not allow you to get as deep as you want
to the class hierarchy (only super's virtual methods are accessible explicitly):

//////////////////////////////////
interface I
{
}

class A(T) : T, I
{
}

class B(T) : T, I
{
}

class C(T) : T, I
{
}

alias C!(B!(A(Object))) D;
////////////////////////////////

Second approach is excellent too, but lacks template merging possibilities and
pointing explicitly which interface function to implement (on name collisions):

//////////////////////////////////////
interface A
{
}

interface B
{
}

interface C
{
}

template A_()
{
}

template B_()
{
}

template C_()
{
}

class D : A, B, C
{
   mixin A_;
   mixin B_;
   mixin C_;
}
////////////////////////////////

Walter, is it a matter of principle not to implement multiple inheritance in
D? If D is the language of practical usage then multiple inheritance must be
considered to implement.
What do you think?
Dec 01 2006
next sibling parent Justin C Calvarese <technocrat7 gmail.com> writes:
Arlen Albert Keshabyan wrote:
 Recently, I've started the subject about multiple inheritance in D. I've got
 the answers. But those solutions are not enough suitable for my purposes. Then
 I thought, why not to implement the feature which is on demand by programmers
 in D? Multiple inheritance is needed indeed just only by seeing the attempts
 of programmers to emulate it in D. It means they need it. Multiple inheritance
 is really not that bad thing which is supposed to be got rid of. Just a linear
 multiple inheritance with possibility to get to the every level of its
 hierarchy is enough, I think. Moreover, I'll help to port many useful C++ code
 into D much easier than now.

This has been discussed to death in the past. Feel free to read up on the past arguments. Here's a couple threads to get you started (I'm sure more threads are out there)... 16 Aug 2001: http://www.digitalmars.com/d/archives/43.html 18 Mar 2004: http://www.digitalmars.com/d/archives/25807.html I think the bottom line is the multiple inheritance would added too much complexity for too little benefit. If the program has been designed in C++, it might need some re-design to bring it into D. -- jcc7
Dec 01 2006
prev sibling next sibling parent Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
Arlen Albert Keshabyan wrote:
 Recently, I've started the subject about multiple inheritance in D. I've got
 the answers. But those solutions are not enough suitable for my purposes. Then
 I thought, why not to implement the feature which is on demand by programmers
 in D? Multiple inheritance is needed indeed just only by seeing the attempts
 of programmers to emulate it in D. It means they need it. Multiple inheritance
 is really not that bad thing which is supposed to be got rid of. Just a linear
 multiple inheritance with possibility to get to the every level of its
 hierarchy is enough, I think. Moreover, I'll help to port many useful C++ code
 into D much easier than now.
 
 I know two approaches by now, but both are restrictive to feel the freedom of
 multiple inheritance.
 
 First approach is excellent, but does not allow you to get as deep as you want
 to the class hierarchy (only super's virtual methods are accessible
explicitly):
 
 //////////////////////////////////
 interface I
 {
 }
 
 class A(T) : T, I
 {
 }
 
 class B(T) : T, I
 {
 }
 
 class C(T) : T, I
 {
 }
 
 alias C!(B!(A(Object))) D;
 ////////////////////////////////
 
 Second approach is excellent too, but lacks template merging possibilities and
 pointing explicitly which interface function to implement (on name collisions):
 
 //////////////////////////////////////
 interface A
 {
 }
 
 interface B
 {
 }
 
 interface C
 {
 }
 
 template A_()
 {
 }
 
 template B_()
 {
 }
 
 template C_()
 {
 }
 
 class D : A, B, C
 {
    mixin A_;
    mixin B_;
    mixin C_;
 }
 ////////////////////////////////
 
 Walter, is it a matter of principle not to implement multiple inheritance in
 D? If D is the language of practical usage then multiple inheritance must be
 considered to implement.
 What do you think?

I'm not Walter, and I'm no expert in the implementation of languages, and I am in fact guilty of using multiple inheritance often enough... But I will say this much. I've been working on implementing my own BovisMOO language for a project, and within Bovis I've allowed for multiple inheritance, despite its predecessor (LambdaMOO) being strictly single inheritance. Which caused a very simple lookup which looked roughly (pseudo-code) like this: # while (obj && !(pname in obj.fieldDefinitions)) { obj = obj.parent; } # if (obj is null) { # // no such property error, throw an exception # } # // do work with the property To now look like this: # if (!(pname in obj.fieldDefinitions)) { # foreach (o; &obj.traverseAncestryBreadthFirstEnsuredOnce) { # if (pname in o.fieldDefinitions) { # obj = o; # break; # } # if (o is Database.instance.rootObject) { # // no such property error, throw an exception # } # } # } # // so do work with the property All off the top of my head, but that's more-or-less how it goes. Yes, it does work, but it sure became a lot uglier and a lot less efficient... and this is just for a weak-typed little scripting language with no concepts of classes or interfaces! I can only imagine what horrors it might lead to in a full systems programming language with rich OOP features. I'd say the main reason it isn't there, is to prevent Walter from having migraines. And I don't consider that a completely unmerited excuse. :) -- Chris Nicholson-Sauls
Dec 01 2006
prev sibling next sibling parent reply Gregor Richards <Richards codu.org> writes:
Arlen Albert Keshabyan wrote:
 Recently, I've started the subject about multiple inheritance in D. I've got
 the answers. But those solutions are not enough suitable for my purposes. Then
 I thought, why not to implement the feature which is on demand by programmers
 in D? Multiple inheritance is needed indeed just only by seeing the attempts
 of programmers to emulate it in D. It means they need it. Multiple inheritance
 is really not that bad thing which is supposed to be got rid of. Just a linear
 multiple inheritance with possibility to get to the every level of its
 hierarchy is enough, I think. Moreover, I'll help to port many useful C++ code
 into D much easier than now.
 
 I know two approaches by now, but both are restrictive to feel the freedom of
 multiple inheritance.
 
 First approach is excellent, but does not allow you to get as deep as you want
 to the class hierarchy (only super's virtual methods are accessible
explicitly):
 
 Walter, is it a matter of principle not to implement multiple inheritance in
 D?

No.
 If D is the language of practical usage then multiple inheritance must be
 considered to implement.

Yeah, obviously. I mean, who the hell uses Java or C#?
 What do you think?

Multiple inheritance is a terrible idea on at least two levels: 1) In class trees with functions or (worse yet) variables with the same name at different levels, it's confusing to the programmer to figure out what name maps to what. 2) The way OO is implemented in 99% of compiled programming languages, multiple inheritance is impossible. Let me explain: // this is the structure representing an object struct Object { struct ClassInfo *classInfo; struct RandomGarbage whateverTheLanguageNeeds; // variables go here } // this is the structure representing a class struct ClassInfo { struct ClassInfo *parent; // <many other things> void **vtable; } vtable is an array of function pointers, like so for example class A.vtable = 0 -> foo() 1 -> foo(int) now imagine we have a class derived from the one described above. To make it usable as the base class, it has a vtable like this class A(B).vtable = 0 -> foo() 1 -> foo(int) 2 -> bar() 3 -> bar(float) Hey presto! If you pass in an object with this vtable, it will work for both, because calling the function foo just involves calling vtable[0]! Now, imagine the multiple-inheritance scenario. We have these two classes: class A.vtable = 0 -> foo() 1 -> foo(int) class B.vtable = 0 -> baf() 1 -> baf(Object) Now we'd like to make a class C derived from both A and B: class C(A, B).vtable = 0 -> ??? 1 -> ??? 2 -> (C's own functions) Now can you see the problem? We can't simply dereference vtable[0] or vtable[1] to get the proper function, because there are two different classes, each with their own vtable[0] and vtable[1]. There are solutions to this (obviously, since C++ works), but they're usually arcane and always inefficient. - Gregor Richards
Dec 01 2006
next sibling parent Gregor Richards <Richards codu.org> writes:
Addendum:
Incidentally, it's usually considered bad form to use multiple 
inheritance in C++.

  - Gregor Richards
Dec 01 2006
prev sibling next sibling parent Kyle Furlong <kylefurlong gmail.com> writes:
Gregor Richards wrote:
 Arlen Albert Keshabyan wrote:
 Recently, I've started the subject about multiple inheritance in D. 
 I've got
 the answers. But those solutions are not enough suitable for my 
 purposes. Then
 I thought, why not to implement the feature which is on demand by 
 programmers
 in D? Multiple inheritance is needed indeed just only by seeing the 
 attempts
 of programmers to emulate it in D. It means they need it. Multiple 
 inheritance
 is really not that bad thing which is supposed to be got rid of. Just 
 a linear
 multiple inheritance with possibility to get to the every level of its
 hierarchy is enough, I think. Moreover, I'll help to port many useful 
 C++ code
 into D much easier than now.

 I know two approaches by now, but both are restrictive to feel the 
 freedom of
 multiple inheritance.

 First approach is excellent, but does not allow you to get as deep as 
 you want
 to the class hierarchy (only super's virtual methods are accessible 
 explicitly):

 Walter, is it a matter of principle not to implement multiple 
 inheritance in
 D?

No.
 If D is the language of practical usage then multiple inheritance must be
 considered to implement.

Yeah, obviously. I mean, who the hell uses Java or C#?
 What do you think?

Multiple inheritance is a terrible idea on at least two levels: 1) In class trees with functions or (worse yet) variables with the same name at different levels, it's confusing to the programmer to figure out what name maps to what. 2) The way OO is implemented in 99% of compiled programming languages, multiple inheritance is impossible. Let me explain: // this is the structure representing an object struct Object { struct ClassInfo *classInfo; struct RandomGarbage whateverTheLanguageNeeds; // variables go here } // this is the structure representing a class struct ClassInfo { struct ClassInfo *parent; // <many other things> void **vtable; } vtable is an array of function pointers, like so for example class A.vtable = 0 -> foo() 1 -> foo(int) now imagine we have a class derived from the one described above. To make it usable as the base class, it has a vtable like this class A(B).vtable = 0 -> foo() 1 -> foo(int) 2 -> bar() 3 -> bar(float) Hey presto! If you pass in an object with this vtable, it will work for both, because calling the function foo just involves calling vtable[0]! Now, imagine the multiple-inheritance scenario. We have these two classes: class A.vtable = 0 -> foo() 1 -> foo(int) class B.vtable = 0 -> baf() 1 -> baf(Object) Now we'd like to make a class C derived from both A and B: class C(A, B).vtable = 0 -> ??? 1 -> ??? 2 -> (C's own functions) Now can you see the problem? We can't simply dereference vtable[0] or vtable[1] to get the proper function, because there are two different classes, each with their own vtable[0] and vtable[1]. There are solutions to this (obviously, since C++ works), but they're usually arcane and always inefficient. - Gregor Richards

The Gregor (tm) strikes again!
Dec 02 2006
prev sibling parent reply Burton Radons <burton-radons smocky.com> writes:
Gregor Richards wrote:
 Now we'd like to make a class C derived from both A and B:
 class C(A, B).vtable =
 0 -> ???
 1 -> ???
 2 -> (C's own functions)
 
 Now can you see the problem? We can't simply dereference vtable[0] or 
 vtable[1] to get the proper function, because there are two different 
 classes, each with their own vtable[0] and vtable[1].
 
 There are solutions to this (obviously, since C++ works), but they're 
 usually arcane and always inefficient.

The solutions to getting around MI when it's necessary are by their very exclusion from base language features always arcane, often inefficient, and almost always incomplete. The language-standard D solution is mixins, which I am certain are a bad idea even if they worked better than they do. I don't have a perfect solution to the problem; there is none because it's asking two objects to exist in one space and we need to resolve that. But given that multiple inheritance is sometimes necessary, waving it off as "too complex" or "bad form" is impractical; like any type of suppression, that only leads to cracking and nasty leaks (mixins). I have an idea. Let's try making this assertion: no type will have in its inheritance tree another type multiple times without being an abuse of multiple inheritance. Given this statement, can anyone find an exception, where MI is not just being used to alias an object to multiple types (and would therefore be better handled with a field)? Because if that statement is true, then the biggest problem in multiple inheritance can be ignored because all non-abusive usages of it would be resolvable into a clean array, no more difficult than single inheritance, except that methods that exist in more than one separate hierarchies should disappear without manual overloading. What I mean is: class A { void foo (int); } class B { void foo (float); } class C : A, B { void bar () { foo (16); } // Invalid because foo exists in both A and B. If we overloaded them, it would be like selecting between two functions from different modules. So for language consistency's sake, foo is not visible here. } class D : A, B { void foo (int x) { A.foo (x); } void foo (float x) { B.foo (x); } void bar () { foo (16); } // But this is okay. } Or better yet: class E : A, B { alias A.foo; alias B.foo; } The key is in not disallowing something just because it's difficult, but because it's wrong, always wrong, negative index on an array wrong. I'm inclined to think my assertion must be correct, but I can't quite discern the law ruling it. One way in which it is ALWAYS correct is with patterns like this: interface I { void foo (); } class A : I { void foo () { ... } } class B : I { void foo () { ... } } class C : A, B { } This is because A and B's implementation of foo must be different, so the user is literally asking two objects to exist in one point at the same time, which is not logical. The inheritor cannot confidently select between them with any consistency (which is the fallback MI languages use if they are intelligent enough to notice the problem at all), because he cannot consistently know what either of those methods do (if the method's changed over time, or is written by another maintainer). Since this is an unsolvable ambiguity, it must be wrong to do this. Gregor Richards wrote:
 Addendum:
 Incidentally, it's usually considered bad form to use multiple
 inheritance in C++.

Yeah, but C++ programmers are programming in C++. The hell do they know about good language practices? ;-)
Dec 02 2006
parent reply Larry Evans <cppljevans cos-internet.com> writes:
On 12/02/2006 09:27 AM, Burton Radons wrote:
[snip]
 I don't have a perfect solution to the problem; there is none because 
 it's asking two objects to exist in one space and we need to resolve 
 that. But given that multiple inheritance is sometimes necessary, waving 
 it off as "too complex" or "bad form" is impractical; like any type of 
 suppression, that only leads to cracking and nasty leaks (mixins).
 
 I have an idea. Let's try making this assertion: no type will have in 
 its inheritance tree another type multiple times without being an abuse 
 of multiple inheritance. Given this statement, can anyone find an 

 Yeah, but C++ programmers are programming in C++. The hell do they know 
 about good language practices? ;-)

How would the D equivalent to mpl::inherit_linearly<, inherit<,>, > (see http://www.boost.org/libs/mpl/doc/refmanual/inherit-linearly.html) work without using the MI class, inherit?
Dec 02 2006
next sibling parent Kyle Furlong <kylefurlong gmail.com> writes:
Larry Evans wrote:
 On 12/02/2006 09:27 AM, Burton Radons wrote:
 [snip]
 I don't have a perfect solution to the problem; there is none because 
 it's asking two objects to exist in one space and we need to resolve 
 that. But given that multiple inheritance is sometimes necessary, 
 waving it off as "too complex" or "bad form" is impractical; like any 
 type of suppression, that only leads to cracking and nasty leaks 
 (mixins).

 I have an idea. Let's try making this assertion: no type will have in 
 its inheritance tree another type multiple times without being an 
 abuse of multiple inheritance. Given this statement, can anyone find an 

 Yeah, but C++ programmers are programming in C++. The hell do they 
 know about good language practices? ;-)

How would the D equivalent to mpl::inherit_linearly<, inherit<,>, > (see http://www.boost.org/libs/mpl/doc/refmanual/inherit-linearly.html) work without using the MI class, inherit?

God, Boost makes me want to stab my eyes out.
Dec 02 2006
prev sibling next sibling parent reply Walter Bright <newshound digitalmars.com> writes:
Larry Evans wrote:
 How would the D equivalent to mpl::inherit_linearly<, inherit<,>, >
 (see http://www.boost.org/libs/mpl/doc/refmanual/inherit-linearly.html)
 work without using the MI class, inherit?

I would suggest using instead D's ability to declare the members of a struct using tuples.
Dec 02 2006
parent reply Larry Evans <cppljevans cos-internet.com> writes:
On 12/02/2006 09:33 PM, Walter Bright wrote:
 Larry Evans wrote:
 
 How would the D equivalent to mpl::inherit_linearly<, inherit<,>, >
 (see http://www.boost.org/libs/mpl/doc/refmanual/inherit-linearly.html)
 work without using the MI class, inherit?

I would suggest using instead D's ability to declare the members of a struct using tuples.

Now, I've another use of c++ MI, and I'm wondering how to do the equivalent in D. This use involves "dynamic inheritance" which is somewhat like the 12.7 Delegation in Stroustrup's _Design and Evolution of c++_. The code is used here: http://preview.tinyurl.com/wwsee The test code is in the corresponding libs/grammar_pipeline/test directory. One application of such dynamic inheritance was discussed here: http://article.gmane.org/gmane.comp.lib.boost.devel/99421 Of course, a more concrete application was in the aforementioned tinurl reference. So...how would this be done in D? Since the above application involved calculating grammar lookahead sets, and since you're interested in emulating spirit in D, this might provide some further motivation for finding a D equivalent :)
Dec 10 2006
parent reply Walter Bright <newshound digitalmars.com> writes:
Larry Evans wrote:
 So...how would this be done in D?  Since the above application involved 
 calculating grammar lookahead sets, and since you're interested in
 emulating spirit in D, this might provide some further motivation
 for finding a D equivalent :)

Could you provide a distilled explanation of what dynamic inheritance is?
Dec 12 2006
parent Larry Evans <cppljevans cos-internet.com> writes:
On 12/12/2006 09:49 PM, Walter Bright wrote:
 Larry Evans wrote:

 So...how would this be done in D?  Since the above application
 involved calculating grammar lookahead sets, and since you're
 interested in
 emulating spirit in D, this might provide some further motivation
 for finding a D equivalent :)

Could you provide a distilled explanation of what dynamic inheritance is?

:* Distilled_Explanation: Dynamic Inheritance (a.k.a. DI, as coded here: in http://tinyurl.com/yd7ean ) is really nothing more than the "infrastructure" for implementing "Dynamic Dual Heirarchies" as described on p. 5 of: http://www.objectmentor.com/resources/articles/dih.pdf which says: A dual heirarchy is like a ladder. The two inheritance heirarchies are the supports of the ladder, and in the INTELLIGENT CHILDREN pattern above, the 'has' relationships in the peers are the rungs of the ladder. An "abstract" picture of such a dual heirarchy is in figure 3 on p. 4. The left side of figure 3 is closer to DI than the right side. This is because the 'has' relationship is stored in the base class ( DI's dyn_inherit::inherit<,,>::super_type::my_ref, corresponding to figure 3's right-pointing solid arrow from B1 to B2). Thus, DI's inherit<,,> corresponds to figure 3's B1 and DI's inherit's DynSupertype template parameter corresponds to figure 3's B2. A more "concrete" picture is figure 2, where lhs of figure 3's B1 corresponds to figure 2's Observer, and lhs of figure 3's B2 corresponds to figure 2's Subject. In contrast to the Observer pattern which figure 2 describes, DI just has one pointer (as opposed to a set of pointers) from B2 (Subject) to B1 (Observers). This single pointer is stored in the dyn_inherit::base::my_subtype member of the DynSupertype of inherit (note the REQUIREMENTS: comment after DynSupertype specifying that it's derived from dyn_inherit::base). :* Preliminary_Conclusion Well, Walter, after I complete the :* Distilled_Explanation below, I realized there's probably no need for Proxy<> supertype of dyn_inherit::inherit, Instead this class could be made a field and the "relevant" function calls forwarded to the Proxy<>::get_ref() as done with the current implementation (e.g. as done by the eff::exp_tree::top::begin method here: http://tinyurl.com/yht62d ). However, that still leaves the dyn_inherit::base and DeltaType supertypes of dyn_inherit::inherit. So..., how would dyn_inherit::inherit be coded in D? ;* Name_and_Location_Rationale: Some of the names (for example DynSuperType and DeltaType for the 1st and 2nd inherit template arguments) may seem mysterious. The following explains how these names were selected. :** DynSuperType_Rationale: The reason for the DynSuperType (and it's inclusion in the Proxy<DynSuperType> supertype of inherit) is that type inherit supertype is "supposed" to correspond to the *p supertype of C in: class C : *p { ... }; from section 12.7, "Delegation", of Stroustrup's _Design & Evolution of C++_. The reason for the "supposed" qualifier above is that there's no automatic forwarding to *p as described in section 12.7. Since D has delegates, I thought maybe D could do this forwarding ( I confess, I've not written a single D program yet ). However, after reading: http://www.digitalmars.com/d/type.html#delegates I guess not, since delegates point to single functions instead of to classes :( . Would Mixin's be any help?. Well, http://www.digitalmars.com/d/mixin.html seems to say that a select set of declarations are *copied* from one context into another; however, what I want needed is delegation to each of the selected functions in the source context (i.e. the SynSuperType). Hence, I guess mixins wouldn't help either :( :** DeltaType_Rationale: The Delta comes from p. 2 of _Mixin-based Inheritance_ by Braca and Cook, which is available here: http://citeseer.ist.psu.edu/bracha90mixinbased.html . This Mixin part of the title tempts me to rethink whether D's mixin's can be some help, but, as mentioned above, I've not yet written a D program. I guess I should start ;) .
Dec 21 2006
prev sibling parent reply Burton Radons <burton-radons smocky.com> writes:
Larry Evans wrote:
 On 12/02/2006 09:27 AM, Burton Radons wrote:
 [snip]
 I don't have a perfect solution to the problem; there is none because 
 it's asking two objects to exist in one space and we need to resolve 
 that. But given that multiple inheritance is sometimes necessary, 
 waving it off as "too complex" or "bad form" is impractical; like any 
 type of suppression, that only leads to cracking and nasty leaks 
 (mixins).

 I have an idea. Let's try making this assertion: no type will have in 
 its inheritance tree another type multiple times without being an 
 abuse of multiple inheritance. Given this statement, can anyone find an 

 Yeah, but C++ programmers are programming in C++. The hell do they 
 know about good language practices? ;-)

How would the D equivalent to mpl::inherit_linearly<, inherit<,>, > (see http://www.boost.org/libs/mpl/doc/refmanual/inherit-linearly.html) work without using the MI class, inherit?

That's a good example. Here's another from Wikipedia: Animal Mammal : Animal Winged : Animal Bat : Mammal, Winged Contrived but not unreasonable, but I think the problem I gave applies even if they don't override any of the parent methods, just as a pure maintainer problem of the subclasses depending upon the implementation of the parent class. We could restrict diamonds to interfaces, like it's done now, but that feels like a hack and doesn't actually solve the problem - in fact, it makes the problem necessary. Damn. I retract my challenge. Perhaps we're trying to shoehorn two types of inheritance into one tree. Something that's Winged is an Animal, but it's not a /complete/ animal; it's not going to have any opinion on its feeding habits. So we could use: Animal Mammal : Animal Winged : abstract Animal Bat : Mammal, Winged And allow the diamond because Winged can't override anything from Animal. This is bad because Animal might have stuff Winged has an opinion on, but more discrete selections of inheritance (which are a good idea anyway) allows us to defeat the diamond when we need to: Reproduction Movement Animal : Reproduction, Movement Mammal : abstract Animal, Reproduction Winged : abstract Animal, Movement Bat : Mammal, Winged In this case Mammal and Winged are exclusive, so the tree works properly. I'd analyse your example more but I'm unfamiliar with Boost. Can you factor the problem so that it can be expressed in terms of animals? :-)
Dec 02 2006
parent Larry Evans <cppljevans cos-internet.com> writes:
On 12/02/2006 10:11 PM, Burton Radons wrote:
 Larry Evans wrote:
 
 On 12/02/2006 09:27 AM, Burton Radons wrote:


 And allow the diamond because Winged can't override anything from 
 Animal. This is bad because Animal might have stuff Winged has an 
 opinion on, but more discrete selections of inheritance (which are a 
 good idea anyway) allows us to defeat the diamond when we need to:
 
     Reproduction
     Movement
     Animal : Reproduction, Movement
     Mammal : abstract Animal, Reproduction
     Winged : abstract Animal, Movement
     Bat : Mammal, Winged
 
 In this case Mammal and Winged are exclusive, so the tree works properly.
 
 I'd analyse your example more but I'm unfamiliar with Boost. Can you 
 factor the problem so that it can be expressed in terms of animals? :-)

Well, I'm kinda agreeing with Walter. AFAICT, the example in boost which used inherit was used to create a tuple, and since there's now a better way (as Walter pointed-out), I'm reluctant to try. However, if I did, there would be a problem with the abstract Animal (or virtual Animal in c++ case). I don't see a way that can be done with c++ metaprogramming since all the args to boost::mpl::inherit have to be types, and, AFAICT, there's no type, virtual X, for any type X, in c++.
Dec 04 2006
prev sibling parent reply Burton Radons <burton-radons smocky.com> writes:
As an aside to Walter, I stumbled on a solution to the multiple vtable 
problem a couple years ago. Instead of putting the vtable in the object, 
you put it in the reference, like with a delegate. Then if an object is 
posing as a base type, you just select an appropriate vtable and offset 
the pointer. That way you don't need to worry about trying to fit 
vtables into base types, although you still need to put offsets into the 
vtable for mutual base types in the (A; B : A; C : A; D : B, C) case for 
field pointers. Didn't say it was a panacea.

It's no good for D, though. Too bad because (even without MI) it would 
easily allow other functionality. There's no reason then to keep value 
and reference types separate, for example, and a mostly-equivalent 
vtable can be selected based upon contextual needs. I had an example for 
why you'd want to do that around but I can't remember it now.

Ah, here's one: say you take a reference of a middle value in an array. 
If someone tries to delete this reference, you can either delete the 
whole array (bad), sigsegv (bad), ignore it because it's not a pointer 
to the beginning of the block (bad because if it were a reference to the 
first array element it would still be nonsensical to delete it but it 
would work), ignore it because it's a reference to an array element 
(better, and possible with the scheme here), or remove it from the array 
(which is probably best but depends upon storing the length with the 
array data, which might be more correct overall but has too many bad 
points to counter its few good ones. But if arrays WERE implemented like 
that, this scheme would allow that to happen efficiently).

It'd remove the need for boxing, too, since you could just convert a 
value into a reference, cast it to void&, then try to cast it back into 
a value type.

It's a little faster on dispatch, of course; one less pointer to follow. 
Likely a little slower when all's considered.

Oh well, stuff for my language, if I ever get around to that.
Dec 02 2006
parent reply Walter Bright <newshound digitalmars.com> writes:
Burton Radons wrote:
 As an aside to Walter, I stumbled on a solution to the multiple vtable 
 problem a couple years ago. Instead of putting the vtable in the object, 
 you put it in the reference, like with a delegate. Then if an object is 
 posing as a base type, you just select an appropriate vtable and offset 
 the pointer.

That is a good idea.
Dec 02 2006
parent BCS <BCS pathilink.com> writes:
Walter Bright wrote:
 Burton Radons wrote:
 As an aside to Walter, I stumbled on a solution to the multiple vtable 
 problem a couple years ago. Instead of putting the vtable in the 
 object, you put it in the reference, like with a delegate. Then if an 
 object is posing as a base type, you just select an appropriate vtable 
 and offset the pointer.

That is a good idea.

That is how I think interfaces should work. It has a whole host of cool implications: interfaces from structs, functions, on-the-fly literals or wherever delegates can be done. Make a .tupleof for interfaces, and a template could even build one. (I'll get off of my soap box now) <g>
Dec 02 2006