Re: Multiple dispatch
===================================== MODERATOR'S COMMENT:
Please remove excessive quoting when replying.
===================================== END OF MODERATOR'S COMMENT
On Mar 19, 10:05 pm, "Grizlyk" <grizl...@yandex.ru> wrote:
jam wrote:
struct A{
virtual void go();
};
struct B{
virtual void go();
};
struct C{
virtual void go();
};
struct D{
virtual void go();
};
if a class inherits any two of the above then it will have to define
its own version of go that will replace in both vtables inherited.
Here is a humble syntax proposal:
struct all: A,B,C,D{
// here is the syntax:
void go() A{cout<<'A';};//override A::go
void go() B{cout<<'B';};//override B::go
void go(){cout<<"all";};//used for C,D and all
};
all * ptr=new all;
ptr->go();//prints 'all'
((A*)ptr)->go();//prints 'A'
((B*)ptr)->go();//prints 'B'
((C*)ptr)->go();//prints 'all'
((D*)ptr)->go();//prints 'all'
vtables of A and B got different versions of go than C and D and if
any class inherits 'struct all' then by default it will use theversoin
of go that prints 'all' unless it is casted to A or be or redefines
go.
Probably it can be done, but for
void go(){cout<<"all";}; //used for C,D and all
you will need entry in vtable of struct "all" for "all::go()", that
normally can be avoided (any vtable of base class can be used to find
"(all*)(ptr)->go();" ).
the order by which the types are phsically inherited is even currently
affected by polymorphic bases. On VC7 the first subobject is the first
polymorphic subobject if there is any.So either C or D could be placed
at the beginning by the compiler .In special cases where all
subobjects have distinct overrides of their own (that is A,B,C and D
each have a specialized vesoin of 'go' ) introducing a general
override(the one printing 'all' in the above example would necessitate
an extra vtable.
But what the practical puprose of the kind of separatedly overloaded
base methods? I do not see any.
suppose 'all' is inheriting from multiple classes defined in different
libraries having functions with similar names and signatures but
different purposes.You can not specify one override for both because
they have different goals and accidentally same names.This becomes a
major problem specially when trying to model C# and JAVA interfaces as
abstract claases containing abstract functions;Now what happens if two
or more of such interface-ish abstract bases have a function with same
name and prototype(as you know interfaces - in contrast to classes -
are multiply inherited in C# and java and the implementing class
defines them as members of the deffining interface)?
Also why have you called this stuff as "multiple dispath"? It looks
like special implemetation of "single dispatch" with "type of class"
as single dispatch selector.
As i know multiple dispatch is something, that has other dispath
selectors, in addition to "class of object", for example, first
parametter of function can be second dispatch selector.
I call that a normal overloading.Different name mangling is exerted on
functions with different params but that is not curently the case for
functions with same name and prototype which leads in a complete
hiding behavoir. Note that we expect different behavoir when calling
'go' from an 'A' or a 'D' pointer/reference.So correct dispaching
will be important.
struct Base
{
virtual void foo(const Base&)=0;
};
struct Derived: public Base
{
void foo(const Base&);
dispatched void foo(const Derived&);
dispatched void foo(const int);
};
struct Extra: public Derived
{
void foo(const double);
};
Here all "foo" with only one parameter became "dispatched" for class
Derived and for all classes inherited from Derived.
extern Base auto* param;
Base heap* ptr=new Derived;
void foo()
{
ptr->foo(*param);
}
Here "Derived::foo(const Base&)" will be called if
"typeid(*param)==typeid(Base)" and "Derived::foo(const Derived&)" will
be called if "typeid(*param)==typeid(Derived)".
It looks like
Base::vtbl[foo_offset](*param);
here called C++ generated
Derived::virtual_to_dispatcher( param );
void Derived::virtual_to_dispatcher( param )
{
Derived::dispatcher_foo( typeid(param), param );
}
here called C++ generated
Derived::dispatcher_foo( typeid(param), param )
void Derived::dispatcher_foo( const typeid& id, ... )
{
va_list param;
va_start(param, id);
if( id == typeid(const int) )
{
const int tmp=va_arg(param,const int);
va_end(param);
[return] Derived::foo( (const int)param );
[return;]
}
if( id == typeid(Derived) )
{
Derived& tmp=va_arg(param,Derived&);
va_end(param);
[return] Derived::foo( (Derived&)param );
[return;]
}
//if( id == typeid(Base) )
{
Base& tmp=va_arg(param,Base&);
va_end(param);
[return] Derived::foo( (Base&)param );
[return;]
}
//execution control never reach the point
//due to static type checking
}
void boo()
{
Base b;
Derived d;
Extra e;
b.foo(*ptr);
b.foo(b);
b.foo(d);
b.foo(e);
d.foo(*ptr);
d.foo(b);
d.foo(d);
d.foo(e);
d.foo(100);
e.foo(*ptr);
e.foo(b);
e.foo(d);
e.foo(100);
e.foo(0.1);
}
Of course, multiple dispatching is doing by the cost of perfomans
lost.
--
Maksim A. Polyaninhttp://grizlyk1.narod.ru/cpp_new
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-...@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ:http://www.comeaucomputing.com/csc/faq.html ]- Hide quoted text -
- Show quoted text -
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]