ABC333 D 解説にある実装例
ABC333 Dの実装例にあった次の行がわからなかったので調べた
ranges::max(forest.groups() | views::transform((auto &&g) { return size(g); }))
質問
- | って何
- views::transform って何
- () {} って何
回答
- パイプ
- range と関数を引数にとり、range の各要素に関数を適用して view を返す関数
- ラムダ式
次の質問
- view::transform が関数だとして、問題の行は関数しか引数にとってない(range をとってない)じゃないか
- range, view って何
回答
-
第1引数に
viewable_range
を受け取ってview
を返すカスタマイゼーションポイントオブジェクトを、Rangeアダプタオブジェクトという。(中略)Rangeアダプタオブジェクト
adaptor
が2つ以上の引数をとる場合、以下の3つの式は等しい。adaptor(range, args...) adaptor(args...)(range) range | adaptor(args...)
[2]
これの3つ目の式が使われている(パイプライン記法というらしい?) - どちらもライブラリ<range>が定義するコンセプト
他の質問
- auto &&g って何
回答
※ auto&& の && は reference collapsing が働くことを意味しているものです
[3]
Reference collapsing と関連する語をひとまず次のように思うことにしました
思ってるだけなので間違えてたらごめんなさいアンド教えてください
Reference collapsing
今回はラムダ式の引数に &&g と書いてあり、引数として rvalue 参照が与えられたときだけ g は rvalue 参照、それ以外(lvalue, rvalue, lvalue 参照, あと何)が与えられたときは g は lvalue 参照になる
もし、今回 &&g と書いてあるところを &g にすれば、引数として何が与えられようと g は lvalue 参照になる
というように参照の参照ができたときにそれが lvalue 参照と rvalue 参照のどっちになるかを決めたルール
lvalue, rvalue
lvalue は名前のついてるオブジェクト(オブジェクトって何)、rvalue は一時オブジェクト
lvalue 参照, rvalue 参照
lvalue 参照は普通(?!)の参照。rvalue 参照は参照してる先を壊していい参照(ある状況で無駄なコピーを避けるのに有用らしい)
&g か &&g か
全部 &&g で生きていく
自分でも何が言いたいかわかっていないスピリチュアルコーナー
これまで範囲 for 文を、何も考えず cpprefjp から丸パクリしてから const auto &e を auto &e にして生きてきた
C++11の範囲for文を使うと以下のように書ける:
std::vector<int> v; for (const auto& e : v) { std::cout << e << std::endl; }
変数宣言には直接コンテナ内の要素の型(上記の例であれば
const int& e
など)を書いても良いし、型推論auto
を使うと、さらに簡潔に書ける。変数宣言にconst参照
const auto& e
を書くとコンテナ内の要素の変更を禁止し、要素のコピーも行わない。参照auto& e
を書くと、コンテナ内の要素を変更できる。実体auto e
を書くと各要素がコピーコンストラクタによってコピーされてからfor文に渡される。
変数宣言 e を変更可能か? コンテナ内の要素を変更可能か? const auto& e No No auto& e Yes Yes auto e Yes No
[4]
Reference collapsing を知ったいま、 &e と書いたら e は常に lvalue 参照となることが分かった。&&e と書いても rvalue 参照が与えられない限り e が rvalue 参照になることがないことも分かった。具体的にどんな状況か今の自分には想像できないが、絶対 lvalue 参照にしたいというときに &e を使うんでしょうか。範囲 for 文をするときは範囲をぶっ壊されたらいやだから何かの間違いで rvalue 参照になったらだめそう(だからauto &e と書くんでしょうか)。auto &&e: (ここに範囲に相当するオブジェクトを返す関数呼び出しを書く) とかやったら rvalue 参照になっちゃうんでしょうか。もうわからない
この記事は、自分が件の実装例にある一行を見たときにどのように調べたらよいかすらわからなかったので、関係ある語を列挙しただけのものです。ラムダ式やら view やら lvalue 参照やらについて厳密にご紹介しようという志はありません。
??? 「クネクネとC++について調べる時間で問題解いた方がレート上がりそう(おれのレートがクネクネとC++について調べるまでもない程度に低そうなため)」
参考
[1] AtCoder の記事"AtCoder Library (ACL)"から"document_ja/dsu.md"
[2] cpprefjp - C++日本語リファレンス の"リファレンス/<ranges>", [4] cpprefjp の "言語機能/C++11/範囲for文
[3] プログラミングの教科書を置いておくところ の"C++ 11 auto の使い方"、その他の関連する記事