稲枝の押入れ

いなえが適当なことを書いては、しまっておく場所

動作未定義になる名前

概要

C++では

  • (あらゆる場所で) __ (アンダースコア2つ)を含む名前 (ex.) int ho__ge;
  • (あらゆる場所で) _ で始まり大文字英字が続く名前 (ex.) int _Hoge;
  • (グローバル名前空間で)_で始まる名前 (ex.) int _hoge;

のいずれかを宣言もしくは定義してしまうと動作未定義となる。
これについては https://cpp.aquariuscode.com/taboo-identifiers などでも触れられている。

意外と知られていない様だがそれはいいとして、これが規格のどこに記述されているか示しているページが見つからなかったので書いておく。

今回はn4140のワーキングドラフトを参考にした。これはC++14に近いワーキングドラフトらしい。
(引用はpdfからコピペしたのでレイアウトが少し崩れているがご容赦いただきたい)

予約された名前の動作未定義

まず、予約された名前を宣言したり定義したりすると、規格で明示に許可された場合を除き動作未定義になるとされている。

17.6.4.3 Reserved names [reserved.names]
1 The C++ standard library reserves the following kinds of names:
(1.1) — macros
(1.2) — global names
(1.3) — names with external linkage
2 If a program declares or defines a name in a context where it is reserved, other than as explicitly allowed by
this Clause, its behavior is undefined.

処理系に予約された名前

その上で、冒頭で示した3つの条件にあたる名前は処理系向けに常に予約されていると記述されている。

17.6.4.3.2 Global names [global.names]
1 Certain sets of names and function signatures are always reserved to the implementation:
(1.1) — Each name that contains a double underscore __ or begins with an underscore followed by an uppercase
letter (2.12) is reserved to the implementation for any use.
(1.2) — Each name that begins with an underscore is reserved to the implementation for use as a name in the
global namespace.

結論

つまり、冒頭で示した3つの名前は予約されており、予約された名前を宣言もしくは定義すると動作未定義になるという建てつけで規格上は記されている。

余談

例えば以下は「明示に定義済マクロの名前はアンダースコア2つを含むか、アンダースコアで始まり大文字英字が続くべきである」とされていて、こういうものが「明示に許可された場合」に当たると思われる。

16.8 Predefined macro names [cpp.predefined]
(略)
4 If any of the pre-defined macro names in this subclause, or the identifier defined, is the subject of a #define
or a #undef preprocessing directive, the behavior is undefined. Any other predefined macro names shall begin
with a leading underscore followed by an uppercase letter or a second underscore.