3

C/C++ での「最も厄介な解析」の問題を理解しようとすると、すぐにこの質問が頭に浮かびます。なぜこの問題を引き起こす構文があるのでしょうか?

例えば、

class Timer
{
public:
    Timer();
};

class TimeKeeper
{
public:
    TimeKeeper(const Timer& t);

    int get_time()
    {
        return 1;
    }
};

int main()
{
    TimeKeeper time_keeper(Timer());
    // the above is eq to this: TimeKeeper time_keeper(Timer (*)());
}

TimeKeeper time_keeper(Timer())では、タイプ Timer を返す名前のない関数 ptr を受け取る関数宣言を単純に禁止しないのはなぜでしょうか? TimeKeeper time_keeper(Timer (*)())関数宣言子として劣っていますか?

このあいまいさが得られるのは、この構文が原因ではないのでしょうか、それとも何か不足していますか?

編集: 個人的にはTimeKeeper time_keeper(Timer())、関数宣言として使用したことはありません。Timer (*)()より明確にわかるように、関数ポインターを指定するために常に を使用してきました。

4

2 に答える 2

8

では、TimeKeeper time_keeper(Timer())が、名前のない関数ptrがTimer型を返す関数宣言であることを単純に禁止しないのはなぜですか?

名前のないパラメーターを使用しているため、しばらくの間、この関数宣言が許可されていないとし ます。その場合、次の宣言も許可されません。

int max(int,int);  //error (in hypothetical C++)
int min(int,int);  //error (in hypothetical C++)

そしてプログラマーは、宣言にもパラメーター名を書き込むように強制されます。

int max(int a,int b);  //ok 
int min(int a,int b);  //ok 

しかし、他の誰かが立ち上がって、「パラメータ名を使用しないのに、なぜ宣言にパラメータ名を書かなければならないのですか?なぜそれはオプションではないのですか?」と尋ねるでしょう。

この男は合理的であり、彼が尋ねたことには意味があると思います。プログラマーに宣言のパラメーターに名前を付けるように強制することは、確かに不合理です。

-

コメントを読むと、次の宣言はまったく同じだと思うようです。

int max(Timer());
int max(Timer(*)());

いいえ。動作の観点からはまったく同じですが、構文の観点からはまったく同じではありません。

微妙な違いは、前者の場合、パラメータ型は何も受け取らずにを返す関数であるのに対し、後者の場合、パラメータ型は何も受け取らずにを返す関数へTimerポインタTimerであるということです。違いがわかりますか?

しかし、問題は、なぜそれらが同じ振る舞いであるのかということです。答えは、前者の宣言では、パラメータ型が調整されてからポインタ型になるため、2番目の宣言と同じように動作します。

C ++ 03規格は、§13.1/3で次のように述べています。

一方が関数型 であり、もう一方が同じ関数型へのポインタであるという点でのみ異なるパラメータ宣言は同等です。 つまり、関数型は関数型(8.3.5)へのポインタになるように調整されます。

C++11でも同じだといいのですが。

-

あなたの疑問(コメントから引用):

なぜ2つの構文が必要なのかを理解するのにまだ近づいていませんか?

2つの異なるタイプだからです。関数型、および関数型へのポインタ。パラメータタイプとしてのみ、同じように動作します。そうでなければ、それらは異なります。ここで私の答えを見て、それらがどこで異なって動作するかを確認してください:

そして、それらは他の状況では異なった振る舞いをするので、私たちはそれらを持っています、私たちはそれらを必要としています。標準は、パラメータタイプとして同じように動作するという理由だけで、1つの構文を禁止しません(そして禁止すべきではありません)。

于 2012-07-18T06:46:21.053 に答える
3

ただ...あなたが聞いたことがあることに注意してください:)

C++11 では、統一された初期化構文を導入することで、この問題に具体的に対処しました。これで書くことができTimeKeeper time_keeper{Timer{}};、解析のあいまいさはありません。

于 2012-07-18T07:49:15.603 に答える