中括弧付きの参照型の変数のdecltype
次のコードを検討してください。
#include <type_traits>
int main() {
const int& p = 42;
auto v1 = decltype(p){};
static_assert(std::is_same_v<decltype(v1), int>);
decltype(p) v2{};
static_assert(std::is_same_v<decltype(v2), const int&>);
// auto v3 = X(const int&)X {};
}
のタイプはv1
として推定されint
ます。同時に、のタイプはv2
として推定されconst int&
ます。の最初のステップはv1
、もう1つの型エイリアスusing T = decltype(p);
を追加してからを追加することとして扱うことができると思いますauto v4 = T{};
。この式(decltype(p){}
またはT{}
)はコンパイラによってどのように扱われますか?その{}
部分がインスタンス化用であることは知っていますが、結果の型がv1
参照型ではないのはなぜですか?
さらに別の質問:(の代わりに)明示的に記述された型を使用v3
するのと同じ型の変数を宣言する方法はありますか?v1
const int&
decltype(p)
標準へのリンクをいただければ幸いです。
回答
(反対派へ:スコット・マイヤーズを引用することは標準を引用することと同等ではないと思うために反対票を投じた場合、まあ...)
効果的なModernC ++から読むことができるように(そのリンクで検索することで到達できるエラッタの一部で補強されCase 2:
、次の読み取りが簡単になりますが、質問に必須ではありません):
場合は
ParamType
非参照である場合は、[...]expr
の型が参照され、参照部を無視します。[...]expr
がの場合はconst
、それもインゴアします。の場合は、それvolatile
も無視してください。
ここparam
で、は宣言指定子です。これは、あなたの場合は単なるauto
、つまり非参照です。
言い換えれば、あなたは、作成しているv1
平野を経てauto
(ないauto&
、それはあなたが参照するか、あるいはであるエンティティで初期化されているかどうかは関係ありませんので、コピーによってすなわち、)const
かない(またはvolatile
かどうか、FWIW)、あなたがそれをコピーしているからです。
より単純なケースについて考えてみてください。
int i = 3;
int& p = i;
auto v1 = p;
限りv1
懸念している、それは実際にそれが1でinitalizedされているかどうかは重要(ではないi
)、または他の(p
それによって)名前と同じ、それは実体があることをどのような値のコピーを取得しますので、実体が知られています。
auto
型の推定は、テンプレートの型の推定と同じように機能し(ブレース付き初期化子の処理方法の違いを除いて、この場合は関係ありません)、どちらもScottMeyersのEffectiveModern C ++を参照できます。