Topic: Two proposals
Author: david@tribble.com (David R Tribble)
Date: Mon, 5 Jan 2004 02:08:43 +0000 (UTC) Raw View
lgalfaso@fd.com.ar (Lucas Galfas=F3) wrote:
> I have two proposals to the Standard and would like opinions.
> The first extension, could be considered natural, the second controvers=
ial.
> Well, I think that the best way to transmit the idea is with some examp=
les,
> so
>=20
> namespace EVB {
> /* explicit virtual binding (I could not find a good name) */
>=20
> struct bar : foo {
> virtual int barFunc01 (int n) =3D foo::fooFunc;
>
> /* This would be the same as:
> virtual int barFunc01 (int n)
> {
> return foo::fooFunc (n);
> }
> */
> }
>
> [...]
This is similar the my proposal for ISO C which I called "function aliase=
s".
[See <http://david.tribble.com/text/c0xalias.htm>.]
I was trying to accomplish something completely different for C, viz.,
giving C something like the function overloading of C++, but the effect
is similar to yours.
-drt
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: lgalfaso@fd.com.ar (=?iso-8859-1?Q?Lucas_Galfas=F3?=)
Date: Mon, 22 Dec 2003 10:52:58 +0000 (UTC) Raw View
The limitation I see is that templates cannot override a virtual function
that is a parameter to the template (without doing some macro magic.)=20
Some examples that I think this would be useful are, an=A0implementation =
of=A0a
cache template and a wrapper that does copy-on-write.
=A0
Most (all) compiler have a virtual table per instantiated (polymorphic)
object and, when I make a call to a virtual function I pay an extra for t=
he
lookup. So, why I am unable to change, at runtime,=A0the function
implementation=A0that is called=A0when I call a virtual function?
This change seems like a radical solution to the original problem, like
killing a mosquito with a bazooka, but my original intent was to know if =
you
think this limitation is big enough to change the standard.
=A0
Lucas/
---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.545 / Virus Database: 339 - Release Date: 11/27/2003
=20
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: do-not-spam-benh@bwsint.com (Ben Hutchings)
Date: Mon, 22 Dec 2003 16:48:11 +0000 (UTC) Raw View
Lucas Galfas=F3 wrote:
<snip> =A0
> Most (all) compiler have a virtual table per instantiated (polymorphic)
> object and, when I make a call to a virtual function I pay an extra for=
the
> lookup. So, why I am unable to change, at runtime,=A0the function
> implementation=A0that is called=A0when I call a virtual function?
<snip>
The reason is that you are mistaken, and implementations actually use
per-class virtual tables.
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: Tue, 23 Dec 2003 17:05:22 +0000 (UTC) Raw View
lgalfaso@fd.com.ar (=?iso-8859-1?Q?Lucas_Galfas=F3?=) wrote (abridged):
> The limitation I see is that templates cannot override a virtual
> function that is a parameter to the template (without doing some
> macro magic.)
Yes; I could see some motivation for the second half of your proposal,
for which there is no equivalent in current C++.
> Most (all) compiler have a virtual table per instantiated (polymorphic)
> object and, when I make a call to a virtual function I pay an extra for
> the lookup.
Actually, no. Most compilers have a virtual table per polymorphic class,
which is shared by all instances of that class. For embedded systems this
table may even be stored in ROM, which I gather is cheaper than RAM for
such systems. There is not a table per object.
> So, why I am unable to change, at runtime, the function
> implementation that is called when I call a virtual function?
One reason is that with current implementations it would affect all
instances of the class. This would be too scary to use.
If we change the implementation to give each instance its own writable
copy, we would increase the memory needed by each instance, in some cases
massively. Even if we used some kind of smart copy-on-write, there would
be some overhead which would be incurred even by programs that didn't use
the new feature. Such a change would also affect backwards binary
compatibility.
Another reason is that the compiler is currently able to optimise away
that extra lookup in some cases, if it can determine the exact class of an
object. Eg:
MyObject obj;
obj.method();
The call to method need not use the virtual table because it will always
resolve to MyObject::method. However, with your change the compiler would
need to be sure that MyObject's constructor had not assigned to method's
slot. So your proposal would lead to a loss of performance.
> This change seems like a radical solution to the original problem, like
> killing a mosquito with a bazooka, but my original intent was to know
> if you think this limitation is big enough to change the standard.
I personally have not suffered from the problem you are trying to solve.
However, I can see the value of it. I would object to the solutions you
have proposed, but I wouldn't object if you proposed a purely compile-time
solution, with no run-time modification of the vtable.
-- Dave Harris, Nottingham, UK
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: lgalfaso@fd.com.ar (=?iso-8859-1?Q?Lucas_Galfas=F3?=)
Date: Wed, 17 Dec 2003 00:41:43 +0000 (UTC) Raw View
Hi,
I have two proposals to the Standard and would like opinions.
The first extension, could be considered natural, the second controversia=
l.
Well, I think that the best way to transmit the idea is with some example=
s,
so
namespace EVB {
=A0/*
=A0explicit virtual binding (I could not find a good name)
=A0*/
=A0struct foo {
=A0 virtual int fooFunc (int n)
=A0 {
=A0=A0 return n;
=A0 }
=A0};
=A0struct bar : foo {
=A0 virtual int barFunc01 (int n) =3D foo::fooFunc;
=A0 /*
=A0 This would be the same as:
=A0 virtual int barFunc01 (int n)
=A0 {
=A0=A0 return foo::fooFunc (n);
=A0 }
=A0 [-- Note: barFunc01 and foo::fooFunc must have the same argument list=
and
return type --]
=A0 [-- Note: barFunc01 must be virtual. --]
=A0 [-- Note: fooFunc could be virtual or not-virtual. --]
=A0 */
=A0 virtual int barFunc02 (int n) =3D fooFunc;
=A0 /*
=A0 This would be the same as:
=A0 virtual int barFunc02 (int n)
=A0 {
=A0=A0 return fooFunc (n);
=A0 }
=A0 [-- Note: This is interesting, because foo::fooFunc is virtual. --]
=A0 [-- Note: notice the diference in both functions, the first one redir=
ects
to foo::fooFunc
=A0=A0 and the second one to fooFunc--]
=A0 */
=A0};
=A0template <typename base_t, int (base_t::*func)(int)>
=A0struct shell : base_t
=A0{
=A0 virtual int shellFunc (int n) =3D func;
=A0 /*
=A0 This would be the same as:
=A0 virtual int shellFunc (int n)
=A0 {
=A0=A0 return (this->*)func (n);
=A0 }
=A0 [-- Note: This is posible because shell is derived from base_t --]
=A0 */
=A0};
}
namespace EO {
=A0/*
=A0 explicit overloading
=A0 [-- Note: this one is controversial. --]
=A0*/
=A0struct foo
=A0{
=A0 virtual int fooFunc (int n)
=A0 {
=A0=A0 return n;
=A0 }
=A0};
=A0struct bar : foo
=A0{
=A0 bar ()
=A0 {
=A0=A0 &fooFunc =3D &bar::barFunc01;
=A0 }
=A0 int barFunc01 (int n)
=A0 {
=A0=A0 return n;
=A0 }
=A0 virtual int barFunc02 (int n)
=A0 {
=A0=A0 return n;
=A0 }
=A0 void generateMoreControversy ()
=A0 {
=A0=A0 &fooFunc =3D &barFunc02;
=A0 }
=A0 /*
=A0 [-- Note: fooFunc must be virtual. --]
=A0 [-- Note: barFunc01 / barFunc02 could be virtual or not-virtual. --]
=A0 */
=A0}
=A0/*
=A0You can get a similar effect doing this.
=A0*/
=A0/*
=A0struct foo
=A0{
=A0 foo ()
=A0 {
=A0=A0 fooFunc =3D &foo::internalFooFunc;
=A0 }
=A0 int (foo::*fooFunc)(int);
=A0 int internalFooFunc (int n)
=A0 {
=A0=A0 return n;
=A0 }
=A0};
=A0struct bar : foo
=A0{
=A0 bar ()
=A0 {
=A0=A0 fooFunc =3D static_cast<int(foo::*)(int)>(&bar::barFunc01);
=A0=A0 barFunc02 =3D &bar::internalBarFunc02;
=A0 }
=A0 int barFunc01 (int n)
=A0 {
=A0=A0 return n;
=A0 }
=A0 int (bar::*barFunc02) (int);
=A0 int internalBarFunc02 (int n)
=A0 {
=A0=A0 return n;
=A0 }
=A0 void generateMoreControversy ()
=A0 {
=A0=A0 fooFunc =3D static_cast<int(foo::*)(int)>(barFunc02);
=A0 }
=A0};
=A0*/
=A0/*
=A0... and the really controversial
=A0*/
=A0template <typename base_t, int (base_t::*func)(int)>
=A0struct shell : base_t
=A0{
=A0 shell ()
=A0 {
=A0=A0 &shell::func =3D &shellFunc;
=A0 }
=A0 /*
=A0 [-- Note: this would work if and only if func where a virtual functio=
n
(and has the
=A0=A0 same parameters and return type as shellFunc.) --]
=A0 */
=A0 int shellFunc (int)
=A0 {
=A0=A0 return n;
=A0 }
=A0};
}
Lucas/
---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.545 / Virus Database: 339 - Release Date: 11/27/2003
=20
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: stephen.clamage@sun.com (Steve Clamage)
Date: Thu, 18 Dec 2003 01:19:31 +0000 (UTC) Raw View
It would be easier for people to comment on your proposals if you said wh=
at you=20
were trying to accomplish and what benefits it would have.
Code examples can illustrate your proposal, but do not substitute for an=20
explanation of the problem that is currently difficult to solve.
--=20
Steve Clamage, stephen.clamage@sun.com
Lucas Galfas=F3 wrote:
> Hi,
> I have two proposals to the Standard and would like opinions.
> The first extension, could be considered natural, the second controvers=
ial.
> Well, I think that the best way to transmit the idea is with some examp=
les,
> so
>=20
>=20
>=20
> namespace EVB {
>=20
> /*
> explicit virtual binding (I could not find a good name)
> */
>=20
> struct foo {
> virtual int fooFunc (int n)
> {
> return n;
> }
> };
>=20
> struct bar : foo {
> virtual int barFunc01 (int n) =3D foo::fooFunc;
> /*
> This would be the same as:
> virtual int barFunc01 (int n)
> {
> return foo::fooFunc (n);
> }
>=20
> [-- Note: barFunc01 and foo::fooFunc must have the same argument list=
and
> return type --]
> [-- Note: barFunc01 must be virtual. --]
> [-- Note: fooFunc could be virtual or not-virtual. --]
> */
>=20
> virtual int barFunc02 (int n) =3D fooFunc;
> /*
> This would be the same as:
> virtual int barFunc02 (int n)
> {
> return fooFunc (n);
> }
>=20
> [-- Note: This is interesting, because foo::fooFunc is virtual. --]
> [-- Note: notice the diference in both functions, the first one redir=
ects
> to foo::fooFunc
> and the second one to fooFunc--]
> */
> };
>=20
>=20
> template <typename base_t, int (base_t::*func)(int)>
> struct shell : base_t
> {
> virtual int shellFunc (int n) =3D func;
> /*
> This would be the same as:
> virtual int shellFunc (int n)
> {
> return (this->*)func (n);
> }
>=20
> [-- Note: This is posible because shell is derived from base_t --]
> */
> };
>=20
> }
>=20
>=20
>=20
>=20
>=20
>=20
> namespace EO {
>=20
> /*
> explicit overloading
> [-- Note: this one is controversial. --]
> */
>=20
> struct foo
> {
> virtual int fooFunc (int n)
> {
> return n;
> }
> };
>=20
> struct bar : foo
> {
> bar ()
> {
> &fooFunc =3D &bar::barFunc01;
> }
>=20
> int barFunc01 (int n)
> {
> return n;
> }
>=20
> virtual int barFunc02 (int n)
> {
> return n;
> }
>=20
> void generateMoreControversy ()
> {
> &fooFunc =3D &barFunc02;
> }
> /*
> [-- Note: fooFunc must be virtual. --]
> [-- Note: barFunc01 / barFunc02 could be virtual or not-virtual. --]
> */
> }
>=20
> /*
> You can get a similar effect doing this.
> */
>=20
> /*
> struct foo
> {
> foo ()
> {
> fooFunc =3D &foo::internalFooFunc;
> }
>=20
> int (foo::*fooFunc)(int);
>=20
> int internalFooFunc (int n)
> {
> return n;
> }
> };
>=20
> struct bar : foo
> {
> bar ()
> {
> fooFunc =3D static_cast<int(foo::*)(int)>(&bar::barFunc01);
> barFunc02 =3D &bar::internalBarFunc02;
> }
>=20
> int barFunc01 (int n)
> {
> return n;
> }
>=20
> int (bar::*barFunc02) (int);
>=20
> int internalBarFunc02 (int n)
> {
> return n;
> }
>=20
> void generateMoreControversy ()
> {
> fooFunc =3D static_cast<int(foo::*)(int)>(barFunc02);
> }
> };
> */
>=20
>=20
> /*
> ... and the really controversial
> */
>=20
> template <typename base_t, int (base_t::*func)(int)>
> struct shell : base_t
> {
> shell ()
> {
> &shell::func =3D &shellFunc;
> }
> /*
> [-- Note: this would work if and only if func where a virtual functio=
n
> (and has the
> same parameters and return type as shellFunc.) --]
> */
>=20
> int shellFunc (int)
> {
> return n;
> }
> };
>=20
> }
>=20
>=20
> Lucas/
>=20
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: lgalfaso@fd.com.ar (=?iso-8859-1?Q?Lucas_Galfas=F3?=)
Date: Thu, 18 Dec 2003 18:31:03 +0000 (UTC) Raw View
I am trying to make virtual functions more flexible, given that you already
pay for a call to a virtual function, give them the flexibility to change
the function they reference to.
This is functionality is especially useful then you want to define a
templates that override a class member virtual function that is a parameter
to the template.
Both proposals try to attack this problem. The second proposal is the one
that achieves this, but the first proposal is somehow a side effect that is
interesting.
Lucas/
---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.545 / Virus Database: 339 - Release Date: 11/27/2003
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: Mon, 22 Dec 2003 04:55:36 +0000 (UTC) Raw View
lgalfaso@fd.com.ar (=?iso-8859-1?Q?Lucas_Galfas=F3?=) wrote (abridged):
> struct bar : foo {
> virtual int barFunc01 (int n) = foo::fooFunc;
> /*
> This would be the same as:
> virtual int barFunc01 (int n)
> {
> return foo::fooFunc (n);
> }
So why bother changing the language? Why not just use the commented
code instead?
> bar ()
> {
> &fooFunc = &bar::barFunc01;
> }
Does this affect all instances of bar, or just the ones which use this
constructor?
I think your intention is the former, in which case it would be better
to find a syntax which reflects that.
template <typename base_t, int (base_t::*func)(int)>
struct shell : base_t {
int shellFunc( int );
func = shellFunc;
};
-- Dave Harris, Nottingham, UK
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]