web-dev-qa-db-ja.com

decltype動作の根拠は何ですか?

C++ 11で理解したように、decltype(expression)は、指定された式とまったく同じ型を推定するために使用されます。ただし、式自体が括弧で囲まれている場合、推定される型は式の型へのlvalue参照です。例えば:

_int x;
decltype(x) y = x;
_

_int y = x;_と同等ですが、

_int x;
decltype((x)) y = x;
_

_int& y = x;_と同じです。

それぞれ

_ decltype(auto) f1()
 {
   int x = 0;
   return x; // decltype(x) is int, so f1 returns int
 }
_

だが

_ decltype(auto) f2()
 {
   int x = 0;
   return (x); // decltype((x)) is int&, so f2 returns int&
 }
_

この行動が標準委員会によって選択される理由は何ですか?

あとがき:

ここで、少なくともGCC 6.2実装の場合、括弧内の式がより複雑な場合、たとえばdecltype((x + x))と推定された型はTですが、 _T&_ではありません。これはさらに混乱します。この動作が標準的なものかどうかはわかりません。

57
bobeff

彼らは、識別子の宣言のタイプを取得する方法を求めていました。

彼らはまた、それが一時的なものであるかどうかに関する情報を含む、式のタイプを取得する方法を望んでいました。

decltype(x)は、識別子の宣言された型xを提供します。識別子ではないdecltypeを渡すと、型が判別され、lvaluesには&、xvaluesには&&、prvaluesには何も追加されません。

概念的には、変数のタイプと式のタイプの違いと考えることができます。しかし、それは標準がそれを説明する方法とは全く異なります。

彼らは、これら2つのことを意味する2つの異なるキーワードを使用することができます。彼らはしませんでした。

エンティティと式を区別する必要があります。

次の質問を検討してください。

ミシシッピ州はどのくらいですか?

この質問には2つの回答があります。

  1. ミシシッピの長さは2,320マイルです。
  2. ミシシッピは11文字です。

同様に、xのタイプについて質問し、xが識別子である場合、その識別子を宣言するために使用されたタイプ(つまり、名前に関連付けられたタイプ)を意味するかどうかは明確ではありませんx)、またはその識別子の唯一の言及からなる式のタイプ。実際、2つの異なるキーワードが存在する可能性があります(例:entity_typeおよびexpr_type)単一のオーバーロードされたdecltypeの代わりに。何らかの理由で、委員会はこれら2つの異なる使用法のためにdecltypeをオーバーロードすることを選択しました。

24
Leon

decltype提案の著者の1人、J。Jarvi氏は次のように述べています。

久しぶりですが、私が覚えていることは次のとおりです(覚えていると思います)。

これらの2種類のセマンティクスを区別するための2つの個別のキーワードは考慮されていません。 (新しいキーワードの導入は簡単には行われません)。

decltype((x))のセマンティクスの変更に関して、コアのワーキンググループでの議論は、おそらく言語との「内部的に一貫性がある」識別子ではなく、式として_(x)_を扱うことに集中しました。ルール。

これは場合によっては混乱を招く可能性があることを人々は認識していましたが、コンセンサス(おそらく全員の好みではないかもしれません)は、最終的には、識別子とは何か、式とは何かに関する標準の以前の定義と一致することになっていました。

[この質問の例]にリンクする例は、本当に驚くべきものです。当時、decltype(auto)を使用して戻り式から関数の戻り値の型を推定することはまだ言語の一部ではなかったため、この特定のユースケースが誰の目にもあるとは思いません。

18
Columbo