【问题标题】:What is the reason C++ doesn't add `std::vector<std::string>` "overload" as argument to `main()`?C++ 不添加 `std::vector<std::string>` “overload” 作为 `main()` 的参数的原因是什么?
【发布时间】:2017-03-13 00:33:42
【问题描述】:

是否有任何根本原因导致新的 C++17(或更高版本)不允许将 main 编写为其他方式

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

?我知道需要与以前的代码兼容,所以

int main(int, char**) 

仍然必须存在,但是有什么技术可以阻止第一个“替代”声明吗?

【问题讨论】:

  • 如果这样做,您会遇到每个 C++ 程序都需要了解 std::vector 的问题。这是很多额外的麻烦,没有太多好处。无论如何,您始终可以将argv 的内容添加到向量中。
  • 我不认为有任何技术原因不支持此功能。显然,您可以编写执行此操作的代码,因此运行时也可以代表您执行相同操作。
  • @BrandonIbbotson 和 std::string 也是!!
  • @Jean-FrançoisFabre 如果你写main(vector&lt;string&gt;),编译器可以很聪明地添加它们,如果你写main(int, char**),则不添加它们。 C++11/14/17 不鼓励使用原始指针,但当您第一眼看到 main 函数时就会看到它们。
  • @einpoklum 除了我已经提到的那些之外,我真的没有更多的理由来表达我的观点。我无法确定有多少人可能想要使用std::vector。对于严肃的命令行工具,我怀疑大多数使用预先编写的参数处理库。对于手写参数处理,我确实经历了将命令行参数传输到std::vector 的阶段,但是TBH 并没有比直接使用内置数组更容易。

标签: c++ command-line-arguments main stdvector


【解决方案1】:

以下是您自己的方法,很简单,只需几行代码:

auto my_main( std::vector<std::string> const& args ) -> int;

auto main( int n_args, char** args )
    -> int
{ return my_main( std::vector<std::string>( args, args + n_args ) ); }

Modulo notation 我相信这个方法在 Accelerated C++ book 中有介绍,也就是说,它是众所周知的。

无需将其添加到标准中:发现它有用的人只需复制并粘贴代码即可。

其他人可能觉得它没用:它在 Windows 中效果不佳,因为按照惯例,main 参数在 Windows 中不是 Unicode,而且 Microsoft 的 setlocale 明确不支持 UTF-8 语言环境。

【讨论】:

  • @vsoftco:谢谢!固定的。我真的需要一个更好的键盘……
  • 这根本不是小事。重点是让编码人员能够以这种方式编写main()...
  • @einpoklum:哦。它对你来说也是微不足道的。如果你继续使用 C++。 ;-)
【解决方案2】:

至少在一个方面,这可能有点难以实现。

这基本上需要一种反向查找形式的函数重载。也就是说,启动代码通常看起来大致是这样的:

extern int main(int argc, char *argv[], char *envp[]);

void entry() { 
    // OS-specific stuff to retrieve/parse command line, env, etc.
    static_constructors();
    main(argc, argv, envp);
    execute(onexit_list);
    static_destructors();    
}

使用您的方案,我们需要两段单独的启动代码:一段调用main 传递argc/argv,另一段传递std::vector&lt;std::string&gt;

我应该补充一点,虽然这意味着这项工作并不完全是微不足道的,但它仍然远不是一个无法克服的问题。仅举一个例子,Microsoft 的链接器已经根据您是否定义了mainWinMain(或wmainwWinMain)来链接不同的启动代码。因此,显然可以检测到用户提供的入口点的(损坏的)名称,并相应地链接到一组适当的启动代码。

【讨论】:

  • 老实说,我们已经重载,甚至在 C:int main(void) 中也是一个同样有效的签名,可以追溯到 C89。
  • @MSalters:正式地说,是的。然而,从实现的角度来看,它(通常)不像其他重载。在我见过的任何情况下,启动代码都会将参数放在那里,由代码决定是否使用它们。编译器参与其中,因为它具有不破坏main 名称的特殊知识,但仅此而已。这是不同的:您确实需要单独的启动代码,一种 C 风格,另一种创建字符串向量。你不能只做一件事,让接收方来决定如何使用它。
  • 我知道。早在 2003 年,我就认真考虑将此作为提案提交给 WG21。阻止我的是我试图让它在 GCC 中工作。毕竟,当您实际完成某项工作时,要让 CWG 相信某事是可行的要容易得多。但我根本没有看到合理的方法。
猜你喜欢
  • 1970-01-01
  • 2020-02-01
  • 2014-10-24
  • 1970-01-01
  • 2012-05-17
  • 1970-01-01
  • 2022-01-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多