27

I was trying to create a program that takes arguments by command line, using main() function arguments. As a (basic) C++ programmer (even if I know quite well pointers and array in C-style) I hardly ever used char* strings and C-arrays. I spent some to take main() arguments and transform it in std::string... So asked myself: why in C++ the main() function is not overloaded to take an std::vector<std::string> argv instead of the old char* argv[]?

For "overload" I mean the coexistence of main() functions like int main() and int main(int argc, char *argv[]), not the overloading of a normal function made by the programmer.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
  • It is pretty trivial to stuff things into a vector of strings, but creating a char* argv[] from a vector of strings is not. – PlasmaHH Aug 22 '12 at 12:01
  • @PlasmaHH Yes. Why couldn't the compiler add the single ctor call required for this overload? –  Aug 22 '12 at 12:01
  • Aside from the actual question, a couple of notes: `main` is not and cannot be overloaded. What you are asking is why the implementation won't use a different version of `main` (overloading happens when *you* create new functions with the same name and different signature, but there can be only one `main` in the program). The answer to that is that the standard does not mandate either way. It requires two signatures to be always present: `int main()` and `int main(int,char**)`, but it does not inhibit compilers from accepting others like `int main(std::vector)` – David Rodríguez - dribeas Aug 22 '12 at 12:11
  • 1
    @DavidRodríguez-dribeas I know `main()`cant be overloaded by the user. I mean "overloded" on the language. We already have two standard version of main. –  Aug 22 '12 at 12:13
  • I would say because `vector` and `string` are non-trivial types (and frankly, quite bulky), requiring memory management etc. Therefore it goes against the philosophy of C++. For the next version (C++1x for those keeping tabs), there is a proposal for a `std::basic_string_ref` class, which would be a non-owning string (ie, just a size and a pointer into a character array). If we combine `std::string_ref` with the C++11 initializer list, then we could get something like `int main(std::initializer_list argv)` without any memory management. It is still time to make the proposal. – Matthieu M. Aug 22 '12 at 12:13
  • 1
    how is this a duplicate of http://stackoverflow.com/questions/6408183/is-main-overloaded-in-c ? imho this should be re-opened – stefan Aug 22 '12 at 12:14
  • 6
    The "duplicate" merely asks *if* main() is overloaded (it isn't). This question is clear about the fact, and asks for the *reason*. Not duplicate at all, voted for reopen. – DevSolar Aug 22 '12 at 12:15
  • @R.M.: You are abusing the term *overloaded*, and doing so against the standard that explicitly requires that **main shall not be overloaded** (§3.6.1/2). The nitpick is that a function is overloaded if there exists at least two functions in the program with the same name and different sets of arguments. There can only be **one** `main` in the program. This is really only a nitpick, but technical writing requires precision in the words. To provide a metaphor, would you say that my house has two locks because both me and my wife have keys to the single keyhole? – David Rodríguez - dribeas Aug 22 '12 at 12:32
  • @DavidRodríguez-dribeas I know, you are right. Wrong term! I edited the question. –  Aug 22 '12 at 12:34
  • What would be the point? The arguments are already allocated, so there's no need for duplicating them into another storage. – Kerrek SB Sep 02 '12 at 22:44

5 Answers5

34

Why isn't it in the standard? Simple:

Because nobody proposed it.

Things go into the C++ standard because someone writes a proposal for it, then gets other people to vote on it and incorporate it. Unless someone actually wants it to happen, it doesn't get to happen.

And considering how trivial this feature really is:

int main(int argc, char **argv)
{
    std::vector<std::string> args(argv, argv + argc);
    ...
}

There just isn't any real need for it. It's a convenience function, and it doesn't even make things that convenient compared to the alternative.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • 5
    I always listen here on SO from C++ programmers that stop using `char[]` & `char*` & use `std::string` in C++. Then why nobody proposed it so far ? – Destructor Apr 11 '16 at 15:10
20

why in C++ the main() function is not overloaded to take an std::vector argv instead of the old char* argv[]

Because that demands dependency on <string> library. C++'s philosophy is always "don't pay for what you don't use". If someone doesn't want the automatic memory management offered by string then they can't be enforced.
2nd view: If some platform doesn't have any library support then you cannot start your C++ program!!

On the contrary, int and char** arguments are built-in and independent types. One can always write custom wrapper on main() which does exactly whatever is the need.

Edit: On AProgrammer's comment:
Suppose that main(vector<string>) is allowed; then if a platform conforms to all C++ features, but don't have standard library support then it will become non-standard compliant.

iammilind
  • 68,093
  • 33
  • 169
  • 336
  • 17
    How allowing the possibility of `int main(std::vector)` without preventing `int main(int, char**)` would break the _pay only if you use_ philosophy? – AProgrammer Aug 22 '12 at 12:11
  • 4
    @AProgrammer: Actually the standard allows the implementation to *add* new valid options for `main`, as long as it still allows the two options defined in the standard. – David Rodríguez - dribeas Aug 22 '12 at 12:13
  • 1
    The "second view" is bogus. A C++ "implementation" that does not even have vector and string is as far from conformance as C is, and couldn't even run a **lot** of simple, standard-conforming, idiomatic C++ code. Also, by that logic we shouldn't be using C++ at all... or C. –  Aug 22 '12 at 12:15
  • @delnan, Consider real time system where it's not guaranteed to have many standard library. It's a matter of choice, not bogus. – iammilind Aug 22 '12 at 12:17
  • If it does not have half of the standard library, it is not C++. Why would the C++ standard be concerned how many other features an "implementation" that is already completely non-conforming would have to cut if they cut feature X? –  Aug 22 '12 at 12:20
  • @DavidRodríguez-dribeas: That, as an answer including a reference to chapter and verse of the standard, would be *my* top candidate for accepting. (As in, "if it isn't overloaded in your implementation, bugger your compiler vendor for it". ;-) ) – DevSolar Aug 22 '12 at 12:20
  • 3
    @delnan: It is a bit trickier than that. There are compilers that are shipped without a standard library implementation, for which you need to provide one. There are also cases where the compiler ships with an implementation of the standard libraries, but you don't want to use it (in my workshop we use our own tweaked standard library, so does Electronic Arts and a few more...). Not saying it cannot be done, but the compiler would have to read *your* includes and use whatever headers *you* have to generate a trampoline function that you can write yourself in a single liner. – David Rodríguez - dribeas Aug 22 '12 at 12:21
  • @iammilind: I *hate* (not with a passion) misuses of technical terms, as they lead to confusion. Nitpick: `main` can **never** be overloaded. Overloading is providing multiple functions with the same name and different signatures. On the contrary, and only for `main` the standard requires that there are **no overloads** in the program, and just states that implementations are required to accept two signatures of `main`. – David Rodríguez - dribeas Aug 22 '12 at 12:24
  • @DavidRodríguez-dribeas Oh, thanks for the info. Very interesting, mind posting that as an answer? –  Aug 22 '12 at 12:26
  • 4
    Well, I would say an implementation missing the standard library is not standard conformant (and thus no C++ implementation) in the first place. But I can perfectly understand your argument of not bringing in dependencies to non-builtin types, even if those are standard-provided. And +1 anyway for being the first one to approach this question from the more fundamental "why is the standard this way"-perspective instead of the "why it not work"-perspective of the other answerers. – Christian Rau Aug 22 '12 at 12:27
  • 1
    @DevSolar: §3.6.1/2 *An implementation shall not predefine the main function. This function **shall not be overloaded**. It shall have a **return type of type int, but otherwise its type is implementation-defined**. All implementations shall allow both of the following definitions of main: `int main()`, `int main(int,char**)`* – David Rodríguez - dribeas Aug 22 '12 at 12:28
  • "then if a platform conforms to all C++ features, but don't have standard library support then it will become non-standard compliant." No, then it was *already* non-standard compliant! – GManNickG Aug 22 '12 at 16:33
