Why isn't main defined `main(int argc, std::vector<std::string> argv)`?

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(int argc, std::vector<std::string> argv)

?

Edit: Even better:

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

There are already multiple definitions of main to choose from, why isn't there a version that is in the spirit of c++?

So, in your dream, what's the point of argc? –  Seb Rose  Aug 13 '10 at 14:55
1  
is it legacy here? Going by the same argument 'argc' should be of type 'size_t' or some other data type which cannot be negative. –  Chubsdad  Aug 13 '10 at 14:55
 
@Seb Rose: Touché! –  Inverse  Aug 13 '10 at 14:58
2  
Implementations are free to offer other signatures for main provided they all return an int. So a better quetion would probably be why don't they? –  Dennis Zickefoose  Aug 13 '10 at 15:41
 

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 "allowstd::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.


Late answer, but I think it's the best. The real issue isn't compatibility with c or includes; it's the possibility of exceptions

Because C++ was designed to be (almost) backwards compatible with C code.

There are cases where C code will break in a C++ compiler, but they're fairly rare, and there's generally a good reason for why this breakage is required.

But changing the signature of main, while convenient for us, isn't necessary. For someone porting code from C, it'd just be another thing you had to change, for no particular gain.

Another reason is that std::vector is a library, not a part of the core language. And so, you'd have to#include <vector> in every C++ program.

And of course, in its early years, C++ didn't have a vector. So when the vector was added to the language, sure, they could have changed the signature of main, but then they'd break not just C code, but also every existing C++ program.

Is it worth it?

We already have multiple definitions of main to pick from, why not add a c++ish version? 

6  
True, that could be done. But is it really worth the bother? You can just make the first line of your programstd::vector<std::string> args(argv, argv+argc). The standard committee prefers only adding new things to the language if it offers significant advantages over a library approach. –  jalf  Aug 13 '10 at 15:11
 
Is it because to compile STL itself, one would require the standard library which in turn calls main? –  Chubsdad  Aug 13 '10 at 15:13
2  
@chubsdad: The standard library doesn't call main. –  GManNickG  Aug 13 '10 at 15:21
2  
Inverse, notice that the multiple versions of main are all compatible with each other using the C calling convention. If an RTL calls main(argc, argv, envp), but the function you've provided is justmain(int, char*[]), the extra third parameter is safely ignored. An RTL can be written to always call a single version of main without regard for which version you provided. But main(vector<string>)is incompatible with other versions, so the RTL (already compiled, in a separate .o file) would need to know what you provided in your source cod


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 and std::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 like std::ifstream and std::ofstreamoperating on const char* C-style strings rather than on std::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.

Because it will force you to include <vector> and <string>

Moreover, it will force you to use the same implementation of <vector> and <string> as the runtime library. –  Mike Seymour  Aug 13 '10 at 15:48
 
@Mike: But you don't neccessarily need to enter main from the runtime library. If the compiler generated a secret function that the runtime library would find that converted from the C arguments to the C++ types of your choice and then called the actual main, there shouldn't be a conflict. Unless I'm missing something, it would be a completely transparent change. –  Dennis Zickefoose  Aug 13 '10 at 16:21
1  
However, you already have the option of at least 2 variants of main(). Adding a C++ specific one doesn't necessarily mean you'd be forced to use it (the existing options could remain as options). This might well complicate the machinery that the compiler/linker would need to support calling the right main() correctly, but it's not impossible. I'm not saying it would necessarily be worth the cost & complications - just that it's not impossible. –  Michael Burr  Aug 13 '10 at 16:33
 
You could even go one step further and the compiler could allow any single argument, provided it can be constructed from a pair of bidirectional iterators. int main(T args); int _Main(argc, argv) { return main(T(argv, argv + argc); } –  Dennis Zickefoose  Aug 13 '10 at 16:34

Like @jalf, I sometimes find myself writing

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

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 of int vmain(const std::vector<std::string>& args).

The runtime already has to know something about C++, to create and destroy static objects and handle uncaught exceptions. So it wouldn't be a huge leap to allow C++-specific variants of main; the only real objection to this one is that you'd have to standardise the implementation of vector and string. –  Mike Seymour  Aug 13 '10 at 15:53
 
@Mike Seymour: I guess you're right.. And then the question comes up why exactly std::basic_string<char> and why exactly std::vector. I would vote for int main(std::initializer_list<std::initializer_list<CharT>>)! –  Cubbi  Aug 13 '10 at 16:17
1  
To take this one step farther - just have a main() snippet that you can have as a starting template in your editor/IDE that does nothing but return cppMain( vector<string>(argv, argv+argc)); and use cppMain() as the 'customizable' starting point of your program. I may actually start using this... –  Michael Burr  Aug 13 '10 at 16:21

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 veryseriously.

link | improve this answer
 
feedback

Basically, to remain compatable with C. If we were to give up that, main() would be moved into a class.

link | improve this answer
 
12  
why on Earth would you move main into a class? That doesn't even make sense to do. Java and C# only do it because non-member functions are disallowed by the language. But that doesn't make it an any less terrible design decision –  jalf  Aug 13 '10 at 15:02
feedback

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.

link | improve this answer
 
feedback

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() is extern "C" by default, and that you can't overloadextern "C" functions.

For more fun, void main(void).

link | improve this answer
 
You forgot the wmain's –  Inverse  Aug 13 '10 at 17:19
 
That seems to be a VC++ feature. It's not obvious how it's implemented (it links to a different runtime, maybe?). –  tc.  Aug 13 '10 at 19:20


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值