This question is only half tongue-in-cheek. I sometimes dream of a world without naked arrays or c strings.
If you're using c++, shouldn't the preferred definition of main be something like:
int main(std::vector<std::string> args)
?
There are already multiple definitions of main
to choose from, why isn't there a version that is in the spirit of C++?
The multiple definitions of main() aren't really multiple definitions. There are three:
int main(void)
(C99)int main(int argc, char *argv[])
(C99)int main(int argc, char *argv[], char *envp[])
(POSIX, I think)But in POSIX, you only really get the third. The fact that you can call a function with extra arguments is down to the C calling convention.
You can't have
extern "C" int main(std::vector<std::string> argv)
unless the memory layout happens to be magically compatible in a portable way. The runtime will call main() with the wrong arguments and fail. There's no easy way around this.Instead, provided main() wasn't
extern "C"
, the runtime could try the various supported symbols in order until it found one. I imagine main() isextern "C"
by default, and that you can't overloadextern "C"
functions.For more fun, void main(void).
Because C++ was in existence long before the C++ standard was, and built heavily on C. And, like the original ANSI C standard, codifying existing practice was an important part of it.
There's no point in changing something that works, especially if it will break a whole lot of existing code.
Even ISO C, which has been through quite a few iterations, still takes backwards compatibility very seriously.
A concern that keeps coming back to my mind is that once you allow complex types, you end up with the risk of exceptions being thrown in the type's constructor. And, as the language is currently designed, there's absolutely no way for such an exception to be caught. If it were decided that such exceptions should be caught, then that would require considerably more work, both for the committee and compiler writers, making it all somewhat more troublesome than simply saying "allow
std::vector<std::string>>
".There might be other issues as well. The whole "incompatible with runtimes" seems like something of a red herring to me, given that you can provide basically the same functionality now with macros. But something like this is rather more involved.
I'll try explain in the best possible sentence.
C++ was designed to be backward compatible with C and
std::vector
was included in a library that only got included in C++.Also, C++ and C programs were designed to run in shells or command lines (windows, linux, mac) and OS pass arguments to a program as an array of String. How would an OS really translate vectors?
That's the most reason I can think of, feel free to criticize it.
There's another reason besides compatibility with C. In C++, the standard library is meant to be entirely optional. There's nothing about the C++ language itself that forces you to use things from the standard library like
std::string
andstd::vector
, and that is entirely by design. In fact, it is by design that you should be able to use some parts of the standard library without having to use others (although this has led to some generally annoying things likestd::ifstream
andstd::ofstream
operating onconst char*
C-style strings rather than onstd::string
objects).The theory is that you are supposed to be able to take the C++ language and use whatever library of objects, containers, etc, that you want with it, be it the standard library or some proprietary library (e.g. Qt, MFC), or something that you created yourself. Defining
main
to accept an argument composed of types defined in the standard library defeats this design goal.Like @jalf, I sometimes find myself writing
But yes, like everyone said,
main
has to be C-compatible. I see it as an interface to the OS runtime, which is (at least int the systems I use) is written in C.Although some development environment encourage replacements such as
wmain
or_tmain
. You could write your own compiler/IDE, which would encourage the use ofint vmain(const std::vector<std::string>& args)
.