LoginSignup
3
2

More than 5 years have passed since last update.

mainとodr-usedとpotentially evaluatedの関係

Last updated at Posted at 2012-11-26

GCC Bugzillaで見つけたC++言語仕様のスミをつつく指摘と、そこから調べてみて分かったC++03とC++11との微妙な差分に関する話題です。
(そもそもmain関数をアクロバティックに使うべきではありませんし、そんな必要もないと思います…)

お話の前提

C++言語仕様では、mainをプログラム内から使用する("odr-used")ことは禁止されています。
もちろん、普通に「プログラム開始時に呼び出されるmain関数を記述する」ことは可能です。ここで言う「使用できない」とは、他関数からmain関数を呼び出し/main関数自身で再帰呼び出しを行ったり、main関数のアドレスを取ったり(&main)が許可されないことを意味します。この仕様に関してはC++03/C++11で変更はありません。

GCC Bugzillaでの指摘

Bug 41431 - &main should be allowed within unevaluated operands. の要旨:
sizeof演算子のオペランドは"potentially evaluated"では無いから、One Definition Ruleが定めるところの"(odr-)used"ではない。つまりsizeof(&main)はOKであり、これに対して警告を出すGCCは間違っている。

補足:「sizeof演算子オペランドは"potentially evaluated" expressionではない」「(大まかに)"potentially evaluated" expression内で用いることを"(odr-)used"と定める」は、C++03/C++11で共通の仕様です。

C++03とC++11との差異

確かにISO C++03からWorking Draft N3126までは "The function main shall not be used (3.2) within a program."(§3.6.1 [basic.start.main]) と記述されており、言語仕様上は「"(odr-)used"で無い箇所ならばmainを使っても良い」、つまり「sizeofでは"(odr-)used"とならないからsizeof(&main)はOK」と解釈可能です。
一方、C++11(N3337)では "The function main shall not be used within a program" となっています。ここでは定義された用語"odr-used"で明に記述していないため、プログラム内のどこであってもmainの使用("use")は許可されず、結局は「sizeof(&main)もNG」と仕様変更されたように読みとれます。

このOne Definition Rule(§3.2 [basic.def.odr])については、仕様上の用語(term)としての"used"と、一般動詞としての"used"が区別できず曖昧であるとの指摘をうけ、N3154 US 19: Ambiguous use of "use"およびN3214 US 19: Ambiguous use of "use" (version 2)で用語"odr-used"が導入された経緯があります。
初版N3154では一旦[basic.start.main]も"odr-used"へと変更する候補にあがっていましたが、続くRev2 N3214では明示的に一般語"used"に変更されています。残念ながら、この変更の根拠までは見つけられませんでした。

おしまい。(どなたか理由までご存知でしたら教えてください)

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2