public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
From: staube@t2.technion.ac.il
To: gcc@gcc.gnu.org
Subject: Idea of feature/optimization for C++
Date: Wed, 01 Sep 2004 09:29:00 -0000	[thread overview]
Message-ID: <1094030972.4135967cb856e@webmail.technion.ac.il> (raw)

Hi gcc gurus, hackers and wizards: 
This is the second mail i write to this list, the first one was wirtten a few
days ago and after finishing it I deleted it by mistake.
This is also the first mail i write that will reach you.

I am writing this mail in order to propose and new optimization/feature in the
C++ front end of GCC.
Before doing it i will warn you a few things:
1) I know nothing about the internal code/design of GCC or any of its frontends
so i cannot code the feature i am proposing, at least in the short-term. If
noone is able to do it, i MIGHT try to start reading and some day do it myself,
but you will have to wait.
2) I know nothing about the C++ standards, so my feature might have non standard
compilance.
3) Who knows?, maybe the feature is already implemented, so, i am not adding
anything :-(

The issue i want to cover is virtual functions and late/early-binding. Its
obvious that virtual functions are a very important part of Object Oriented
Programming with C++ but many developers refrain from using it because they
mean a performance loss when they are not needed, other solutions have been
found to implement some of the features that virtual functions provide, for
example templates.

I will illustrate this in an example.... I will write the same program twice.
One version using virtual functions and another one using templates
Look at the following two versions of main.cpp.

Example 1, Version 1 (using virtual functions)
**************************
#include <iostream>
using namespace std;


class HelloWorld {
    protected:
    HelloWorld() { };
    public:
    virtual void doIt() = 0;
};

class HappyHelloWorld : public HelloWorld{
    public:
    HappyHelloWorld() { };
    public:
    virtual void doIt() { cout << "Hello World :)" << endl; };
};

class SadHelloWorld : public HelloWorld {
    public:
    SadHelloWorld() { };
    public: 
    virtual void doIt() { cout << "Hello World :(" << endl; };
};

void letsSee(HelloWorld &hw)
{
    cout << "Lets see what&#8217;s his mood when he says hello World:" << endl;
    hw.doIt();
}

int main(int argc, char *argv[])
{
  SadHelloWorld shw;
  HappyHelloWorld hhw;
  letsSee(hhw);
  letsSee(shw);

  //doing PAUSE
  char c;
  cin >> c;
  return 0;
}

Example 1, Version 2  (using templates)
********************
#include <iostream>
using namespace std;


class HelloWorld {
    protected:
    HelloWorld() { };
    public:
    // no virtual
    // virtual void doIt() = 0; 
};

class HappyHelloWorld : public HelloWorld{
    public:
    HappyHelloWorld() { };
    public:
    /*virtual*/ void doIt() { cout << "Hello World :)" << endl; };
};

class SadHelloWorld : public HelloWorld {
    public:
    SadHelloWorld() { };
    public: 
    /*virtual*/ void doIt() { cout << "Hello World :(" << endl; };
};

template <class MyHelloWorld>
void letsSee(MyHelloWorld &hw)
{
    cout << "Lets see what&#8217;s his mood when he says hello World:" << endl;
    hw.doIt();
}

int main(int argc, char *argv[])
{
  SadHelloWorld shw;
  HappyHelloWorld hhw;
  letsSee(hhw);
  letsSee(shw);

  //doing PAUSE
  char c;
  cin >> c;
  return 0;
}
*******************************************************************************
Output of the two versions
****************************
Lets see what&#8217;s his mood when he says hello World:
Hello World :(
Lets see what&#8217;s his mood when he says hello World:
Hello World :("

As you see both examples do the same thing, only that the second one uses Early
Binding and then is more efficient.

I know than sometimes, virtual functions cannot be replaced by templates, for
example if there is an array of 100 pointers to HelloWorld Objects, we would
have no idea which function has to be called, then only the virtual function
solution would work. 

As a result of this, using virtual functions is always a better that using
templates, at least when you do not care about efficiency.

If we would like more and more developers to start using Object Oriented
Techniques it would be great that virtual functions perform as good as normal
functions whenever possible  &#205; was thinking that if the compiler would be
inteligent enought it could do early binding in the first example too, because
theres no need to do late-binding. Then programmers that would be worried about
the efficency of their code could still use the clean and good syntax of the
first example. Also it would be nice that programmers which do not know about
this optimization using templates, could get this for free :-)
 
How could all this be done??
When compiling any C++ function  the compiler should behave like this:
1 - compile several versions of the same function (usimg different name
decorations) .... one must do all the function calls using latebinding, just in
case we will need it, and the rest of the versions should be the earlybinding
version for every class that inherts from the parent class.
     In the example it would make three versions... the latebindingone, the
earylbinding for class SadHelloWorld and the earybinding for class
HappyHelloWorld.
2 -  If there are function calls to the function (function letsSee in our
example) it should be done to the early binding version whenever possible. 
3 &#8211; There could be problems sometimes because the compiler can only create
versions of letsSee for classes it knows that exist, then if a class was
declared in another file, no letsSee function would be created for that class
and then the user would get a linker error for not finding the earlybinding
version of the function, which would be the correct error to show to the user.
The programmer then would be forced to add the following code before declaring
the letsSee function:
    //AngryHelloWorld is defined in another file
    class AngryHelloWorld : public class HelloWorld;

4 - there should be an option in g++ to disable this behaviour. 
5-This optimization should also be applied to methods from the class itself. Any
method getting the "this" hidden parameter could also do its internal calls
throw latebinding orearlybinding, of course being earlybinding is the preferred
option.
 
Some other problems:
 For functions who get lots of parameters there would be lots of versions which
will increase a lot the size of the binary code. Maybe generating all the
versions should not be the default action but programmers should choose
whatever they want to make earlybinding versions or not. To do that they might
use the well known reserved word "virtual" and an additional one "final" (Am i
starting to sound like Java??).
Then:
  1)   If they write: void letsSee(virtual HelloWorld &hw), the compiler would
make only the latebinding version.
  2)   If they write: void letsSee(final HelloWorld &hw), the compiler would