4

The main reason, I suspect, is because the usual implementation is to make it an extern "C" function, with varargs. In a lot of implementations, it is the C runtime library which calls main.

There are many ways around this, but none of them seem worth the bother, given how easy it is to convert the arguments to whatever you want.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
2

It would be trivial for a compiler to compile a main defined as

int main(std::vector<std::string> args) {
    ...
}

as it has been written as

int main(int __argc, char **__argv) {
    std::vector<std::string> args(__argv, __argv+__argc);
    ...
}

It would be even about as easy to allow any container, even custom one, and not just std::vector<std::string>. But it isn't standard because ­— standard answer to why isn't this in the standard — nobody proposed it and convinced enough people that it was a good idea. I don't think there was a proposition, so there is probably no rationale for its rejection. The change is probably to simple for most of involved people to bother.

AProgrammer
  • 51,233
  • 8
  • 91
  • 143
1

Basically, a std::vector is NOT the same (in memory layout or anything) as an array of char *. To permit this, you'd have to make the compiler recognise the new main declaration and add a wrapper on entry that created a vector of strings.

Given you were doing that, you might as well throw argc away as well, and have the declaration of main be

int main(std::vector<std::string> argv)

But it's work for the compiler. You'd have to get a lot of people who thought it was worthwhile.

Otherwise you can just do it yourself

