Topic: main()???


Author: David R Tribble <david.tribble@central.beasys.com>
Date: 1997/04/15
Raw View
I wrote:
>> A basic, but arguable, tenet of object-oriented
>> programming is that *all* functions and variables are members of classes.
>> Other languages, like Java and Eiffel, enforce this.

bonnardv@pratique.fr (Valentin Bonnard) responded:
> Why ? I write OO program with lots of non-members functions; in
> particular, operator<< has to be non-member; what's special with
> members functions ? Why are they better than a non-member ?
>
> Also in the STL design algo aren't (and shouldn't be) members of a
> class. A class represent an object: an interface over a
> representation.
>
> Lots of functions just use classes, they don't implement one.

Sounds like those functions should be put into classes, then.  It appears
that you will have a hard time coding in other O-O languages when the need
arises.  Avoiding classes is anathema to O-O principles, regardless of
how nifty templates are.

> Perhaps you use classes as namespaces because your compiler
> doesn't support them ?

Not exactly.  What happens when your operator<<() conflicts with a third
party's operator<<()?  Or when your List class conflicts with someone
else's List class?  Oh, but I forgot, your single compiler supports
namespaces while the eight or nine compilers we use don't.  A namespace,
by any other name, is just a wrapper class.

> IMO the view that everything is a class is just ugly and can
> lead to fat classes that know everything.

We've never had that problem.  Our classes don't get bigger, we just have
more classes.  Like you said before, each class should embody a single type
of object; it has only the necessary functions/operators/algorithms needed
for that object.  A class should do a few things very well.  And some classes
can embody a set of algorithms (functions) with no object data at all.

You dislike fat classes.  What about excess global data and functions?
They can be especially annoying because, lacking classes, it's not always
obvious how they are grouped together or how they interact.  And they tend
to be spread out in the source code and third-party libraries, so they can
be difficult to track down.

We rarely find the need for global data, because practically every function
we have operates on object-specific data, even if the object is a static
singleton POD.  Even ::main() operates on object-specific data, that being
the data (object) encompassing the execution of the program (which is
usually little more than the command line arguments).  Why not write the
program that way then, and put it in a class?
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Oleg Zabluda <zabluda@math.psu.edu>
Date: 1997/04/16
Raw View
David R Tribble <david.tribble@central.beasys.com> wrote:
: bonnardv@pratique.fr (Valentin Bonnard) responded:
: > Why ? I write OO program with lots of non-members functions; in
: > particular, operator<< has to be non-member; what's special with
: > members functions ? Why are they better than a non-member ?
: >
: > Also in the STL design algo aren't (and shouldn't be) members of a
: > class. A class represent an object: an interface over a
: > representation.
: >
: > Lots of functions just use classes, they don't implement one.

: Sounds like those functions should be put into classes, then.  It appears
: that you will have a hard time coding in other O-O languages when the need
: arises.  Avoiding classes is anathema to O-O principles, regardless of
: how nifty templates are.

Templates provide programming paradigm different from OOP. It's is
no less powerful then OOP and sometimes much superior. Alex Stepanov
calls it Generic Programming (GP). Like Valentin Bonnard mentioned,
STL uses this other (GP) paradigm, not OOP. STL does not employ OOP
for anything, but a little bit of convenience.

Moreover, GP sometimes provides a total replacement for OOP, with
a usual tradeoff - OOP has smaller code size, GP is faster.

If you want to play a little game - post some (very short) OO stuff
and I'll translate it to GP, to show what I mean.

BTW, does anyone know any other language that combines both GP and OOP,
or C++ is unique in this respect?

Oleg.
--
Life is a sexually transmitted, 100% lethal disease.
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Matt Austern <austern@isolde.mti.sgi.com>
Date: 1997/04/16
Raw View
David R Tribble <david.tribble@central.beasys.com> writes:

> > Also in the STL design algo aren't (and shouldn't be) members of a
> > class. A class represent an object: an interface over a
> > representation.
> >
> > Lots of functions just use classes, they don't implement one.
>
> Sounds like those functions should be put into classes, then.  It appears
> that you will have a hard time coding in other O-O languages when the need
> arises.  Avoiding classes is anathema to O-O principles, regardless of
> how nifty templates are.

