2013-05-20 13 views
13

私はついにを読んできました。私はなぜ後尾型が必要なのか理解できません。C++ 11で必要な末尾戻り型の追加はなぜですか?

私は問題を強調するために使用され、次の例に出くわした:

template<class Lhs, class Rhs> 
    decltype(lhs+rhs) adding_func(const Lhs &lhs, const Rhs &rhs) {return lhs + rhs;} 

decltype(lhs+rhs)が動作しないため、識別子lhsrhsは、解析フェーズの後にのみ有効ですので、例は、違法です。

私の質問は、decltypeタイプの解像度のタイミングについてです。私が間違っていない場合は、キーワードdecltypeを使用して、コンパイル時に式の型を判別します。

すべての解析が完了した後に、decltypeがタイプの解決を実行することに欠点がありません(上の例でうまくいくでしょう)。私が代わりに、C++ 11標準では、トレーリングリターンタイプを提供し

...これが問題を解決するための簡単な方法だっただろうと信じて:

template<class Lhs, class Rhs> 
    auto adding_func(const Lhs &lhs, const Rhs &rhs) -> decltype(lhs+rhs) {return lhs + rhs;} 

私は、私が行方不明です疑いはありません何か、後の戻り値の型の他の使用を見ることができないので。私の推論の欠陥はどこにありますか?

完全な関数本体を解析した後にdecltype型の解像度を持つことができるので、後ろ向き戻り型はあまりにも複雑な解決策のようです。

答えて

18

全ての解析が完了した後(上記の例では正常に動作することになる)タイプの解決を行います。

欠点は、C++の解析と処理モデルの基本的な基礎を根本的に変えなければ不可能だということです。

あなたの提案を行うために、コンパイラはdecltypeの構文を参照し、構文の内容の基本的な字句解析を行う必要があります。次に、ソースファイルをさらに解析します。後のある時点で(?)、私は以前見たことがあるかどうか、私はそれらの解析作業をすべてやります。

一般的な規則として、C++では、シンボルの定義にはの先にと表示されません。 C++構文解析フレームワークの基本的な前提は、シンボルが使用される前に宣言されていなければ、コンパイラエラーであるということです。

クラスは先読みで逃げることができますが、そのメンバーに関してのみ実行できます。これは、id式がメンバ変数を参照している可能性がある(つまり、すでに宣言されているスコープ内のローカル変数またはグローバル変数を参照していない場合など)ここではそうではありません。id表現が正確に何を指しているのかはわかりません。

さらに、あなたが示唆するものはあいまいさを作り出します。これはどういう意味:

int lhs; 

template<class Lhs, class Rhs> 
    decltype(lhs+rhs) adding_func(const Lhs &lhs, const Rhs &rhs); 

すると、グローバルlhs変数に参照のうえdecltype構文、またはローカルlhs関数のパラメータですか?

int lhs; 
float rhs; 

template<class Lhs, class Rhs> 
    decltype(lhs+rhs) adding_func1(const Lhs &lhs, const Rhs &rhs); 
template<class Lhs, class Rhs> 
    auto adding_func2(const Lhs &lhs, const Rhs &rhs) -> decltype(lhs+rhs); 

adding_func1グローバル変数を参照:

我々は今それを行う方法は、これら二つの間に明確な線引きがあります。 adding_func2は、関数パラメータを参照します。

地球のすべてのC++コンパイラを根本から壊すことができます。あるいは、戻り値の型を遅く指定することもできます。

また、C++のアプローチとnot bother to state it at allを使用することもできます。

+0

あなたの優れた答えをありがとう、私は今の使用を参照してください。私はC++ 14リファレンスのために余分なクッキーを与えることができたらいいと思う! –

+0

C++ 14の場合:それが最終的に含まれる予定ですか?それはドキュメントの面で傷つく世界のように聞こえる... – MFH

+0

@MFH:それは[C++ 14コミュニティドラフト](http://isocpp.org/blog/2013/05/new-paper-n3690-programming-言語 - C委員会ドラフト)。予期しない結果を招いているので、おそらくC++ 14になるだろう。そして、はい、それはドキュメンテーションのために幾分苦痛かもしれません。しかし、もう一度、これは 'decltype'を使用して関数*のコード*に正確に対応する型を推論するような無意味な冗長性を持たないことを意味します。 –

4

まあ明らかな問題は、あなたがループを開くようになるということです。私はdecltypeを有するの欠点を見ることができない

typedef decltype(lhs+lhs) foo; 
foo lhs; 
+0

はい、私はそれがどのように問題になるかを見ています。しかし、これらの種類のものは私にとって明らかなプログラミングエラーのようであり、コンパイル時のエラーによって解決することができます。 –

+5

@MarcClaesen:しかし、それは "明確な"エラーではありません。このタイプのエラーを検出するには、コンパイラはHalting Problemを解決する必要がありますが、これは不可能です。 –

+0

ああ、私はそれを逃したとは信じられない。ありがとう@MikeSeymour! –

関連する問題