2011-12-06 69 views
15

一个鲜为人知的,但几乎从来没有使用C++的功能被赋予一个声明:功能尝试捕捉语法和主

void foo(); 

一个可能的,法律上的定义可能是:

void foo() try { 
    throw 42; 
} 
catch(...) { 
} 

这里whole function implementation wrapped is within a try/catch pair,这似乎与允许this相似。

这是合法的做int main()?例如:

int main() try { 
    throw 42; 
} 
catch(...) { 
} 

The rules for main,n3290§3.6.1谈论的大多是应该采取什么样的参数和它返回什么 - 他们似乎并不明确禁止这样做,因为他们与其他各种奇怪的东西呢(如联系)你可能会试图尝试。

这是合法的吗?

+2

有趣的学术问题,虽然我不确定它有很多实际用途。 http://stackoverflow.com/a/620817/10077 –

+0

法律?技术上大多数编译器都会支持它。定义良好?不是真的,因为我当然无法想出任何理智的做法。 – AJG85

+0

@ AJG85 - 我的意思是在“既不是未定义的行为也没有实现定义的行为”的意义上进行了定义,而不是在“经过良好测试的常见实现方式”方式 – Flexo

回答

7

该标准并没有禁止在[basic.start.main]它的使用,并同时迫使所有的实现支持至少int main() {/*...*/ }int main(int argc, char* argv[]) {/*...*/},并不限制这两个声明(3.6.1,第2段)的实现。

从孤立的看来,它至少会出现它是合法的,尽管当然只涉及函数声明而不是函数定义。

读上,[except.handle],第13周的状态如下:

例外中对象的析构函数抛出具有静态存储 持续时间或在名称空间范围对象的构造没有被捕获 main()上的function-try-block。 (15.3第13段)

它使放置在一个main()功能试块,这强烈地暗示,这种结构是合法的,并已定义的行为的具体提及。在信息中加入main()只是其名称和返回类型中的特殊信息,并且实现可能不会重载它以改变任何行为,但是它是一种非常强大的情况,它以正常方式运行,除非特别注意,例如上面的引用。换句话说,是的,这是合法的和明确的。

我在这个答案的第一个版本中提供的博客文章实际上很好地说明了上面的blockquote给出的规则,所以我会retain the link to it,即使它没有直接讨论OP中的问题题。

关于对OP的评论,您可以在函数尝试块和[except。句柄]有这样的说法:

流失功能尝试块的结尾等于返回 没有值;这会导致返回值 函数(6.6.3)中出现未定义的行为。 (15.3第15段)

如果你在的main一抓到底块的时候,你就不会流过函数的身体(这将是在这种情况下,试块) ,所以main自动调用return 0;的规则不适用。你需要返回一些int(很可能是一个错误代码),以防止未定义。

+1

没有太多的信息(关于定义),'静态'constatations非常简单:“全局”对象在'main'被调用之前被初始化并且在它返回之后被破坏...所以显然不在'try/catch'内块。至于关于构造函数语法的评论,是的,它很奇怪,但是并没有真正回答这个问题...... –

+0

我同意那个评估,并且已经注意到了;谢谢。我发现一个明确的引用'main()'有function-try-blocks,所以我认为这篇文章无论如何都是无用的。我将进行编辑以澄清此问题。 – matthias

+0

15.3的引用非常有趣。(这可能是我的下一个问题,如果它是合法的)结合约翰内斯与之相关的DR似乎可以回答它。 – Flexo

0

我试过了,它会编译,并按预期运行。一个奇特的表述,但我认为它没有违反任何规则。 为了清楚(自己和将来的代码mantainers),你也可以改换为:

int main() 
{ 
    try { 
     throw 42; 
    } 
    catch(int /*...*/) { 
    } 
} 
+4

它也适用于我的编译器。 “编译和运行”的问题是我知道我的编译器编译并运行了很多没有很好定义的东西。 – Flexo

+1

公平点,@awoodland。所以,如果有疑问,我会建议使用上面提到的公式,这似乎完全符合您的要求。尽管您的原始配方似乎没有违反标准的任何规定。 – alexandreC