int main(int argc, char **argv)
{
    std::vector<std::string> args;
    args.reserve(argc);
    for (std::size_t arg = 0; arg < argc; ++arg)
    {
         args.push_back(argv[i]);
    }
    return mymain(args);
}

Code is not guaranteed to compile or work cos I just wrote it off the top of my head.

or (better, thanks to AProgrammer)

int main(int argc, char **argv)
{
    return mymain(std::vector<std::string>(argv, argv + argc));
}
Tom Tanner
  • 9,244
  • 3
  • 33
  • 61
  • 4
    `std::vector args(argv, argv+argc);` is enough. I don't think it's performance sensitive enough to even warrant a reserve. – AProgrammer Aug 22 '12 at 12:15
  • 1
    @AProgrammer: Not only it is not sensitive enough (and there are not that many arguments usually), but in many implementations the constructor that takes 2 iterators (this case) performs a single allocation. – David Rodríguez - dribeas Aug 22 '12 at 12:18
  • oh, nice. I don't do that many create vector from range things. – Tom Tanner Aug 22 '12 at 12:19
  • Well, compiling a language is indeed work for the compiler. I guess the question was not so much about why compilers don't provide such an overload, but why it isn't defined that way in the C++ standard in the first point. – Christian Rau Aug 22 '12 at 12:23
  • @Christian - well, originally std::vector, std::string and the rest of the STL weren't part of the language. And after that, I don't think there was much call for it – Tom Tanner Aug 22 '12 at 12:24
  • @TomTanner That's what I would think, too. There was a long time until `std::string` became the idiomatic way to work with strings. But *iammilind* has a good point, too. – Christian Rau Aug 22 '12 at 12:30
  • 1
    @TomTanner The call is maybe for new C++ programmers. Im a physicist and not a programmer but in our C++ course the professor told us to use std::vector or std::array instead of C-arrays. We didn't see in class C-arrays nor string as char*... –  Aug 22 '12 at 12:33
  • 3
    @R.M. Wow, you're one of the lucky few to get teached proper C++ from the start. – Christian Rau Aug 22 '12 at 12:34
  • @R.M. You'll be very lucky to never see either. Your course should at least teach you how to deal with them - the chances are that if you are talking to the O/S, you'll need them. – Tom Tanner Aug 22 '12 at 12:43
  • 1
    @TomTanner We saw pointers in deep, so understanding char* strings is not so complicate. And neither are C-arrays. As I said, it was a C++ course for physicians, not for programmers. Anyway I studied it by myself, but I newer used it: I think C++ goes to garbage collecting (see smart_pointers), so a medium-level programmer can "stay safe" using STL and libraries. –  Aug 22 '12 at 12:50
  • 1
    @RM: That's how programmers should be taught! It's not staying safe, is staying correct and clean. :) Any good C++ programmer avoids unnecessary complexity, just as you were taught. – GManNickG Aug 22 '12 at 16:35
  • 2
    C++ doesn't do garbage collection. It is up to the programmer to free memory they've allocated. smart pointers help that, but that's all – Tom Tanner Aug 23 '12 at 09:17