1 名前:デフォルトの名無しさん (ワッチョイ dfcf-HvS5) mailto:sage [2017/01/09(月) 14:49:27.56 ID:p96WJVyd0.net] 次スレを立てる時は本文の1行目に以下を追加して下さい !extend:on:vvvvv:1000:512 C++に関する質問やら話題やらはこちらへどうぞ。 ただし質問の前にはFAQに一通り目を通してください。 IDE (VC++など)などの使い方の質問はその開発環境のスレにお願いします。 前スレ C++相談室 part128 echo.2ch.net/test/read.cgi/tech/1480172629/ このスレもよろしくね。 【初心者歓迎】C/C++室 Ver.100【環境依存OK】 echo.2ch.net/test/read.cgi/tech/1478440682/ ■長いソースを貼るときはここへ。■ codepad.org/ https://ideone.com/ [C++ FAQ] https://isocpp.org/wiki/faq/ www.bohyoh.com/CandCPP/FAQ/ (日本語) VIPQ2_EXTDAT: default:vvvvv:1000:512:----: EXT was configured
684 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/18(土) 12:48:34.92 ID:waR+gchT0.net] それで話を戻すと、 「継承関係無しで、自分自身でもないクラス G をbind出来るか?」 というのが俺の問いね。 お前は日本語にもこだわるタイプのようだから、「自分自身でもない」と明記しておく。 (これは普通に分かると思いたかったが) 要するに俺は、 「静的型であるC++に於いてthisのバインドって意味あるのか?」 と問うている。 動的型ならバインド後にメンバ追加して実行時に揃っていればダックタイピング可能だから意味がある。 静的型はバインドする時点でメンバが揃っていることを確定出来ないといけない。 それって要するに継承関係がないと無理だよね?という話。
685 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/18(土) 12:51:40.31 ID:waR+gchT0.net] × 静的型はバインドする時点で ○ 静的型はバインドが使われているソースをコンパイルする時点で 一応訂正しとくわ。分かる範囲だとは思うが。
686 名前:デフォルトの名無しさん (ワンミングク MM5f-W3uL) mailto:sage [2017/03/18(土) 13:01:24.39 ID:TmvAgLdoM.net] 何が言いたいのか全然わからん とりあえず、そのJavaScriptでできると主張しているコードを晒せ 第一引数にthisをバインドする意味って、内部的にはメンバメソッドはオーバーロード(+マングリング)で解決されるんだから、バインドしとかないと動かねーだろがよ
687 名前:デフォルトの名無しさん (ワッチョイ 2322-ghbJ) mailto:sage [2017/03/18(土) 13:17:03.94 ID:WJ1Bgcsq0.net] std::list<std::function<void<void>>> funcs; A a; B b; callbacks.push_back(std::bind(&A::func, &a)); callbacks.push_back(std::bind(&B::f, &b)); for(auto func : ...) func(); こういう使い方のbindの場合継承は関係ないと思う
688 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/18(土) 13:31:02.22 ID:waR+gchT0.net] >>672 > バインドしとかないと動かねーだろがよ その通りだ。 多分君はC++しか知らないから、それ前提で話をしているからそう思えるのだと思う。 これ自体は不思議ではない。 JavaScriptなら以下みたいなことが出来る。 var a = { a: 1, k: 2, calc: function(x){return this.k*x+this.a;} }; var b = {}; // bはaと継承関係なし var b_calc = a.calc.bind(b); // aのcalcにbをバインド ---(A) b_calc(3); // 実行可能、結果は NaN ---(B) b.a = 4; b.k = 5; b_calc(6); // 実行可能、結果は 34 ---(C)
689 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/18(土) 13:31:20.02 ID:waR+gchT0.net] C++から見ればデタラメだが、JavaScriptはこれでも動く。 C++は(A)の時点でバインド対象(今回はb)がcalcを動かしても問題ないことが必要で、 コンパイル時に確定させる為には通常は継承関係がないと無理だろ。 JavaScriptはそういうの関係無しにとりあえずbind出来る。 ただし中身が揃っていない時に実行したらNaNが返ってくる。(B) そして中身を揃えたあとには正しく実行される。(C) だからJavaScriptみたいな言語ならthisをバインドする意味があるのだが、 C++のように継承関係がないとメンバ関数を呼べないのなら、 常に f->*calc の形で記述することが可能であり、bind時にthisを確定させる意味がない。 (やってもいいのだが、冗長=糖衣構文) JavaScriptでは(B)の時点で b はメンバを何も持っておらず、 (C)の時点でもメンバは a, k のみで、calcはメンバではないことに注意。 (当たり前だが a を継承していれば calc もメンバになる)
690 名前:デフォルトの名無しさん (ワッチョイ 537b-gO1F) [2017/03/18(土) 13:32:09.09 ID:ux+WuUO90.net] >>670 thisに限らずbindするメリットは呼び出し側が(bindで引数を合わせることにより)実際に呼び出される物がどんな関数のか気にせずに呼び出せることっていうのは解るよね? それで、thisのbindだけ疑問視する理由は?
691 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/18(土) 13:38:41.49 ID:waR+gchT0.net] >>673 > callbacks.push_back(std::bind(&A::func, &a)); これを、this側が関係ない奴、例えばBにして、 callbacks.push_back(std::bind(&A::func, &b)); // (D) だとコンパイル通らないだろ?(俺の予想だが) だったら、常にその場合は、 callbacks.push_back(a->*func)); と書けるよね?という話。 (もちろん糖衣構文ならそれでいいんだが) JavaScriptは(D)でも
692 名前:Rンパイル通るんだよ。(まあコンパイル自体がないんだが) そして実行も出来る。(ただし実行時にメンバが揃ってない時にはお察しで) [] [ここ壊れてます]
693 名前:デフォルトの名無しさん (ワッチョイ 537b-gO1F) [2017/03/18(土) 13:48:07.93 ID:ux+WuUO90.net] >>677 つまり >callbacks.push_back(a->*func)) と書けるようにしたらbindでthis使う必要ないって話? そうなのであれば callbacks.push_back([&]{a.func();}); と書けるから別に要らない
694 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/18(土) 13:53:42.63 ID:waR+gchT0.net] >>676 見やすさの為に、というのはいい。 > thisのbindだけ疑問視する理由は? プログラミングコストが減ってないから。 auto a_func = std::bind(&A::func, &a) なら、 a を管理するか a_func を管理するかで、何も隠蔽出来てないし減ってない。 ただ>>673 みたいな使い方だと、 型を揃えた結果、同じ記述で実行出来るから、この点は確かにメリットはある。 これを言いたかったのか?
695 名前:デフォルトの名無しさん (ワッチョイ 537b-gO1F) [2017/03/18(土) 13:59:12.74 ID:ux+WuUO90.net] >>679 bindを使う利点なんてそれしか無いと思うんだけど…
696 名前:デフォルトの名無しさん (ワンミングク MM5f-W3uL) mailto:sage [2017/03/18(土) 14:02:09.89 ID:TmvAgLdoM.net] >>674 C++では、お前があとからやってるインスタンス構築を先にやっとけよってだけの話
697 名前:デフォルトの名無しさん (ワンミングク MM5f-W3uL) mailto:sage [2017/03/18(土) 14:03:34.16 ID:TmvAgLdoM.net] >>679 type_erasureの話がしたかっただけ? C++のこと知らねーなら議論の余地がなさすぎ JavaScriptスレいけよ
698 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/18(土) 14:04:04.03 ID:waR+gchT0.net] >>678 ちょっと輻輳してて申し訳ないが、 > >callbacks.push_back(a->*func)) > と書けるようにしたらbindでthis使う必要ないって話? そう。というか継承関係ある状態でしかメンバ関数使えないのなら、 thisをbindする意味がないと思った。 (引数はbindしていいが、これもbindなしで継承でも書ける>>669 ) ただし、>>673 みたいに、「戻り値と引数が同じなら同じ関数型」として扱えるのなら、 継承関係なしのA::funcとB::funcを同じに扱えるからやっぱbindしてないと駄目だな。 ところで、ここでクロージャを使うことに意味はあるのか? > callbacks.push_back([&]{a.func();}); もちろん使ってもいいが、a.funcがクロージャ内の変数を捕捉しているはずもないし、直接 > callbacks.push_back(a->*func)); で全く問題なくね?
699 名前:デフォルトの名無しさん (ワッチョイ 2322-ghbJ) mailto:sage [2017/03/18(土) 14:06:49.68 ID:WJ1Bgcsq0.net] 正直 std::function<...> f[] = a.func; で書けるなら書きたい 書けないからbind使ってる
700 名前:デフォルトの名無しさん (ワッチョイ 2322-ghbJ) mailto:sage [2017/03/18(土) 14:07:07.58 ID:WJ1Bgcsq0.net] []いらない
701 名前:デフォルトの名無しさん (ワッチョイ a30e-BL3h) mailto:sage [2017/03/18(土) 14:10:17.22 ID:JpaAP8SC0.net] 今時bind使わずlambdaで済ますよね
702 名前:デフォルトの名無しさん (ワンミングク MM5f-W3uL) mailto:sage [2017/03/18(土) 14:10:36.75 ID:TmvAgLdoM.net] >>683 aをキャプチャする必要が有るだろうが まじでclassとインスタンスの違いをもう少し学んでくれ
703 名前:デフォルトの名無しさん (オッペケ Sr97-w0Gz) mailto:sage [2017/03/18(土) 14:11:31.23 ID:2lr6MuOgr.net] なんだ、継承の意味を知らないんじゃなくて std::bindを見てECMAScriptのbindingと同じものだと勘違いしていただけか。 これでは話が噛み合うはずがない
704 名前:デフォルトの名無しさん (ワッチョイ 537b-gO1F) [2017/03/18(土) 14:14:40.36 ID:ux+WuUO90.net] >>687 新しい文法追加してa-> *func って書いたらaを参照キャプチャしてfuncを呼び出す関数オブジェクトを返すようにしてほしいらしいよ。
705 名前:デフォルトの名無しさん (ワンミングク MM5f-W3uL) mailto:sage [2017/03/18(土) 14:17:30.12 ID:TmvAgLdoM.net] >>689 関数を一級オブジェクトにしろという主張?? 別の言語でやれとしかいいようがないな…
706 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/18(土) 14:20:22.86 ID:waR+gchT0.net] >>681-682 > インスタンス構築 それはインスタンス構築ではなく、使う物だけとりあえず入れてるんだよ。 a を構築しているのではなく、 a.func の数式 k*x+a を使いたいから、 とりあえず a と k に値を入れて使っているだけ。 数式を間借りしているだけなんだ。 もっと a が複雑で、100個くらいメンバを持っているベクトル値だったとして、 calcも calc_0 〜 'calc_100 とかあったとして、そのうち1個だけ丁度いい数式があったら、それを借りる感じ。 このデタラメっぷりはC++にいると理解不能だが、JavaScriptに慣れるとC++が色々面倒で仕方ない。 そもそもテンプレートも型消去も最初からvarだとやらなくていいんだよ。 (その分デバッグが辛いが)
707 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/18(土) 14:24:47.73 ID:waR+gchT0.net] >>689 いやその文法はすでにC++0xにあるとの理解だが、これが間違いか? 既に>>663 にURL上げたが。 > メンバーを指すポインター演算子 .* および ->* は、特定のクラス・オブジェクトのメンバーを指すポインターをバインドする際に用いられます。
708 名前:デフォルトの名無しさん (ワンミングク MM5f-W3uL) mailto:sage [2017/03/18(土) 14:26:29.15 ID:TmvAgLdoM.net] >>691 > それはインスタンス構築ではなく、使う物だけとりあえず入れてるんだよ。 >とりあえず a と k に値を入れて使っているだけ。 >数式を間借りしているだけなんだ。 それをインスタンス構築っていうんだよ、覚えとけばか >もっと a が複雑で、100個くらいメンバを持っているベクトル値だったとして、 >calcも calc_0 〜 'calc_100 とかあったとして、そのうち1個だけ丁度いい数式があったら、それを借りる感じ。 そういう場合はお前の言うとりあえずだけを入れられるコンストラクタ作るんだよ まぁ普通の感性ならその部分はサブクラスとして切り出すけどね >このデタラメっぷりはC++にいると理解不能だが、JavaScriptに慣れるとC++が色々面倒で仕方ない。 >そもそもテンプレートも型消去も最初からvarだとやらなくていいんだよ。 面倒ならjsで書いとけばいいんじゃないですかね
709 名前:デフォルトの名無しさん (ワンミングク MM5f-W3uL) mailto:sage [2017/03/18(土) 14:27:43.20 ID:TmvAgLdoM.net] >>692 間違い
710 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/18(土) 14:43:08.69 ID:waR+gchT0.net] >>684 ちなみに何でそれ書けないんだ? std::function<...> f_bound = a.func; // (E) バインド済み std::function<...> f_not_bound = A::func; // (F) 未バインド、第1引数はthis で文法的に問題ないし、普通にこうだと思っていた。 ただし俺はC++でメンバポインタを使ったことはないから、 現在駄目なのなら何か理由があるのだろうけど、 逆にそうだと信じ切っており、 JavaScriptはこれができない=常にbindが必要なのでウザくて仕方なかった。例えば、 var func = someInstance.someMethod.bind(someInstance); と常に2回 someInstance と書く必要があり、これがウザイ。 ただC++も同じく糞なのか?
711 名前:デフォルトの名無しさん (ワンミングク MM5f-W3uL) mailto:sage [2017/03/18(土) 14:55:00.20 ID:TmvAgLdoM.net] >>695 classとインスタンスの違いがわかってないうちはマジで理解できないだろうからもう諦めろ JavaScriptのbind一通り調べたよ jsは関数型に依っててインスタンスって考え方がないんだな
712 名前:デフォルトの名無しさん (ワッチョイ a30e-BL3h) mailto:sage [2017/03/18(土) 15:03:41.03 ID:JpaAP8SC0.net] 最悪一部menberの参照だけ取られる表記と同じで、それがメンバ関数だとインスタンス全部が人質になるとか怖すぎ。
713 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/18(土) 15:44:12.23 ID:waR+gchT0.net] >>696 インスタンスとクラスの違いが分かってないのはお前だろ。 >>695 をJavaScriptで再記すると、 var a = new A(); var func_0 = a.func; // bindされない ← 直感的にはbind済みであって欲しい var func_1 = A.prototype.func; // bindされない ← これはOK で、JavaScriptは両方ともbindされないんだよ。 だから他言語から来た連中はbindを忘れてここでバグると言われている。 その「他言語」ってのは俺はてっきりC++だと思っていたから、695の理解になる。 ところがC++も同様に糞ならまあそれでよし。 改めて見ると、代入出来ないってことか?つまり、以下が出来ない。 std::function<...> f = a->*func; // bind済み std::function<...> f = a.*func; // bind済み なるほどC++も糞だな。ただ、実装自体は>>669 で出来るのだから、 何故これを出来ないようにしたのかは謎だが。
714 名前:デフォルトの名無しさん (ワッチョイ 838b-UnlH) mailto:sage [2017/03/18(土) 15:49:31.59 ID:YXP7lJmh0.net] JavaScript… あれはインスタンスしかないみたいな似非^2オブジェクト指向じゃん? あまりの酷さに批判が高まったのか、エッセンス6とかでprototypeキーワードが導入されたが それぐらいのもん ちなC++の話として、クロージャはあんま継承関係無い f.calc(x, 2)をfunc(x)の如く扱いたければfの所有でおk
715 名前:デフォルトの名無しさん (ワッチョイ 838b-UnlH) mailto:sage [2017/03/18(土) 15:55:28.34 ID:YXP7lJmh0.net] 個人的にはstd::bind(&F::calc, f, _1, 2)ですらF::calcの直接callに最適化されずに、 間接メモリアドレッシング後のcall止まりになるんではないかと危惧してゐる テンプレートを使える環境にありながら 関数へのポインタなど使うのは教育上によろしくない
716 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/18(土) 16:02:10.31 ID:waR+gchT0.net] なおC#ではあっさり書けることが判明した。 > class DelegateTest > { > static void Main() > { > Person p1 = new Person("鬼丸美輝"); > Person p2 = new Person("神無月めぐみ"); > > ShowMessage show = new ShowMessage(p1.ShowName); > show += new ShowMessage(p2.ShowName); > show += new ShowMessage(A); > show += new ShowMessage(B); > > show(); > } > > // 結果 > // 名前: 鬼丸美輝 > // 名前: 神無月めぐみ > // A が呼ばれました。 > // B が呼ばれました。 > ufcpp.net/study/csharp/sp_delegate.html
717 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/18(土) 16:02:29.43 ID:waR+gchT0.net] そしてC++でも出来そうなんだが、、、 > Human alice; > printf("Alice"); > (alice.*pf5)(); > > // おまけ > int Human::*x = &Human::age; > alice.age++; > printf("age = %d (%d)", alice.*x, &(alice.*x)); > qiita.com/Ted-HM/items/282785fcdcd06fb59642
718 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/18(土) 16:27:36.88 ID:waR+gchT0.net] >>699 > 似非^2オブジェクト指向じゃん? あれはクラスベースではなくプロトタイプベースだから。 それを無理矢理クラスベースとして使おうとするからおかしな事になる。 最初からプロトタイプベースとして使えば何も問題なく、 実際に表現出来る範囲もクラスベースよりも広いので、なかなか面白い。 > ちなC++の話として、クロージャはあんま継承関係無い JavaScriptでも継承とクロージャは全く関係ない。 > f.calc(x, 2)をfunc(x)の如く扱いたければfの所有でおk これはそうだと思う。 fがf_boundに変わっても手間は同じで、意味ねーというのが最初の主張。 >>700 > 個人的にはstd::bind(&F::calc, f, _1, 2)ですらF::calcの直接callに最適化されずに、 というかこれを期待するのがC++なのか? それはさすがに厳しいとは思うが、確かに無理ではないが。 > テンプレートを使える環境にありながら > 関数へのポインタなど使うのは教育上によろしくない これはどういう意味?さすがに今回の上記 > std::bind(&F::calc, f, _1, 2) をテンプレートで常に直接callするようには出来ないだろ。 というかテンプレートと関数ポインタの使う範囲は被らないと思うが。(代替出来ない)
719 名前:デフォルトの名無しさん (ワッチョイ 838b-UnlH) mailto:sage [2017/03/18(土) 16:35:15.55 ID:YXP7lJmh0.net] >> 個人的にはstd::bind(&F::calc, f, _1, 2)ですらF::calcの直接callに最適化されずに、 >というかこれを期待するのがC++なのか? >それはさすがに厳しいとは思うが、確かに無理ではないが。 できる F:calc()は仮想関数では無いし、 表記の例では&F:calc自体が(F::calc()と同じシグネチャを持つ別名の関数とかに)差し替えられはしないので 本質的には直接callとなるべきもの
720 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/18(土) 16:38:53.29 ID:waR+gchT0.net] ああ分かった。 >>702 はこちらの解釈間違い、これは出来ているわけではないね。 .* と ->* はあくまでその場で呼んでいるだけであって、 bind済みの関数を返してくれるわけではないのね。
721 名前:デフォルトの名無しさん (ワンミングク MM5f-W3uL) mailto:sage [2017/03/18(土) 16:42:00.60 ID:TmvAgLdoM.net] もういいよ jsスレでやれよ
722 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/18(土) 17:00:49.05 ID:waR+gchT0.net] >>704 > 本質的には直接callとなるべきもの それを言いだしたら全部だろ。そうなってないから色々問題なわけで。 ただこれに関してはスタックイメージを揃えればいいだけだから、やる気だけだね。 最初からスタックイメージを揃える呼び出しを用意してもいいし、 一旦>>669 の形式で2段階呼び出しにして、インラインにしてもいい。 (ただしインライン展開対象は外側関数なので従来最適化ルーチンは使えない) いずれにしても難しくはないよ。やる気だけの問題だね。
723 名前:デフォルトの名無しさん (ワッチョイ c353-PkJR) mailto:sage [2017/03/18(土) 17:01:39.49 ID:U4KC6daQ0.net] 知識がないのに何故語ろうとする
724 名前:デフォルトの名無しさん (ワッチョイ 838b-UnlH) mailto:sage [2017/03/18(土) 17:59:03.48 ID:YXP7lJmh0.net] >それを言いだしたら全部だろ。そうなってないから色々問題なわけで。 std::bind(&F::calc, f, _1, 2)という記述を見たコンパイラはポインタが関係するのでF::calc()を直接呼出しして良いものか迷うかもしれないが、 std::bind(<F::calcを表す関数オブジェクト>, f, _1, 2)なら std::bind()自体の書き方や関数オブジェクトの書き方がよほどアレでない限りはF::calc()直接呼出し相当のコードになる 全部一緒というなら一緒なんだろう藻前の中では(ry
725 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/18(土) 20:18:06.83 ID:waR+gchT0.net] >>709 いや結局何が言いたいんだ? 君:700「std::bind(&F::calc, f, _1, 2)は最適化されないかも…」 俺:703「それを期待するのは厳しいだろ」 君:704「いやできるし、そうなるべきだ」 俺:707「そりゃそうだが」 人間が見れば簡単に分かることが出来ないなんて!なんてのは全部だよ。 一般的にはポインタになった時点で最適化が難しくなる。 f->calc(x,k); // 直接呼び出し std::bind(&F::calc, f, _1, 2)(x); // 直接呼び出し std::function<...> f; // (G) f = std::bind(&F::calc, f, _1, 2); // (H) f(x); // 2段呼び出し // (I) f = std::bind(&F::calc, f, 2, _1); // (J) f(k); // 2段呼び出し // (K) C++では「戻り値と引数」が合ってたら良いんだろ? だったら(G)はいけるよな? この場合、fには(H),(J)とも可能なんだよ。 バインドされているのは第1引数でも第2引数でもいい。 ところがこれを実行する際、直接呼び出しに展開する為には、 (I)と(K)で呼び出し方法を変えなければならない。 スタック上の引数の位置が異なるからね。 そして一般的には(H)(J)はどこか遠いところで代入されており、 通常はその関数外から与えられる。 だから最適化は難しいんだよ。
726 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/18(土) 20:18:41.61 ID:waR+gchT0.net] ローカル関数内でfが分かりやすく代入されている場合は完全に最適化出来る。 同様の方法で外部から与えられた場合でも常に最適化する為には、 fに代入される可能性のあるポインタを全て精査する事が必要だが、一般的にこれは無理。 (書いた本人には何が入る可能性があるか簡単に列挙出来るが、 ソースコードから抽出するのはかなり無理) したがって、次案としては、 f自体に「第○引数を第△引数に入れ替え、第●引き数は▲で固定」という情報を持たせ、 対応することになる。(なおこの操作を別関数として行うのが「2段呼び出し」になる。) もっとも、C++のメンバポインタはintサイズでなくてもいいみたいなので、 この方法でも出来なくもないが、VC++ではやってないね。 > VC++で試したところ、普通は4、多重継承していれば8、仮想継承していれば12となりましたが、 > www7b.biglobe.ne.jp/~robe/cpphtml/html03/cpp03058.html これをやっていれば通常でも4では済まない。 多重で増えているのはポインタのずれを補正する分だね。 > https://www.microsoft.com/japan/msdn/vs_previous/visualc/techmat/feature/jangrayhood/
727 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/18(土) 20:19:09.95 ID:waR+gchT0.net] 分かるか? 完全に「直接呼び出し」にするには動的データとして「メンバ関数オブジェクト」みたいな物を作り、 それの展開ルーチンをインラインで埋め込まないといけないんだよ。 (サブルーチンで呼び出すと結局2段呼び出しになるだけ無駄) だったらそのままその「展開ルーチン」→「ターゲットメンバ関数」の2段呼び出しでもいいや、ってことになるだろ。 それがVC++でこの部分の直接呼び出し最適化をしていない理由だと思うよ。 多分さほど効果がないんだよ。(やる事自体は難しくない) 表面的な原因は、「第1引数がbindされた関数ポインタ」「第2引数がbindされた関数ポインタ」が 同じ型になってしまうことだよ。だからといって、これらが別型なのは言語として糞だろ。 明示的に分かりやすくその場で代入されている場合は、 これらを別扱いすればいいだけだから比較的楽に対応出来る。 だけど一旦ポインタとして受けられた場合、どれになるかは分からなくなるので無理になる。 それで、ポインタ自体にその情報を与えて動的モドキで対応するよりも、 単純に2段呼び出ししたほうがマシ、という判断が為された、ということだよ。VCでは。 ただ、2段呼び出しは「継承したクラス」を自分で書いた場合で、 std::bindってevalするわけではなくて、静的なライブラリ(=データしか作成出来ない)だよな? だったら内部的に上記「メンバ関数オブジェクト」方式になっている可能性が高く、 2段呼び出しで汎用ルーチンで展開=一番遅いパターンだと思うけどね。 まあここら辺はそっちの方が詳しい気がするが。 で、改めて聞くが、何が言いたいんだ? 俺はCコンパイラを作っているわけではないし、俺に文句言われても知らんがな。 結論としては、 > std::bind()自体の書き方や関数オブジェクトの書き方がよほどアレでない限りはF::calc()直接呼出し相当のコードになる は間違いだね。理由は上記、完全精査はかなり難しいからだ。 (もし出来てるのならスゲーとは思うけど)
728 名前:デフォルトの名無しさん (ワッチョイ 3fe5-eT6H) mailto:sage [2017/03/18(土) 20:25:58.81 ID:vEAnzxNk0.net] std::hashのconstexpr版って標準に入る予定とかないの?
729 名前:デフォルトの名無しさん (ワッチョイ 738b-UnlH) mailto:sage [2017/03/19(日) 00:13:07.69 ID:F98WB86R0.net] >>710-712 長文乙だがstd::bind()が(テンプレート関数なので)インライン展開されるということが何を含意し、 関数オブジェクトと組み合わせたときどういう効果があるかあんまお分かりではなさげ std::bind()内の第1引数への操作がインライン展開されるならば(そのようにstd::bind()自体が書かれているならば 第1引数の操作に関して >人間が見れば簡単に分かること は、 >コンパイラが見れば簡単に分かること と一致する(>>709 の「std::bind()自体の書き方(中略)がよほどアレでない限りは」がソレを指してゐる で、第1引数が関数オブジェクトでありかつF::calc()が仮想関数で無い限りは、F::calc()というシンボルのアドレスが コンパイル時に決まるから、直接呼出しのコードにできる 第1引数がポインタの場合はそうとは限らず、std::bind()の呼び出しの外もみてポインタが指すシンボルが一意であることまで 確認しないとコンパイラはF::calc(this, x, 2)というcallで済むところを(*p)(this, x, 2)的なコードにしかできない
730 名前:デフォルトの名無しさん (スプッッ Sddf-8YZg) mailto:sage [2017/03/19(日) 00:17:51.96 ID:UQylyHTkd.net] お前らのおすすめのデザインパターんおしてて
731 名前:デフォルトの名無しさん (ワッチョイ 738b-UnlH) mailto:sage [2017/03/19(日) 00:18:40.25 ID:F98WB86R0.net] 訂正 誤: F::calc()というシンボルのアドレスがコンパイル時に決まるから、直接呼出しのコードにできる 正: F::calc()というシンボルの呼び出しであることがコンパイル時に確定するから、直接呼出しのコードにできる
732 名前:デフォルトの名無しさん (オッペケ Sr97-w0Gz) mailto:sage [2017/03/19(日) 00:38:21.66 ID:rBaNXWYpr.net] >>715 とりあえずRAIIは使っとけ ナマポをnewする奴は殺害されても犯人に情状酌量の余地が残る
733 名前:デフォルトの名無しさん (ワンミングク MM5f-W3uL) mailto:sage [2017/03/19(日) 00:38:32.17 ID:Sogj9z7eM.net] >>715 expression template
734 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/19(日) 01:10:03.99 ID:7dJ8iAqk0.net] >>714 日本語で説明しようとしたのはまずかった。C++で書き直すと、以下。 ただしC++文法には詳しくないので、syntaxErrorは適宜脳内修正よろしく。 意味だけ見てくれ。ソースは>>666 から流用してる。 class F { int _a; public: F(const int a):_a(a) {} int calc(const int x, const int k) const { return k * x + _a; } }; int main() { const F f0(1); const F f1(2); std::function<...> f0_1 = std::bind(&F::calc, f0, _1, 3); // 第2引数を固定 std::function<...> f0_2 = std::bind(&F::calc, f1, 4, _1); // 第1引数を固定 std::function<...> f1_1 = std::bind(&F::calc, f1, _1, 5); // 第2引数を固定 call_sub(F0, f0_1, f0_2); call_sub(F1, f1_1, f0_1); } void call_sub(F& f, std::function<...> f1, std::function<...> f2){ f->func(1,2); // (L) 直接呼び出し f1(3); // (M) コンパイラによっては直接呼び出し、一般的には2段階呼び出し f2(4); // (N) 2段階呼び出し }
735 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/19(日) 01:10:33.50 ID:7dJ8iAqk0.net] (L)は必ず直接呼び出しになる。アセンブラなら push, push, push, call (M)はソース上を精査すれば同型呼び出ししかないことが分かるので 技術的には(L)と同程度まで最適化可能ではあるが、一般的には無理だと思う。 2段階呼び出し時は push, push, push, call, mov, jmp (N)は異なる形の呼び出しが与えられているので、 技術的に(L)と同じコスト(アセンブラ4命令程度)の直接呼び出しは不可能。 無理にcmpとかやるより普通に2段階呼び出しの方がいいと思う。 だからVCもそうしていると見ている。 それで、std::bindについては詳しい奴が以下見れば実装の見当が付くはずだが、 俺はC++用語に詳しくないので分からん。 ja.cppreference.com/w/cpp/utility/functional/bind 俺が実装するなら、ありがちなのをテンプレートで実装するが、 その場合はポインタサイズはsizeof(int)*2になる。 (メンバ関数へのポインタと、bind済みの値をstructで持つ=内部的な匿名クラスにするから) VCがなぜ4に出来るのかは分からん、というか計測間違いじゃないかと思う。 (バインド済みの値の分を入れてない)
736 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/19(日) 01:11:05.58 ID:7dJ8iAqk0.net] 俺が言いたかったのは、上記(L),(M),(N)ということ。 君の主張は、すべてbind時で確定して、上記(M)(N)も(L)と同じコストで呼べるという主張だと読める。 それは無理。 確かにアドレス自体は確定はするが、 引数をbindしているのだからスタックをその形にしてやらないといけない。 上記(N)の呼び出し、アセンブラ4命令ではどうやっても書けないだろ。 cmp使って書くくらいなら2段階呼び出しで6命令(2分岐)の方がマシ。 cmp使って無理に直接呼びにしたら、 そこに来る可能性のある呼び出し型を全部そこに書かなければならなくなる。 そしてx86はプレディケートを持ってないので、cmpで分岐しないといけない。(ARMは持っている) それって完全に本末転倒だろ。 それで、std::bindと関数オブジェクトをどう組み合わせたら、 (L),(M),(N)について上記通りアセンブラ4命令程度で呼び出せるのかよろしく。
737 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/19(日) 01:17:42.85 ID:7dJ8iAqk0.net] すまん、重要なところを間違えていたので訂正。 >>719 > std::function<...> f0_1 = std::bind(&F::calc, f0, _1, 3); // 第2引数を固定 > std::function<...> f0_2 = std::bind(&F::calc, f1, 4, _1); // 第1引数を固定 > std::function<...> f1_1 = std::bind(&F::calc, f1, _1, 5); // 第2引数を固定 の2つ目、インスタンスは f0 ね。 std::function<...> f0_2 = std::bind(&F::calc, f0, 4, _1); // 第1引数を固定, f0 ただ結局、変な引っかけみたいになっているだけで意味は同じかな? まあ訂正しとくけど。
738 名前:デフォルトの名無しさん (ワッチョイ bfcc-UNkP) mailto:sage [2017/03/19(日) 01:31:51.96 ID:i6MRGbY60.net] まだJAVAガイジ張り付いているのか…
739 名前:デフォルトの名無しさん (ワッチョイ 8330-PVeP) mailto:sage [2017/03/19(日) 01:41:06.04 ID:I9SbzQA70.net] あんだけ無能な醜態をさらしておいて ボクはレベルが高いけどちょっと知らなかっただけちょっと間違えただけで済んで まだ自分のいうことに説得力がある聞いてくれる人がいると思ってるところがもうね…
740 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/19(日) 01:44:23.31 ID:7dJ8iAqk0.net] bindの説明読む限り、やっぱこれかなり汎用に作っていて遅いと思うぞ。 ただ一般的にはそこが見えるほど使うことはないと思うが。 アセンブラ的には、 f->func(): 4命令程度(分岐1回) std::bind経由での呼び出し: 10-50命令程度か?(分岐2回以上) 内部オブジェクト作成方式: 6命令程度(分岐2回) じゃないかな。
741 名前:デフォルトの名無しさん (ワッチョイ 537b-gO1F) [2017/03/19(日) 01:49:16.54 ID:jcDR9uoj0.net] まぁ、別にスレ違いというわけでもないからいてもいいんじゃない?付き合いたい人が付き合えば。 俺はレスしないけど。
742 名前:デフォルトの名無しさん (ワッチョイ 537b-v8EU) mailto:sage [2017/03/19(日) 01:59:32.09 ID:jcDR9uoj0.net] と、言ったものの、我慢しきれないので撤回します。 >>725 https://godbolt.org/g/SFtHQt こうなる意味を考えて。 もう一つヒントあげるとstd::function<int()>で受けるとどうなるか見てみたらいいよ。
743 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/19(日) 02:14:29.60 ID:7dJ8iAqk0.net] 誰かと思えば>>678 か。 じゃあついでに言っておくと、以下だね。 callbacks.push_back([&]{a.func();}); // (O) クロージャ作成が無駄 callbacks.push_back(a->func)); // (P) この書き方は現在出来ないが、こっちの方がいい JavaScriptでは(O)は無駄だとされる。クロージャが余分にメモリを食うから。 クロージャ無しで書けるならその方がいい。コード領域も無駄だし。 これはC++も同じだし、C++の方が厳しいはずだが。 とはいえstd::bindの仕様が重すぎるのでこちらもイマイチだ。 C++ならどっちが重いかは微妙だね。 なおJavaScriptのbindは「前から順に固定される」だけの仕様なので、 固定した引数分のデータ領域しか各bindインスタンスには必要ない。 というかC++のbindが妙にリッチな仕様なのが謎だが。C++っぽくない。
744 名前:デフォルトの名無しさん (ワッチョイ 537b-gO1F) [2017/03/19(日) 02:17:00.87 ID:jcDR9uoj0.net] >>728 C++なら無駄ではない 終了
745 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/19(日) 02:19:33.17 ID:7dJ8iAqk0.net] >>727 俺には計算済みとしか見えないが、何か操作必要? -O3外せとかか? > fn(int): > lea eax, [rdi+rdi] > ret > bind(): > mov eax, 4 > ret > direct(): > mov eax, 4 > ret
746 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/19(日) 02:28:44.92 ID:7dJ8iAqk0.net] >>727 というかな、根本的に間違ってると思うぞ。 一般的に関数ポインタを使う場合、それは外部から与えられるんだよ。 自分の内部で作って使うって事はない。 (ここでは単純なソースで議論するからそうなるだけで、一般的にはそうではない。 つか、それじゃ関数ポインタの意味がないし) 典型的にはcallbackだよ。外部から与えないと全く意味無いだろ。 で、その場合は当然この手の事前計算とかでの最適化は出来ないんだよ。
747 名前:デフォルトの名無しさん (ワッチョイ 537b-v8EU) mailto:sage [2017/03/19(日) 02:33:33.53 ID:jcDR9uoj0.net] >>731 一時一句同じじゃないと理解できない人だったか。 https://godbolt.org/g/o73pz4 これで理解できますか?
748 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/19(日) 02:51:38.54 ID:7dJ8iAqk0.net] >>732 あーお前がアホだということはよく分かったわ。 まともに議論する気なら、お互いが見ているものが同一であることを確認しないといけない。 >>727 を見たらアホかと思うのは道理だろ。 そして>>732 もアホかと思うよ。関数内部で何を作ってもそれは最適化されるよ。 それは一時変数を除去すればいいだけなのだから。 そうではなくて、例えば以下にしないといけない。 int main(){ auto f = std::bind(&something::func,ptr); bind(f); } int bind(std::function<...> f){ return f(); // bind済みのfを呼ぶコストをここで計測する } 再度言うが、関数ポインタは外部から与えないと意味無いんだよ。
749 名前: てかお前ら実は全く関数ポインタ使ってないだろ。 だから使い方自体を知らないんだよ。 これで、bind/関数オブジェクト/クロージャで呼び出しコストを比べてみなよ。 当たり前だが上記だとbind呼んで終わりになるけど、 もちろんその先のターゲット(something::func)が呼ばれるまで見るんだよ。 つまりstd::bind内部のコードもね。それが呼び出しコストなんだから。 それで、あらかじめ計算済みとかいうアホなオチはマジで止めてくれ。 一般的にポインタを与えた場合、それが無理なことくらい分かるだろ。 [] [ここ壊れてます]
750 名前:デフォルトの名無しさん (ワッチョイ 537b-v8EU) [2017/03/19(日) 03:14:07.27 ID:jcDR9uoj0.net] >>733 注文の多いやつだなぁ。 https://godbolt.org/g/R1ljMl 関数ポインタを外から渡すようにかえてやったぞ。 自分で言ってることをC++で書く能力ぐらいあるよね? 次から自分で書けよ。 std::bindに余分なコストなんてない。std::functionの方にある。 ヒントあげたのに全く考えようとしなかったのかな?
751 名前:デフォルトの名無しさん (ワッチョイ 537b-v8EU) mailto:sage [2017/03/19(日) 03:24:22.16 ID:jcDR9uoj0.net] >>733 なぜか一時変数だから最適化できると信じてるみたいだけど、そう思うなら int std_function(something* ptr,fn_ptr_type fptr){ std::function<int()> f = std::bind(fptr,ptr); return f(); } と書いてみればいい。 >そして>>732 もアホかと思うよ。関数内部で何を作ってもそれは最適化されるよ。 >それは一時変数を除去すればいいだけなのだから。 がバカな発言だったと理解できると思うから。
752 名前:デフォルトの名無しさん (ワッチョイ 0f59-Rjy3) mailto:sage [2017/03/19(日) 03:38:13.98 ID:xwQyhAst0.net] ああ、Javaだと〜とか言ってた人か
753 名前:デフォルトの名無しさん (ワッチョイ cf6b-8YZg) mailto:sage [2017/03/19(日) 08:10:18.88 ID:oCYtEhVi0.net] >>717 調べても出てこない.... コンストラクタとデストラクタでNewとかするやつだっけ?? >>718 数式を渡して分かりやすくするってのはなんとなくわかったんだけど 逆にごちゃごちゃしすぎてる気がするって印象を受けた
754 名前:デフォルトの名無しさん (ワッチョイ ef6c-i8cA) mailto:sage [2017/03/19(日) 08:15:20.51 ID:gWCLtiPs0.net] >>737 デストラクタでdeleteやで expression templateは効果がどうなの?って思い始めてる 普通にコンパイラの最適化に任せた場合とそんなに変わるんかな
755 名前:デフォルトの名無しさん (ワッチョイ cf6b-8YZg) mailto:sage [2017/03/19(日) 08:18:02.91 ID:oCYtEhVi0.net] >>738 すまん とかにまとめた scope抜けたときに必ず処理させるってやつよね 確かに必要なやつだな コード見やすくってやって逆に色々と設定があると逆に見にくくなるんじゃないか?って疑問が残った 今はあとシングルトンパターンぐらいしかわかんないや
756 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/19(日) 08:46:03.88 ID:7dJ8iAqk0.net] 訂正ね。 >>733 × std::bind内部のコードもね。 ○ std::functionのoperater()の内部のコードもね。 処理系の実行コードも、という意味で書いたが、 std::bindはstd::functionを返すので今回についてはoperator()のコードになるのだよな? まあ間違っていたら適宜訂正してくれ。分かる範囲だと思う。 >>734 > std::bindに余分なコストなんてない。std::functionの方にある。 これが上記について言っているのならその通り。 ただそれは揚げ足取りだと分かるだろ。それがやりたかったのならどうぞ、おめでとう。 それが分からないのなら君にはこの話は無理だね。 というわけでいずれにしてもこの話は終わりでいい。
757 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/19(日) 08:47:04.27 ID:7dJ8iAqk0.net] 一応中身は確認した。 >>734 については呼び出し側は全部同じコードが出るという事ね。ここまではいい。 問題はその先だ。それは君も分かってるんだろ?だったら何故それをしない? >>735 > なぜか一時変数だから最適化できると信じてるみたいだけど、そう思うなら これについては相変わらずそちらが間違いだね。 事前計算済みのコードをドヤ顔で出してきたのはそちらだろ。 それはコンパイル時に「事前計算が出来る」ということがコンパイラにも分かったから。 とはいえ、君みたいな奴も沢山いるのも事実だよ。 > と書いてみればいい。 書いてみたらstd::functionのコードが出た。 中身は今の俺にぱっと分かるようなものではないね。 が、まあ、100命令弱増えているからその分遅いと言える。 だから結論は、直接=ファンクタ<<<<bindになるのかな? ファンクタは正直ピンとこない。 あとは>>729 で無駄がないとドヤ顔のラムダがどこまで速いかだね。 まあ頑張って。 いずれにしても、この話は終わりでいい。 俺が確認したい範囲はもう分かった。
758 名前:デフォルトの名無しさん (ワッチョイ 537b-gO1F) [2017/03/19(日) 08:51:40.65 ID:jcDR9uoj0.net] >std::bindはstd::functionを返すので今回についてはoperator()のコードになるのだよな? ここまで書いても理解出来ないのかよ…
759 名前:デフォルトの名無しさん (ワッチョイ 537b-gO1F) [2017/03/19(日) 09:00:02.50 ID:jcDR9uoj0.net] >>741 俺はただ知識がないやつをバカとは思わないが、お前みたいな自分が理解出来ないのを相手のせいにしてアホなんて言う奴は本当にバカだと思うよ。 書いておかないと理解しなさそう(=出来なさそう)だから一応書いておいてあげるよ。 std::bindの返りの型はstd::functionでは”ない”
760 名前:デフォルトの名無しさん (オッペケ Sr97-w0Gz) mailto:sage [2017/03/19(日) 09:08:50.00 ID:EshC/yEQr.net] >ID:7dJ8iAqk0 コストは 直接=ラムダ=bind <<< std::function bindとstd::functionは関係無い functionにbindを重ねればfunctionのコストがそのまま残る
761 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/19(日) 09:17:50.63 ID:7dJ8iAqk0.net] >>743 だから俺はそこら辺までは詳しくないのさ。 繰り返しているとおり、std::bindの説明を読んでも全てを今すぐ理解する知識はないんだよ。 俺はC+JavaScriptだからね。C++はbetterCとして使ってきてるが、 VC++(=CLI)だからSTLを使ったことはなく、.NETだし。 C++特有のテンプレートとか型消去については 「動的型なら何も考える必要ないのに」で飛ばしてきたし、 RAII+スマポについても「そこまで言うならGC言語使えよ」としか思ってない。 だから今、型消去とかも読んでるけど、これを理解するには時間がかかるし、 上記の通りSTLについてもほぼ知らないから、これまたインストールに時間がかかるんだよ。 > std::bindの返りの型はstd::functionでは”ない” まあそれはさておき、std::bindは何が返るんだこれは? 型消去で無理矢理格納出来るだけなのか? ただ、実行時はstd::functionのoperator()が呼ばれると思うが、これも違うのか?
762 名前:デフォルトの名無しさん (ワッチョイ 537b-gO1F) [2017/03/19(日) 09:26:27.21 ID:jcDR9uoj0.net] >>745 知らないなら想像で実行時コストとか決めつけるなよ auto f=std::bind(func); f(); と std::function<int()> f=std::bind(func); f(); で出力されるコードが違うんだから違うと
763 名前:解るもんだとおもってstd::function版を書かせたんだけど、何が解らなかったのかな? [] [ここ壊れてます]
764 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/19(日) 09:41:13.37 ID:7dJ8iAqk0.net] >>744 あー何となく分かってきた。以下ページ、 ja.cppreference.com/w/cpp/utility/functional/bind の「メンバ関数 operator()」ってとこが呼ばれるのか。つか英語版見るべきだったかも。 じゃあ当初の「std::bind内部のコードもね」でも十分通じる気もするが、まあこれはいい。 いずれにしても俺はこの通り、cppreferenceの見方もよく分かってない。 だから君らに追いつくのは時間がかかる。 > コストは 直接=ラムダ=bind <<< std::function ラムダは最高に最適化された状態でbindと同じ。 bindもoperator()の内部でプレースホルダ引数の配置をするのなら、 同様に最高に最適化された状態で直接と同じ。 結果、直接=<bind=<ラムダ じゃないか? まあこれについてはそちらの方が詳しいだろうし、こちらも引き続き詳細確認中だが。
765 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/19(日) 09:49:17.20 ID:7dJ8iAqk0.net] ちなみに誰かと確認してみたが、 > std::bindを見てECMAScriptのbindingと同じものだと勘違いしていただけか。(>>688 ) なるほど、その通りだ。俺が思っていたbindとはだいぶ違う。
766 名前:デフォルトの名無しさん (ワッチョイ 5319-v8EU) mailto:sage [2017/03/19(日) 09:52:16.04 ID:/fHKNSq50.net] 直接<間接=関数ポインター<λ<バインド なぜならバインドは内部で関数ポインターを使うしかないから ラムダは言語で実装されてるから。
767 名前:デフォルトの名無しさん (ササクッテロル Sp97-q0jq) mailto:sage [2017/03/19(日) 17:47:12.05 ID:SFAOW7ATp.net] 関数呼び出しのコストでここまで議論できるって凄いな 普段C++で何作ってんだろ
768 名前:デフォルトの名無しさん (ワッチョイ 537b-gO1F) [2017/03/19(日) 18:17:17.48 ID:jcDR9uoj0.net] >>750 議論ではなく出来の悪い生徒の補習してただけだから。
769 名前:デフォルトの名無しさん (ワッチョイ f37b-12+v) mailto:sage [2017/03/19(日) 18:21:02.30 ID:V1EWIlT/0.net] ギリギリ迫るのも楽しいものです
770 名前:デフォルトの名無しさん (ワッチョイ 2302-nFTW) mailto:sage [2017/03/19(日) 18:49:00.48 ID:6JgBGVv40.net] >>750 え、Hello worldだよ?
771 名前:デフォルトの名無しさん (ワッチョイ 7302-12+v) mailto:sage [2017/03/19(日) 20:26:30.60 ID:fEuC6OUR0.net] ある時系列データにフィルタを通した任意の範囲のデータを扱うクラスを作るんだが 今だとイテレータよりRangeの方が良いのか?
772 名前:デフォルトの名無しさん (ワッチョイ f37b-12+v) mailto:sage [2017/03/19(日) 22:20:21.59 ID:V1EWIlT/0.net] もう少し具体的に と思います
773 名前:デフォルトの名無しさん (ワッチョイ 8330-PVeP) mailto:sage [2017/03/20(月) 00:26:19.05 ID:V0m6X4Gc0.net] 基本的にレンジはイテレータのペアのラッパでしかなく イテレータが無くなるわけでもないからとりあえずはイテレータを前提に作っておけばよかろ
774 名前:デフォルトの名無しさん (ワッチョイ f33c-u6wT) mailto:sage [2017/03/20(月) 12:05:47.42 ID:OlwkB3mR0.net] >>737 expression templateは遅延評価による高速化のために使うんやで 速度が必要無いなら要らんのやで >>738 実測してみた? 二項演算子(または結果を戻り値で返す関数)を多用する場合、 x, y, zを持つベクトルなんかだと明らかに効果ある 組み込み型だと全く効果ない
775 名前:デフォルトの名無しさん (ワッチョイ ef6c-i8cA) mailto:sage [2017/03/20(月) 13:05:30.60 ID:ZNh1GxS+0.net] >>757 いつか実装して確かめてみようとは思うんだけど ・数学的に簡略化が可能な場合は当然事前にできるだけ簡略化する ・計算途中の値もよく使うので=が出てきて評価が頻繁 な場合、あんまり効果なさそうだなあというところで二の足
776 名前:デフォルトの名無しさん (ワッチョイ 5319-v8EU) mailto:sage [2017/03/20(月) 13:17:35.04 ID:hOjZeIpo0.net] expression templateってコンビネーターのことじゃね?
777 名前:デフォルトの名無しさん (ワンミングク MM5f-W3uL) mailto:sage [2017/03/20(月) 13:29:36.59 ID:o1Hy6TV3M.net] >>758 計算途中の値もよく使うって、それ途中と違うがな 函数という考え方について、もう少し勉強した方がいい
778 名前:デフォルトの名無しさん (ワッチョイ f33c-u6wT) mailto:sage [2017/03/20(月) 14:06:32.00 ID:OlwkB3mR0.net] >>758 あーまだ実装してないのね 自分の実用するコード(4次元までのベクトル、4x4
779 名前:ワでの行列)だと5〜30%くらいの向上なんで、実装する労力考えると最後のダメ押しでもよかったなとは思うけど >・計算途中の値もよく使うので=が出てきて評価が頻繁 一応、a = b + c;程度の式でも効果あるにはある 多分インライン展開されても、レジスタの使用効率がちょっと良くなるんだと思う a = b + c; みたいな式で for (int i = 0; i < 3; i++) a.f[i] = b.f[i] + c.f[i]; という計算に展開された方が、レジスタを使い切らないからじゃないかなと (ちなみにループはアンロールされる前提だけど、ヒープに確保するような長いベクトルでもETの方が効率良いはず あとこの例だと、SSEとかのSIMDのイントリンシック使うと4次元まで組み込み型になるので、全くETの意味が無くなるw) 複数の組み込み型を含む演算で、SIMDとか他の高速化を使った上でさらに速くしたいなら、ETはおすすめしたい ただし計算過程でxがy, zに干渉するような計算(内積、外積とか)にはET使えないので注意 [] [ここ壊れてます]
780 名前:デフォルトの名無しさん (ワッチョイ f33c-u6wT) mailto:sage [2017/03/20(月) 14:14:14.02 ID:OlwkB3mR0.net] 訂正 Xxがy, zに干渉するような計算 ○各要素を複数回評価するような計算 a = cross(b, c); なら大丈夫だけど a = cross(b, c) * d; とかやると乗算の回数が増えるし計算結果が狂ったりする
781 名前:デフォルトの名無しさん (ワンミングク MM5f-W3uL) mailto:sage [2017/03/20(月) 14:25:46.95 ID:o1Hy6TV3M.net] >>762 横から補足 ublasなんかは複数回評価を前提としてて、そのまま使うと遅い なので、noaliasというものが用意されてる
782 名前:デフォルトの名無しさん (ワッチョイ cf6b-8YZg) mailto:sage [2017/03/20(月) 16:40:52.42 ID:d0t0+ba+0.net] なるほど よくわからん
783 名前:デフォルトの名無しさん (ワッチョイ bf0b-8YZg) mailto:sage [2017/03/20(月) 17:28:44.64 ID:lZKrgjvb0.net] 結論 expression templateは科学系数値計算にしか効果はない そういうのは既にライブラリーが存在する よって自分でexpression templateを実装する必要に駆られる場面はほぼない
784 名前:デフォルトの名無しさん (ワッチョイ f33c-u6wT) mailto:sage [2017/03/20(月) 18:08:39.79 ID:OlwkB3mR0.net] >>765 >科学系数値計算にしか効果はない ではなくて、「速度が必要な場面でも、実装する優先度は低い」ならわかる 自分が以前調べた限りでは、ETとSIMDを同時に使ってるものは無かった はっきり言って、速度が重要な局面かつSIMDが使えるマシンなのにまずSIMDを使わないというのは有り得ない けなすわけではないが、SIMD命令がある一般的なマシンにおける数値計算には、今あるETのライブラリはまともに使えんのじゃないか ていうか科学計算ならETより、SIMDやGPGPUを使う方が先 自分の場合はゲームでの計算なんで、CPUかつヒープじゃなくスタックを使う必要があるので その時点でuBlasやBlitzは選択肢から外れるんだわ