Except that C++ is, by design, a language that supports several
different ways of organizing programs.  (The two that I think of as
the most important are generic programming and object-oriented
programming.)  This was not an oversight, or a compromise in the name
of backwards compatibility.  One of the fundamental premises of C++'s
design is that no one technique is always best for all purposes.

Some languages do try to enforce a single style of programming; this
certainly implies that porting a C++ program to Language X might be
difficult, if that program uses a style that Language X doesn't
support.  If you think that you're likely to port your program to
several different languages, then you undoubtedly ought to think about
which subsets of those languages you'll use.
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: David R Tribble <david.tribble@central.beasys.com>
Date: 1997/04/13
Raw View

Stephen.Clamage@Eng.Sun.COM (Steve Clamage) wrote:
> C++ takes the view, common to most programming languages, that the program
> entry point is special, and not "just another function." If main is indeed
> "just another function," that forces certain implementation decisions
> which might not be appropriate on some platforms.

fjh@mundook.cs.mu.OZ.AU (Fergus Henderson) wrote:
> Alternatively, the implementation could just mangle the name `main' to
> `__user_main' and have the C++ startup code contain a definition of
> `main' which does whatever magic is needed and then calls `__user_main'.
> Note that C++ already requires name mangling of main to be special cased,
> because you can define it as either `main(void)' or `main(int, char **)'.

I prefer to write my programs with a ::main() that is as lightweight as
possible.  I also like to make ::main() the *only* non-member function in
the whole program.  (A basic, but arguable, tenet of object-oriented
programming is that *all* functions and variables are members of classes.
Other languages, like Java and Eiffel, enforce this.)

To wit:
    class Program   // Embodies the execution of the program
    {
    public:
        int         main(int argc, char **arg);
    };

    int main(int argc, char **argv)
    {
        Program     prog;
        return prog.main(argc, argv);   // Only this, nothing more
    }

Now the actual work of the program gets done by Program::main().  Since
the Program object 'prog' is instantiated when ::main() executes, it doesn't
have to worry about global variable and library initializations, since
it knows they've already been done.  And Program::main() is recursively
callable if need be.
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/04/10
Raw View
Stephen.Clamage@Eng.Sun.COM (Steve Clamage) writes:

>C++ takes the view, common to most programming languages, that the program
>entry point is special, and not "just another function." If main is indeed
>"just another function," that forces certain implementation decisions
>which might not be appropriate on some platforms.

It does?  Why?

>If you really need to get the C effect of calling main in C++, you can do it:
>
> int MyMain(int, char**); // does the work
>
> int main(int argc, char** argv) { return MyMain(argc, argv); }
>
>Now use "MyMain" in the way you would use "main" in C.

Surely an implementation could do this automatically?
Of course, it would have to use a name reserved for the implementation,
such as `__user_main', rather than MyMain.

Alternatively, the implementation could just mangle the name `main' to
`__user_main' and have the C++ startup code contain a definition of
`main' which does whatever magic is needed and then calls `__user_main'.
Note that C++ already requires name mangling of main to be special cased,
because you can define it as either `main(void)' or `main(int, char **)'.

--
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]






