decltypeには不思議がいっぱいです。
その驚くほど複雑な仕様は、彼ら闇魔術師の足元にも及ばない私には大変理解し難いものです。
以下のコードにあるdecltype((a))はその仕様のうちの一つです。
Cpp
1#include <iostream> 2 3int main() { 4 int a = 2; // int 5 decltype(a) b = a; // int 6 decltype((a)) c = a; // int& ←こ↑こ↓ 7 ++c; 8 decltype(auto) d = ++a; // int& 9 ++d; 10 11 cout << a << " " << b << " " << c << " " << d << endl; 12 13 return 0; 14} 15
何故()を付けると、参照型だと推論されてしまうのでしょうか。
decltype(auto)に関しては、「Effective Modern C++」という魔導書を読んだことで辛うじて理解できています・・・
トラックに轢かれても、彼らの世界にだけは転生したくありません。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答3件
0
C++11で導入されたdecltype
は、2003年の n1478 初版から最終的に2007年の n2343 (Revision 7)まで、長い期間議論された後に正式採用された言語機能だったようです。
n2115 (Revision 6) によれば、「変数名に対してはソースコード上で宣言している型」を直接探し出しますが、「ソースコードに登場しない式では左辺値(lvalue)は参照型とする」とあります。
2.2 Semantics of
decltype
Determining the typedecltype(e)
build on a single guiding principle: look for the declared type of the expressione
. Ife
is a variable or formal parameter, or a function/operator invocation, the programmer can trace down the variable's, parameter's, or function's declaration, and find the type declared for the particular entity directly from the program text. This type is the result ofdecltype
. For expressions that do not have a declaration in the program text, such as literals and calls to built-in operators, lvalueness implies a reference type.
この考え方を質問中コードに適用すると、次の通りとなります。
c++
1int a = 2; 2 3decltype(a) b = a; 4// 式a つまり 変数a はint型として宣言される → int 5 6decltype((a)) c = a; 7// 式(a) の宣言はソースコードに出現しない → int&
変数a
に対してdecltype(a)
とdecltype((a))
をどのように扱うかについては、C++11での正式採用に向けて議論を重ねる中でも変遷があったようです。
投稿2019/06/07 09:10
編集2019/06/07 13:05総合スコア6191
0
Chironian さんの回答の補足です。
何故()を付けると、参照型だと推論されてしまうのでしょうか
Chironian さんの回答の通り、decltype
の仕様として、そのように定義されているからです。decltype
は、その引数の式の型となるとは限りません。
この場合は、decltype 指定子 - cppreference.com における 説明 4) が適用されています。つまり、decltype((a))
で、引数(a)
はかっこで囲まれているint
型のlvalue
式なので、int&
と推論されています。
ですので、rvalue reference
とは直接関係ないと思われます。
(式が参照型を持つことはありません。C++ の式は、それぞれ2つの独立した性質、型および値カテゴリによって特徴付けられていますが、式が最初に型Tへの参照を持つ場合、その型はそれ以降の分析の前にTに調整されます。)
(また、lvalue
, rvalue
などついては、値カテゴリ - cppreference.com が詳しいです。)
投稿2019/06/07 04:32
総合スコア124
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
ベストアンサー
こんにちは。
decltypeの訓練はご存知でしょうか? これは比較的分かりやすい解説と思います。
eに括弧がない時はdecltype(e)はeの型そのもの(もっと条件は複雑ですが略)、中略、「eがlvalueならば、decltype(e)はT &である。Tはeの型である」と定義されているからのようです。
(a)は式ですから、一時領域(rvalue reference)を返します。rvalue referenceはlvalueなので後半の条件に該当しT&となるという寸法のようです。
さて、「rvalue referenceはlvalue」が謎ですよね。「お前は何を言っているんだ?」と感じます。
以前、拙いですがところで右辺値参照は左辺値ですで解説したことがあります。
分かりやすいとは言えませんが、多少はヒントになるかも知れません。
【alphyaさんの回答を見て修正】
(a)はてっきり一時領域を返すと思っていたのですが、(例えばstd::vectorのoperator[]やatと同様)これの結果は左辺値参照と理解しておけば良さそうです。(a)=123;
が通りました。(一時領域ならエラーになる筈です。)
左辺値参照は当然lvalueなので int& になるということのようです。
投稿2019/06/06 17:53
編集2019/06/07 07:23総合スコア23272
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/06/07 02:01
2019/06/07 08:15
2019/06/07 09:14
2019/06/07 16:02 編集
2019/06/07 09:53 編集
2019/06/07 09:58
2019/06/07 10:04
2019/06/07 11:24
2019/06/07 12:19
2019/06/07 12:24
2019/06/07 13:45
2019/06/07 14:18 編集
2019/06/07 15:49 編集
2019/06/07 15:59 編集
2019/06/07 16:08
2019/06/07 19:18
2019/06/08 01:16
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/06/07 10:00
2019/06/07 10:04