2016-08-15 7 views
3

[質問#38]ほとんどの厄介な解析

#include <iostream> 

struct Foo 
{ 
    Foo(int d) : x(d) {} 
    int x; 
}; 

int main() 
{ 
    double x = 3.14; 

    Foo f(int(x)); 

    std::cout << f.x << std::endl; 

    return 0; 
} 

タイプFooと入力します。私が知る限り、これは最も厄介な解析の例です。私の質問は、この構文は何ですか。int(x)文中のFoo f(int(x));を意味しますか?これまでのところ私だけのような関数宣言を見た:

  1. Foo f(int);

  2. Foo f(int x);

Foo f(int x);として、それは同じですか?

答えて

2

int(x)の文Foo f(int(x));の意味は?

xのまわりのかっこは余計で無視されます。したがって、int(x)int xと同じで、タイプintxというパラメータを意味します。

Foo f(int x);と同じですか?

はい。 Foo f(int(x));は、fという名前の関数宣言で、Fooを返し、タイプintxという1つのパラメータをとります。

これは標準からの説明です。 $8.2/1 Ambiguity resolution [dcl.ambig.res]

(強調鉱山)

関数スタイル キャストとも宣言の コンテキストで起こり得る[stmt.ambig]に記載された宣言の間の類似性から生じる曖昧。このコンテキストでは、 パラメータ名の周りの括弧の冗長なセットを持つ 関数宣言と、イニシャライザ という関数形式のキャストを持つオブジェクト宣言の間で選択します。 [stmt.ambig]に記載されているあいまいさの場合と同様に、は、 がおそらく宣言のとなる可能性のある構造を考慮することです。 [注:宣言には、引数のまわりに括弧を追加することによって、明示的に曖昧さのない を指定できます。 あいまい性は、コピー初期化または リスト初期化構文の使用、または非ファンクションスタイルのキャストの使用によって避けることができます。 - エンドノート] [例:

struct S { 
    S(int); 
}; 

void foo(double a) { 
    S w(int(a));  // function declaration 
    S x(int());  // function declaration 
    S y((int(a))); // object declaration 
    S y((int)a);  // object declaration 
    S z = int(a);  // object declaration 
} 

- 終了例]

したがって、int(x)は(パラメータ)宣言として考えるのではなく、関数スタイルのキャスト。

4

問題は、私には分かりませんが、プロトタイプのパラメータ名を括弧で囲むことは有効です。だから、

Foo f(int(x)); 

は、本当の問題は、C++著者らは、また、私には未知の理由のために、それがあったと判断していることがある

Foo f(int); 

と考えられている

Foo f(int x); 

と解釈することができますほとんど同じセマンティック(インスタンスの初期化)のために2つの異なる構文形式を持つようにクール

これは、「何かが宣言と定義の両方になることができれば、それは宣言です」というトラップをトリガすることによって「解決」される構文のあいまいさを導入します。

したがって、C++パーサーは、最初のものの意味的意味が何であるかを決定する前に、任意の数のトークンを解析できる必要があります。

これは明らかにコンパイラライター以外の問題ではありませんでしたが、それを理解するためにC++コードを読んでいる人も同じことができなければならないことを意味します。それから "最も厄介な"。

+1

'int * a [10]'を 'int(* a)[10]'と違うようにする必要があるので、これは許されます。そして、誰も必要なときに構文を* only *に制限するのに気をつけませんでした。 –

+0

@BoPersson:コードを見ましたが、[Vexing Parseについての混乱した詳細](http://stackoverflow.com/questions/7007817/a-confusing-detail-about-the-most-vexing-parse)、および正直私はそれを理解していない:(。 – NeonGlow

+0

@NeonGlow rulsは同じで、関数に2つのパラメータがあり、2つ目に関数ポインタがあるとします。 – songyuanyao