also make the earlybinding version
  3)   If they write: void letsSee(HelloWorld &hw), the compiler would
show&#209;

                Warning: main.cpp:XX : HelloWorld has virtual functions but    
                "virtual" nor "final" were specified when getting 
                the params of letsSeefunction, to disable this warning use 
                the -Wnobind flag.

The last problem i have thinked of, is the binary distribution of libs. In those
cases functions cannot be instantiated (the same problem that the template
solution would have!!!). In that cases it would be impossible to call letsSee
using earlybinding on new classes declared by the user which inhert from
HelloWorld, of course, unless there could be a very advanced feature would be
implemented in the linker which would instantiate the latebinding binary code
to the needed earlybinding version (i don´t think it is going to happen anytime
soon). In those cases when optimizing would be impossible, the old fashion
latebinding should be used.

Another optimization: inline and virtual!!!
A method could be declared at the same time inline and virtual. then when a
function call that method using earlybinding it will inline the function, but
in the latebinding version it would call the method in the standard way.

Hey, i hope you liked this optimization, please tell me whatever you think about
it.
If it would be impossible to implement, tell me.
If it would be possible but noone has the time or will to do it, tell me too. I
will be happy to know that at least it was a good idea and i wil try to help
implement it in the future.

Thank you very much for your time,
Sincerilly,
Marcelo Taube

             reply	other threads:[~2004-09-01  9:29 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-09-01  9:29 staube [this message]
2004-09-01 13:43 ` Dave Korn
2004-09-05 23:22   ` staube

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1094030972.4135967cb856e@webmail.technion.ac.il \
    --to=staube@t2.technion.ac.il \
    --cc=gcc@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).