yohhoyの日記

技術的メモをしていきたい日記

Declaration or Expression?

プログラミング言語C++の文法では、宣言(declarations) と 式文(expression-satements) が曖昧になる箇所がある。なおプログラミング言語Cの文法にはこの曖昧さは存在しない。

struct X {
  X();
  //...
};

// X型の変数xをデフォルトコンストラクタで構築... のつもりが
X x();  // 「引数なしでX型を返す関数xの宣言」とみなされる

どちらにも解釈可能な曖昧なケースに対して、C++標準規格では宣言として扱うよう定めている。N3337 6.8/2より例示コードを引用:

T(*d)(int);        // 引数にint型をとりT型を返す関数へのポインタdの宣言
T(e)[5];           // 要素数5のT型の配列eの宣言
T(f) = { 1, 2 };   // T型オブジェクトfを宣言し、2つの引数で初期化
T(*g)(double(3));  // T型へのポインタgを宣言し、double型の値3で初期化

最後のケースは「ポインタ型変数をdouble型で初期化」と解釈され ill-formed となる*1。これは曖昧さ解決が文法解析(syntactic analysis)の問題として処理され、意味(semantics)の解釈とは独立であるため。

C++11で導入された Uniform Initialization を用いると、この曖昧を排除して式として解釈させることができる。


N3337 6.8/1, 6.8/3より部分引用。

1 There is an ambiguity in the grammar involving expression-statements and declarations: An expression-statement with a function-style explicit type conversion (5.2.3) as its leftmost subexpression can be indistinguishable from a declaration where the first declarator starts with a (. In those cases the statement is a declaration.

3 The disambiguation is purely syntactic; that is, the meaning of the names occurring in such a statement, beyond whether they are type-names or not, is not generally used in or changed by the disambiguation.

関連URL

*1:仮に式として解釈した場合は、「T型の一時オブジェクトを *g で初期化し、同オブジェクトの関数呼び出しオペレータ T::operator()(double) を値 double(3) で呼び出す」となる。