Author: Stephen.Clamage@Eng.Sun.COM (Steve Clamage)
Date: 1997/04/02
Raw View
In article 054215@cs.mu.oz.au, fjh@mundook.cs.mu.OZ.AU (Fergus Henderson) writes:
>Stephen.Clamage@Eng.Sun.COM (Steve Clamage) writes:
>
>>Here is the relevent part of the draft standard (3.6.1 "Main function"):
>>
>>"The function main shall not be called from within a program. The linkage
>>(3.5) of main is implementation-defined. A program that takes the address
>>of main, or declares it inline or static is ill-formed."
>>
>>The "shall not" and "ill-formed" phrases means a diagnostic message is
>>required for any violation. (A compiler is allowed to accept the code
>>anyway, but normally you get an error message and no runnable program.)
>>A C++ compiler that accepts a call to main without complaint is not
>>conforming.
>
>The "ill-formed" phrase does mean that a diagnostic message is
>required for any violation, but the "shall not" phrase can mean
>either that a diagnostic is required, or that violation results
>in undefined behaviour, depending on exactly how the requirement
>is stated. ...
>
>With regard to the case in question, the requirement that Steve Clamage
>quoted, "the function main shall not be called from within a program"
>seems to me to be a requirement on the execution of a program, not on
>its form, and so no diagnostic is required.  (In contrast, if there
>requirement were "a program shall not contain a call to the function
>main", then it would be a requirement on the form, and so a diagnostic
>would be required -- but that is not the case.)
>
>>Calling main or taking its address was even disallowed by the ARM.
>
>Yes, but the ARM just says that "the function main may not be called
>from within a program", ...

The draft standard started out as the ARM with the commentary omitted
(literally: the troff source of the ARM was used for the original draft).
Wording of sections was modified as deficiencies were discovered. This
is a phrase that has survived unchanged so far.

It should have always been understood that in C++ it is an error
requiring a diagnostic to attempt to call main or take its address.
I guess no one noticed before that the words of the draft when taken
literally do not say that. (For example, the popular Plum Hall C++
Validation Suite has always had a test for calling or taking the
address of main in its "should not compile" section.)

I've submitted a request to clarify the wording in the draft.

---
Steve Clamage, stephen.clamage@eng.sun.com
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/03/31
Raw View
Stephen.Clamage@Eng.Sun.COM (Steve Clamage) writes:

>Here is the relevent part of the draft standard (3.6.1 "Main function"):
>
>"The function main shall not be called from within a program. The linkage
>(3.5) of main is implementation-defined. A program that takes the address
>of main, or declares it inline or static is ill-formed."
>
>The "shall not" and "ill-formed" phrases means a diagnostic message is
>required for any violation. (A compiler is allowed to accept the code
>anyway, but normally you get an error message and no runnable program.)
>A C++ compiler that accepts a call to main without complaint is not
>conforming.

The "ill-formed" phrase does mean that a diagnostic message is
required for any violation, but the "shall not" phrase can mean
either that a diagnostic is required, or that violation results
in undefined behaviour, depending on exactly how the requirement
is stated.  Here's the relevent part of the draft standard:

 |   1.3  Implementation compliance                     [intro.compliance]
 |
 | 5 Although this International Standard states only requirements on C++
 |   implementations, those requirements are often easier to understand if
 |   they are phrased  as requirements on programs, parts of programs, or
 |   execution of programs.  Such requirements have the following meaning:
 |
 |   --Whenever this International Standard places a  diagnosable require-
 |     ment on the form of a program (that is, the characters, tokens, syn-
 |     tactic elements, and types that make up the program), and a program
 |     does not meet that requirement, the program is ill-formed and the
 |     implementation shall issue a diagnostic message when processing that
 |     program.
 |
 |   --Whenever this International Standard places a requirement on the
 |     execution of a program (that is, the values of data that are used as
 |     part of program execution) and the data encountered during execution
 |     do not meet that requirement, the behavior of the program is unde-
 |     fined and this International Standard places no requirements at all
 |     on the behavior of the program.

With regard to the case in question, the requirement that Steve Clamage
quoted, "the function main shall not be called from within a program"
seems to me to be a requirement on the execution of a program, not on
its form, and so no diagnostic is required.  (In contrast, if there
requirement were "a program shall not contain a call to the function
main", then it would be a requirement on the form, and so a diagnostic
would be required -- but that is not the case.)

>Calling main or taking its address was even disallowed by the ARM.

Yes, but the ARM just says that "the function main may not be called
from within a program", it does not say that a compiler must issue a
diagnostic if the program contains a call to main().  The ARM in
general doesn't say much about what diagnostics a compiler must issue.
Note that even if a program does contain a call to main(), in the
general case it is undecidable whether that call will actually be
executed.

--
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]