1 名前:デフォルトの名無しさん mailto:sage [2017/10/10(火) 00:11:34.01 ID:nc/5PI4P0.net] 次スレを立てる時は本文の1行目に以下を追加して下さい !extend:on:vvvvv:1000:512 C++に関する質問やら話題やらはこちらへどうぞ。 ただし質問の前にはFAQに一通り目を通してください。 IDE (VC++など)などの使い方の質問はその開発環境のスレにお願いします。 前スレ C++相談室 part131 mevius.2ch.net/test/read.cgi/tech/1501295308/ このスレもよろしくね。 【初心者歓迎】C/C++室 Ver.101【環境依存OK】 mevius.2ch.net/test/read.cgi/tech/1500329247/ ■長いソースを貼るときはここへ。■ 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
830 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 14:46:54.14 ID:p3uF8GIb0.net] ごめ>>814 の前半は思い過ごしかorz 別にmemset()側に__restrictは要りませんな…
831 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 14:52:43.00 ID:SsMAbqSz0.net] >>813 3.10.10.4 a type that is the signed or unsigned type corresponding to the dynamic type of the object, って言ってんだから基礎型も the dynamic type に含まれてると思うぞ。 > 変更できない既存ライブラリの型に情報を無理やりねじ込んだりするのには使える。 使えない。 reinterpret_castの結果がlvalueとして正当ではない、だからundefinedで何やってもおk、 というのが最適化していい根拠なんだろ。だったらreinterpret_castしたその値を使う時点で駄目だろ。 lvalueとして正当に使えると言うのなら、undefinedじゃないんだから最適化で削除しては駄目だ。 ただまあ、ここら辺を俺と君でやりあっても意味が無い。 おそらく20年前にガチで同じことが彼らによって既に為されているはず。 俺がコンパイラを作るわけでも無し、俺は現状確認だけでいいよ。
832 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 14:57:33.47 ID:PnhOPMpK0.net] >>814 >>816 >一般論としてポインタの引数が1つしかなくとも大域変数経由で あ、そういうことか・・・ まぁmemset使ってそういう症状出るとしたら、呼び出し側のpでつければいいよね 自分は__restrictそんなに使い倒してないけど、C++の標準に入らないのかな
833 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 15:03:35.17 ID:xhmNfS4m0.net] >>817 これだけ言われてまだ dynamic type が何なのか読んでないとしか思えない発言が来るか。 https://timsong-cpp.github.io/cppwp/n4659/intro.defs#defns.dynamic.type > reinterpret_castの結果がlvalueとして正当ではない、だからundefinedで何やってもおk、 > というのが最適化していい根拠なんだろ。だったらreinterpret_castしたその値を使う時点で駄目だろ。 ポインタの reinterpret_cast で型違いの結果を得ることは未定義動作にならないし、 それに * を適用して lvalue
834 名前:を得ることも未定義動作にはならない。 得られた lvalue を通したアクセスが aliasing rule に基づいて未定義動作となる可能性がある。 [] [ここ壊れてます]
835 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 15:04:02.65 ID:p3uF8GIb0.net] >reinterpret_castの結果がlvalueとして正当ではない えっ合法なんじゃ… int x = 10; char* p = reinterpret_cast<char*>(&x); *p = 2; // *pがlvalueであるところの式 x = (int)*p; // 元の型へのキャストバック printf("x=%d\n", x); // 2 多分最適化されると printf("x=%d\n", 2); になる
836 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 15:19:05.40 ID:SsMAbqSz0.net] >>812 > union で最後に書いたメンバと別のメンバを読み出すのも C++ では未定義動作だよ。 一応unionのところ(9.5)読んだ。これは書いてなかった。 ただしGCCが「独自拡張だ」って言ってんだからどこかにはあるのだとは思うが。 章番号分かればよろしく。まさか、書いて無いから未定義って奴か? なお9.5.5ではanonymous union ってのが定義されてて、どうもこれでやれってことっぽい。 例は以下。 void f() { union { int a; const char* p; }; a = 1; p = "Jennifer"; }
837 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 15:22:01.05 ID:p3uF8GIb0.net] dynamic_typeはdynamic_cast<>とかtypeidの実装がvtableを悪用した黒魔術なので使わなーい それはそうとして、Type-Based Alias Analysisの障害となるaliasingだけことさら問題視するLLVMの人らのスタンスはフェアではないキモス 同じ型でもaliasingは起こそうと思えばいくらでも起こせるし、コンパイラはプログラマーが意図的にaliasingさせるケースが有り得るのではと 猜疑心にとらわれて十分な最適化ができないのは同じ やっぱC++は関数型プログラミング言語にシフトすべき頃合い
838 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 15:27:33.98 ID:SsMAbqSz0.net] >>819 3.10.10には the dynamic type と cv-qualified version of the dynamic type しかないのだが、 では double や long long は何型なのだ? > 得られた lvalue を通したアクセスが aliasing rule に基づいて未定義動作となる可能性がある。 ではその aliasing rule を読もう。何章だ? なんとなく aliasing rule はコンパイラ側の仕様で、C++の仕様では無いと思うのだが。
839 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 15:35:56.40 ID:xhmNfS4m0.net] >>823 なんでせっかくリンク貼られた定義を無視するの?(・・・英語まともに読めないならそう言ってね。) dynamic type は式を評価した結果の属性であって型の分類ではない。 aliasing rule は basic.lval にあるルール "If a program attempts to access ... the behavior is undefined" を指す。 https://timsong-cpp.github.io/cppwp/n4659/basic.lval#8
840 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 15:36:33.89 ID:BMNBgd4s0.net] 規格キチガイとの会話は不毛 ツルッツルピカピカ
841 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 15:39:23.48 ID:SsMAbqSz0.net] >>822 違うぞ。 794内リンク読む限り、確かにこの最適化はフェアだし、使われていい。 というか、それ以前はポインタが一つでもあったら全く最適化が出来なくなっており、 確かにそれは問題視されてた。 だから標準化委員会がそっちを選んだ、というのは分かる話だ。 違う型でエイリアスすることはほぼないし。 問題は意図的にやりたいことが偶にあって、そのときにどう回避するかだよ。 763がこれに該当する。
842 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 15:51:01.10 ID:xhmNfS4m0.net] >>826 現行の規格で保証される範囲でまともな方法を見出そうとしてるなら、苦労に見合う実りは得られないからやめとけと言っておく。 標準化委員会のおおかたもそんな認識だから bit_cast なんていう提案が好意的に進められている。 www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0476r1.html
843 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 15:53:50.85 ID:SsMAbqSz0.net] >>824 では最初から分かるようにそう言え。 こちらは仕様書を読むのが仕事ではないので、そもそも用語も知らない。見て分からなければそれまでの話だ。 つか、lvalue, rvalue もひどいが、 xvalue とかもでてきて、いよいよC++はどうしようもなくなりつつあるなと実感したよ。 Linusが嫌うわけだよこれは。 ただまあこれは本題でもない。 aliasing rule の確認の方が重要だ。 してそのリンク先、3.10.10と同じだ。 > 得られた lvalue を通したアクセスが aliasing rule に基づいて未定義動作となる可能性がある。(>>819 ) これはどこからそう取れるんだ? reinterpret_castをした結果が正当なlvalueなら、それをデリファレンスした結果も正当なlvalueだろ。 この章にはどこにも”aliasしてる場合”なんて記述はない。 だらからここを根拠にするのがそもそもおかしいんだよ。 君が期待することがここに書いてあるとしたら、例えば以下になるべきなんだよ。 the dynamic type of the object IF THE OBJET IS NOT ALIASED, とかね。でも実際はそうじゃない。
844 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 16:10:52.86 ID:SsMAbqSz0.net] >>827 つか、完全に暴走してるなこれは。 これならmemcpyと同じだし、 わざわざ別に作らずともmemcpyを正式に認めてCと同じ並びにしたほうがいい。 それ以前に reinterpret_cast が使われている関数内は自動的に -fno-strict-aliasing すればいいだけなんだが。 (関数単位でこの最適化を切る。ほぼ全てこれでいけるはず) ただまあ、これが真面目に議論されているのなら、仕様書の文面や俺の感想はともかく、 君の言う通り、今のC++の仕様では対処する方法がない、ということなのだろうね。
845 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 16:11:41.87 ID:xhmNfS4m0.net] >>828 "If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined" これが lvalue (それ自体は未定義ではない)を通した「アクセス」を未定義とするルールとして読めないのだとしたら、もうどう説明しても無理だろう。 用語を知らないといいながら共通の定義を求めるのではなく開き直って勝手な解釈に基づく話を進められるようではまともな会話にもならない。 説明は諦める。 規格や先人の解説を読みなおすなりして誤りに気づいてもらえれば幸いだ。 https://www.google.com/search?q=aliasing+rule
846 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 16:30:16.51 ID:SsMAbqSz0.net] >>830 ちげーよ。 俺は、reinterpret_castの結果が正当なlvalueなら、それはド頭の the dynamic type of the object に該当するから、 *(long long*)&f = i はありだろ、と読んでるんだよ。そこは君も同じだろ。 > ポインタの reinterpret_cast で型違いの結果を得ることは未定義動作にならないし (>>819 ) つまり (long long*)&f で long long* 型になるのはおk ←君の見解ね、俺も同意だが。 > それに * を適用して lvalue を得ることも未定義動作にはならない。 得られた lvalue を通したアクセスが aliasing rule に基づいて未定義動 (>>819 ) つまり、*(long long*)&f もおk ←これも君の見解ね、俺も同意で。 > 得られた lvalue を通したアクセスが aliasing rule に基づいて未定義動作となる可能性がある ここが違う。 3.10.10には alias が云々って何も書いてないだろ。 しかも *(long long*)&f = i; は両方とも long long なんだから、「型違い」のaliasではないんだよ。 だからGCC等の -fstrict-aliasing には該当しない。 というのが文面からとれる意味だ。あくまで「文面」な。 ただまあ、実際にはそうじゃないんだろ。
847 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 16:33:08.86 ID:SsMAbqSz0.net] ああすまん、ちょっと慌ててて余分なコピペされてるわ。 上記1回目の「得られた lvalue を通したアクセスが…」は余分で。
848 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 16:34:35.29 ID:xhmNfS4m0.net] >>830 > 俺は、reinterpret_castの結果が正当なlvalueなら、それはド頭の > the dynamic type of the object > に該当するから、 > *(long long*)&f = i > はありだろ、と読んでるんだよ。そこは君も同じだろ。 違うねぇ。 オブジェクトの型 dynamic type は式の型とは違うし、式の型の影響を受けるものじゃないんだよ。 何度も区別しろと言ったつもりだったんだけど。
849 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 16:35:57.16 ID:xhmNfS4m0.net] ごめん、アンカーミスった。 >833 は >831 宛てね。
850 名前:デフォルトの名無しさん [2017/11/19(日) 16:43:31.03 ID:7jEiMXMd0.net] >>825 確かに自分に中身のないやつほどルールブックを神格化するよな 自分なりにどう思うなんて怖くて言えないから で、そういうお前さんは何か内容のある発言ができるのかね?
851 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 16:46:31.93 ID:Q6cWJ/Rgr.net] > *(long long*)&f で long long* 型になるのはおk んなこたーない doubleオブジェクトの領域にlong longでアクセスすることが未定義動作
852 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 17:22:20.65 ID:XAwzlQ9S0.net] double f = 0; と変数fを構築した時点で、「値0.0のdoubleオブジェクト」が作られてメモリに置かれるんだよ(規格で言うstored valueな) それはスタック回収やdeleteで破壊されるまでずーーっとdoubleのままで、変わることはないの 外側でポインタや参照をどれだけいじくり回したって決して変わらないの 家の横に「←ここは馬小屋です」って看板を立てたって、その家は家のままだし、勝手に馬を入れて飼うのは未定義動作なんだよ そろそろ理解したらどうなの
853 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 17:56:59.79 ID:BMNBgd4s0.net] >>835 内容ある発言と言われても別にこんなのは規格をひっくり返して議論するようなことでないし たぶん俺なら(little endianだとして) union Double { double v; struct { uint64_t f:52; // fraction uint64_t e:11; // exponent uint64_t s:1; // sign }; }; とかにするかな、それで何の問題も起こらない
854 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 18:00:09.08 ID:SsMAbqSz0.net] >>837 多分それが違うぞ。それはどこに書いてある? 少なくとも多くのCプログラマはそう思って無い。だから平気でキャストする。 そして830内ULRも読んだが、これも明示的なエイリアスがあるケースだ。 お前らが過度にびびって拡大解釈してるだけだろ。
855 名前:デフォルトの名無しさん [2017/11/19(日) 18:11:47.43 ID:7jEiMXMd0.net] あー、こいつcast-as-lvalueに完全に洗脳されている手合いかw
856 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 18:14:47.74 ID:xhmNfS4m0.net] >>839 https://timsong-cpp.github.io/cppwp/n4659/intro.object#1 > ... The properties of an object are determined when the object is created. ... An object has a type. ... 今度からは少なくとも自分でどこをどう探したかぐらい示そうな。
857 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 18:31:26.29 ID:SsMAbqSz0.net] >>841 嘘つけ。キャストした場合についてはどこにも書いてない。 型が普遍なんてのは、君が勝手に思い込んでいるだけだ。 というか、いわゆる「強い型」ってのはそうらしいが、C++はそうじゃないだろ。 ちなみに俺も反論を用意してたところだ。 https://godbolt.org/g/viYhGj 中身は795の場所で、ついでだから f = *(double*)&i; を試した。 予想通りこちらはfmov(movsd)が出た。(最適化は切ってある) つまり、俺が768で言ったように、 *(long long*)&f = i; // mov命令でコピー または f = *(double*)&i; // fmov命令でコピー になるんだよ。少なくともgccはキャストされればその型だと認識している。 君はこれを矛盾無く説明出来ないだろ。
858 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 18:51:00.89 ID:Q6cWJ/Rgr.net] >キャストした場合についてはどこにも書いてない はて、N4700の6.10/p8ほぼそのままの文面が少し上に貼り付けてあったような… >>821 N4700 3.9, 4.5/p1, 6.8全般, 6.10/p8, 12.3/p1, 12.3/p(5.3), その他「launder」が登場する記述全般
859 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 18:52:07.63 ID:p3uF8GIb0.net] 正しいそうなコードが吐かれたことは未定義動作でないという証拠には全くならない なぜなら未定義動作というのは コンパイル時のエラー、実行時のエラー(または例外)、一見正常っぽく気体通り動く、その他、 というあらゆる事象を包含し得るので、、、 もちろんコンパイラの変更で(ことによったらコンパイル条件の変更だけでも) ある日突然狂ったコードが吐かれる危険性があるが そうなっても未定義動作をプログラムした人の責任 よって現時点で正しいげなコードが吐かれることをいかに力説しても無駄で、 規格の矛盾の指摘にはつながらない
860 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 18:53:33.74 ID:xhmNfS4m0.net] >>842 オブジェクトの型に関与しない操作についていちいち記述があるわけないだろ。 まさか「〜によりオブジェクトの方は変わらない」とかの記述が全演算子&標準関数その他諸々について必要だ なんて言うわけじゃないよね? 未定義動作の結果はなんでもアリだと言っただろう。 その結果(想定の命令コードが生成されたこと)が未定義動作の結果のひとつだとして、何の矛盾も無い。
861 名前:片山博文MZ mailto:sage [2017/11/19(日) 19:03:59.08 ID:R56+Z6E80.net] inline const self_type *const_this() { return this; } template <typename T_TYPE> inline T_TYPE *drop_const(const T_TYPE *obj) { return const_cast<T_TYPE *>(obj); }
862 名前:デフォルトの名無しさん [2017/11/19(日) 19:04:38.54 ID:RgqRbH7C0.net] ソースが仕様、ソース読めってやつか。
863 名前:デフォルトの名無しさん [2017/11/19(日) 19:25:00.73 ID:7jEiMXMd0.net] そう言って居直るやつは問題だが ソースを読まない言い訳にするやつもダメ 腐敗は両岸から起きうることだ
864 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 19:53:33.03 ID:SsMAbqSz0.net] >>844-845 うむ。それは一理ある。 >>845 では逆から行こう。reiniterpret_castのど頭、 > 5.2.10 Reinterpret cast > 1. The result of the expression reinterpret_cast<T>(v) is the result of converting the expression v to type T. vをTに型変換したのが結果だとそのまま書いてある。 これはどう解釈すれば、「型はどうやっても変更できない」と取れるのだ? さすがに無理だろ。 > 7. An object pointer can be explicitly converted to an object pointer of a different type. これも型を変更できると読めるが。そして再び1に戻ると、 > 1. ---- If T is an lvalue reference type or an rvalue reference to function type, the result is an lvalue; つまり当然有効なlvalueであり、デリファレンスも可能だ。 だからキャストを反映してmovなりfmovが出るのだ。 違うか? 君が言うようにメモリ上の型が普遍なら、どうやっても i には fmov が出ては駄目だろ。 (と思ったが、君は837ではないのか、、、)
865 名前:デフォルトの名無しさん [2017/11/19(日) 20:02:38.24 ID:7jEiMXMd0.net] >>849 If T is an lvalue reference typeという但し書きがついているよな (double&)ならlvalueだが(double)は違う
866 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 20:09:33.36 ID:xhmNfS4m0.net] >>849 > これはどう解釈すれば、「型はどうやっても変更できない」と取れるのだ? 式の型 (static type) は変わるが、オブジェクトの型 (dynamic type) は変わらない。 > 君が言うようにメモリ上の型が普遍なら、どうやっても i には fmov が出ては駄目だろ。 未定義動作ならなんでもアリだと言った。
867 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 20:15:36.23 ID:SsMAbqSz0.net] >>851 それで突っぱねるのなら平行線だね。 俺は仕様書に詳しいわけでは無いから動作から説明するしかない。 君は仕様書には詳しいようだが、キャストした場合にも型が変更されないという記述を出して来れない。 ま、デッドロックだ。 とはいえ状況は色々分かったよ。ありがとう。
868 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 20:42:27.06 ID:Q6cWJ/Rgr.net] >つまり当然有効なlvalueであり、デリファレンスも可能だ。 仕様を引用して説明されてもこのとんちんかんな発言を繰り返すあたり、 知らないから間違えているのではなくオツムが悪いので必然的に無知になったと言うことに>>851 は気付くべき
869 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 20:47:51.98 ID:xhmNfS4m0.net] >>852 > 俺は仕様書に詳しいわけでは無いから動作から説明するしかない。 なら↓お前の理解に基づいてこの動作を説明できるか試してみるといいかもしれない。 https://wandbox.org/permlink/2aKzO4VN3KRDB6Gu > 君は仕様書には詳しいようだが、キャストした場合にも型が変更されないという記述を出して来れない。 式の型 (static type) とオブジェクトの型 (dynamic type) は別物だという客観的な 前提 [intro.defs] を素直に読みさえすれば何度も見えてるはずなんだけどな。
870 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 20:54:00.37 ID:XAwzlQ9S0.net] こいつわかってて引っ掻き回してるだけのような気がするわ そうじゃなかったら馬鹿すぎる
871 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 21:10:07.51 ID:JvH46D6m0.net] ある型の変数を入力として、別の型にキャストされた値を返すのはそりゃできるだろう 元の変数の型を変えることはそりゃ無理だろう
872 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 21:20:19.91 ID:SsMAbqSz0.net] >>854 それは何も不思議じゃ無いと思うが。 例の最適化もされてるし。 どこが俺の理解と矛盾してるつもりなんだ?
873 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 21:40:24.30 ID:xhmNfS4m0.net] >>857 お前の中でどういう理解になっているかは把握できていない。 その答えからすると、 "*(long long*)&f = i;" なら未定義動作にならないけど "auto p = (long long*)&f; *p = i;" なら未定義動作になる、 という理解なのかな。まぁそんなことは無いんだけどさ。
874 名前:デフォルトの名無しさん [2017/11/19(日) 22:14:48.53 ID:RgqRbH7C0.net] いやまあ無いんだけどな。 いつまで言い張る気なんだろうか。
875 名前:デフォルトの名無しさん [2017/11/19(日) 22:16:28.57 ID:RgqRbH7C0.net] あると言えばあるんだけどな。 そろそろごめんなさいしてはどうか。
876 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 22:24:05.56 ID:kv2+5Ve80.net] 本の虫での解説記事が待たれる
877 名前:デフォルトの名無しさん [2017/11/19(日) 23:33:53.04 ID:qbUCqX2r0.net] strict aliasing ruleについてはここで解りやすく解説されてる。自分で怪しいと思う奴は読め。 d.hatena.ne.jp/yohhoy/touch/20120220/p1
878 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 23:37:47.80 ID:SsMAbqSz0.net] >>858 ああそうだぞ。それは>>815 で既に言ったし、実際に発現事例は今のところ全てaliasされてる。 顕在化させるには、「別型」で「alias」しないといけないんだよ。 オプションの名前も全くそうだろ。 多分君は理屈が分かってないんだ。 あれはtypeグループごとにメモリフェンスしていて、 別typeグループに入っていると結果的にout-of-orderになるだけなんだよ。 それは常時動いている。 ただし different type で alias して無いと顕現しない(ユーザ側には見えない)というだけ。 だからその可能性がある部分にwarningが出る。 しかしwarningというのは「普通やらないけど大丈夫か?」であって「絶対駄目」ではない。 結局君は different type alias について正確に理解出来てないんだよ。 上記を覆したければ、alias無しで different type alias の最適化がかかっている例を持って来い。 君の言う、 > まぁそんなことは無いんだけどさ。 の例だね。多分無いから。 既に言ったがLLVMだからインデックスレジスタは完全に残るんだよ。(多分) キャストを知らないのだから理解出来ないようだが、(long long*) 部分は命令にならない。 (これはC++仕様書にも明記してあるが、C界では常識) だから *&f だけが残り、結果、 *(long long*)&f と *&f (=f) は同じLLVM命令になる。(はず) だからそこは問題視されてないんだよ。最適化器からも同じに見えるから。 逆に考えてみろ。同じtypeグループ内、例えば int と int が out-of-order になったら話にならんだろ。 だから同typeグループ内は alias があっても in-orderになってる。 そして別グループ double と int は常にout-of-orderになってるが、当然、関数でつながれているときにはフェンスされる。 例えば int a = max_idx(double*) みたいな感じで、doubleの配列から最大値の添字を取るときとかね。 だから different type で alias して無いとそれが見えないようになってるんだよ。 というのが俺の理解だ。覆す例があればよろしく。
879 名前:デフォルトの名無しさん mailto:sage [2017/11/19(日) 23:50:16.66 ID:XAwzlQ9S0.net] ダメだこりゃ
880 名前:デフォルトの名無しさん mailto:sage釣 [2017/11/20(月) 00:03:11.09 ID:y/6cZRj30.net] そろそろ専用スレを建てて欲しいな
881 名前:デフォルトの名無しさん [2017/11/20(月) 00:06:21.48 ID:Veq8ZMOx0.net] 最初に質問した奴が謝罪すれば治まるのでは。
882 名前:デフォルトの名無しさん mailto:sage [2017/11/20(月) 00:12:55.32 ID:gqHMI2DN0.net] 最適化は人類には早すぎた 早すぎたテクノロジー
883 名前: mailto:sage [2017/11/20(月) 00:14:41.52 ID:Y8ntE/6M0.net] いきなりレベルの低い話で割り込んで恐縮です。 よろしくお願いいたします。 久々にJava から C++ に移行して、簡単なイテレータパターンを実装しました。 Java で書いた https://ideone.com/DJ9pI5 を元に C++ で書いてみたのがこれです。 https://ideone.com/FwNlc4 ここで、コンテナにあたる Aggregateクラス(具象クラスは BookShelf) の中に イテレータ(Iterator:具象クラスは BookShelfIterator) を作成して返すメンバ関数 iterator() を定義していますが、 C++ だからデストラクタも定義しないとね、と考えて 当初、Aggregate クラスに仮想メンバ関数 delete_iterator() を書いて Aggregate::iterator() と Aggregate::delete_iterator() を対にするように作っておりました。 しかし教科書をみると Aggregate::delete_iterator() みたいなデストラクタはそもそも定義しないようで、 普通に Iterator *it = BookShelf(具象クラス)->iterator(); delete it; でなんの問題もないようです。 なぜ、これで問題がないのかトンと見当がつきません。 イテレータを作った具象クラスの中でデストラクタを定義する、というのならば分かりやすいのですが、 抽象クラスのポインタをキャストもせずに直接 delete できるのは、どういうからくりになっているのでしょうか? よろしくお願いいたします。
884 名前:デフォルトの名無しさん mailto:sage [2017/11/20(月) 00:34:03.39 ID:uuALJ8Da0.net] >>863 > 上記を覆したければ、alias無しで different type alias の最適化がかかっている例を持って来い。 これでいいかな。 https://wandbox.org/permlink/RNDO0CIl9UpsaRwQ
885 名前:デフォルトの名無しさん mailto:sage [2017/11/20(月) 00:41:55.57 ID:uuALJ8Da0.net] >>863 ごめんまちがえた。 >869 じゃわかんないね。 https://wandbox.org/permlink/vuQgmlWOUcxhu5jW
886 名前:デフォルトの名無しさん mailto:sage [2017/11/20(月) 00:53:02.54 ID:H8zFncfx0.net] >>869 せこいわw gcc7.2.0(そこの最新版)で%eにしたら見えるがな。 まあ努力はご苦労様。 とはいえ、gcc4.4.7ならこのコードでも顕在化するし、「aliasが要る」という要件が怪しいのは認める。 この最適化はまだ発展途上のようだね。
887 名前:デフォルトの名無しさん mailto:sage [2017/11/20(月) 01:07:57.23 ID:H8zFncfx0.net] >>870 おっとすまん、輻輳してしまったが、869で問題なく分かったぞ。 そして両方とも、gcc7.2.0にするか、globalにすると直る。 したがって、 different type alias で問題が発生するのには 「aliasが要る」という俺の見解は間違いだ。 ただ、過度の最適化による不具合を防ぐ努力は行われており、 gcc4..4.7→gcc7.2.0でこのコードに関しては修正されてる。 とはいえgcc7.2.0でもどこまで動くか分かった物ではないね。
888 名前:デフォルトの名無しさん mailto:sage [2017/11/20(月) 01:11:14.23 ID:uuALJ8Da0.net] >>872 さぁ、お前の罪を数えろ。
889 名前:デフォルトの名無しさん [2017/11/20(月) 01:32:56.30 ID:Veq8ZMOx0.net] 何で素直に謝罪できないんだろうね。
890 名前:はちみつ餃子 mailto:sage [2017/11/20(月) 01:42:11.88 ID:mEO8F9pQ0.net] >>868 それが virtual の効果だとしか。 基底で virtual 宣言したメンバ関数群はそのポインタをまとめたテーブルが作られ、オブジェクトはそのテーブルを指すポインタを持つ。 派生のオブジェクトは派生側の関数群を指すポインタテーブルへのポインタを持つ。 だから virtual を使うと「変数の型ではなくオブジェクトが呼出すべきメンバ関数を知っている」という状況を作れるんだよ。 ただ、基底のデストラクタを virtual に指定しないときでも見かけ上は型システムをパスしてしまいコンパイルエラーにならない場合がある。 これは未定義だからやっちゃダメだよ。
891 名前:はちみつ餃子 mailto:sage [2017/11/20(月) 01:59:59.63 ID:mEO8F9pQ0.net] >>868 ,875 Wikipedia にも解説があるやないけ https://ja.wikipedia.org/wiki/%E4%BB%AE%E6%83%B3%E9%96%A2%E6%95%B0%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB
892 名前: mailto:sage [2017/11/20(月) 02:35:52.58 ID:Y8ntE/6M0.net] >>875-876 うーん、普通のポリモフィズムの話が同様に適用できるんですね… Base<-Derived1 Base<-Derived2 の基底・派生関係のとき Base *p = new Derived1() ならば、delete p; は delete (Derived1 *)p; Base *p = new Derived2() ならば、delete p; は delete (Derived2 *)p; となる、と考えていいでしょうか。 Base *p = new Derived1() ならば、p->method(); は p->method_Dirived1(); Base *p = new Derived2() ならば、p->method(); は p->method_Dirived2(); という話と同じなんですね。 んーなせ Aggregate::delete_iterator() を作らなくちゃ、と考えたのか逆にわからなくなってしまいました… ありがとうございました。
893 名前: mailto:sage [2017/11/20(月) 02:59:04.07 ID:Y8ntE/6M0.net] 次に >>868 のテンプレート版を書いてみました。 https://ideone.com/LO68r5 void * (Java の Object)をキャストするのを嫌ったという理由になります。 >>868 >class Iterator >virtual void *next() = 0; >class BookShelfIterator : public Iterator { }; >void *BookShelfIterator::next() >Book *book = (Book *)it->next(); https://ideone.com/LO68r5 そこで不思議に思ったことなんですが、 コンストラクタは template <typename T> class Derived : Base { public: Derived(){}; }; とテンプレート引数 T をコンストラクタ名をつけなくていい(public: Derived<T>(){}; としない)のに、 デストラクタは template <typename T> class Derived : Base { public: ~Derived<T>(){}; }; (クラスのメンバ関数宣言) template <typename T> Derived<T>::~Derived<T>() { } (クラスのメンバ関数定義) とテンプレート引数 T をデストラクタ名につけないといけないのでしょうか?何か分かりやすい理由はありますでしょうか?
894 名前:はちみつ餃子 mailto:sage [2017/11/20(月) 03:03:42.40 ID:mEO8F9pQ0.net] >>877 キャストとは意味が違うんだよ。 上でさんざん議論してる static type と dynamic type の話とも関係あるのかなぁ? 入り組んでてよくわからん。 型はあくまでも Base* で、仮想関数テーブルを辿って必要な関数を呼び出すってだけだ。 繰返すけど、 Base のデストラクタに virtual がついてないときに Base のポインタに対して delete すると Base のデストラクタが呼び出されるだけになってまうので気をつけてな。 派生クラスのデストラクタが空っぽのときでもデストラクタが呼び出される必要はあるらしいぞ。
895 名前: mailto:sage [2017/11/20(月) 03:12:59.68 ID:Y8ntE/6M0.net] >>878 の続きです。 同じく、テンプレート版 https://ideone.com/LO68r5 にて一点不満におもったことがあります。 >>878 では基底クラスの記述について、 template <typename T> class Iterator { public: virtual T *next() = 0; }; 派生クラスは template <typename T> class XXXIterator : Iterato<T> { public: T *next(); }; template <typename T> T *XXXIterator::next() { ... } と書きました。 しかし本当は、基底クラスを純粋に一個にしたいと希望しているのです。 つまり基底クラスにテンプレート引数Tを書きたくない。 class Iterator { public: virtual ○○○ *next() = 0; }; と基底クラスを一つだけにしぼりつつ、 派生クラスにテンプレート引数を使用して記述することは可能でしょうか?○○○に書けるなにかいい記述はないでしょうか? テンプレート引数を使用した具象クラスに対応する、テンプレート引数を使用しない抽象クラスを書くことは可能でしょうか?
896 名前:はちみつ餃子 mailto:sage [2017/11/20(月) 03:15:21.39 ID:mEO8F9pQ0.net] >>878 付けなくてもいいし、付けても通るってのは私は今初めて知った。
897 名前:はちみつ餃子 mailto:sage [2017/11/20(月) 03:23:45.23 ID:mEO8F9pQ0.net] >>880 強引なキャストで出来る可能性はあるかもしれないけど、 常識的な方法では出来ないと思う。 ただ、そもそもそういう継承関係を作る必要は無いんじゃないか。
898 名前: mailto:sage [2017/11/20(月) 03:26:59.22 ID:Y8ntE/6M0.net] >>879 ありがとうございます。 meyers の effective C++ 第7章を読み返しています C++ には Java の fainal がないので、うっかり、std::string や std::vector を派生させてしまうところでした、危ないなあ…
899 名前:デフォルトの名無しさん mailto:sage [2017/11/20(月) 03:30:13.52 ID:iECo0Ul80.net] >>868 混乱するならシンプルに設計したら?例えばこんな感じ?登録して表示するだけなら簡単でしょ? #include <stdio.h> #include <string> #include <vector> class Book{ public: std::string name; Book(std::string _name) :
900 名前: name(_name){} void show(){printf("%s\n",name.c_str());} }; class Books{ public: std::vector<Book *>m_list; Books(){} ~Books(){for (auto p : m_list) if (p) delete p;} void addBook(Book *p){m_list.push_back(p);} }; int main(){ Books books; books.addBook(new Book("aa"));books.addBook(new Book("bb")); books.addBook(new Book("cc"));books.addBook(new Book("dd")); for (auto p : books.m_list) p->show(); // iterator使いたいなら //for (auto it = books.m_list.begin(); it != books.m_list.end; it++) (*it)->show(); return 0; } [] [ここ壊れてます]
901 名前:はちみつ餃子 mailto:sage [2017/11/20(月) 03:34:54.09 ID:mEO8F9pQ0.net] >>880 Java のことはあまり知らんので元ネタにした Java 版の方をよく見てなったけど、 interface のかわりに抽象クラスを使おうとしてたのか。 似たような機能に見えちゃうかもしれないけど、インターフェイスを強制する方法としては抽象クラスはあまり良くない。 C++ 的にはコンパイル時にディスパッチする多相と実行時の多相があって、 抽象クラスは実行時にディスパッチする仕組みなのでコンパイル時に確定するはずのことを実行時にするのはクソザコという風潮。 だけど「コンセプト」の機能が C++ に導入されるのが延び延びになってていまだ入ってないので、 traits とか SFINAE とかを使ったまわりくどいメタプログラミングで代用してるのが実情なんだ。
902 名前: mailto:sage [2017/11/20(月) 03:45:45.65 ID:Y8ntE/6M0.net] >>881 >付けなくてもいいし うーん、デストラクタの場合はテンプレート引数をつけないとおこられちゃいます… ×https://ideone.com/x5FrwU 69行目 ○https://ideone.com/FUJ3OO 69行目 よくわらからないな…
903 名前:はちみつ餃子 mailto:sage [2017/11/20(月) 03:53:09.38 ID:mEO8F9pQ0.net] >>886 いや、型名の方には付ける必要あるよ ×: template <typename T> TShelf::~TShelf() { delete [] (this->t_s); } 〇: template <typename T> TShelf<T>::~TShelf() { delete [] (this->t_s); } △: 知らんかった template <typename T> TShelf<T>::~TShelf<T>() { delete [] (this->t_s); }
904 名前: mailto:sage [2017/11/20(月) 03:57:21.44 ID:Y8ntE/6M0.net] >>884 はい、すごくよくわかります!! std::vector とか、std::list とかstd::deque とかは、たぶんいけると思います。 mevius.2ch.net/test/read.cgi/tech/1434079972/14 mevius.2ch.net/test/read.cgi/tech/1434079972/19 なんとなくデザパタ本を読み返していて、車輪の再発明に没頭してしまいましたが、C# のデザパタ本、というのも聞かないし、もうデザパタは古いのかな…
905 名前:デフォルトの名無しさん mailto:sage [2017/11/20(月) 03:58:54.21 ID:O993TKuI0.net] マジか 役に立つ日が来るかどうかはシランケド
906 名前: mailto:sage [2017/11/20(月) 03:59:06.77 ID:Y8ntE/6M0.net] >>887 ありがとうございます。確認いたしました。
907 名前:デフォルトの名無しさん mailto:sage [2017/11/20(月) 03:59:26.41 ID:O993TKuI0.net] ↑ >>887
908 名前: mailto:sage [2017/11/20(月) 04:12:32.38 ID:Y8ntE/6M0.net] >>885 夜遅くにコメントいただきありがとうございます。 >C++ 的にはコンパイル時にディスパッチする多相と実行時の多相があって、 理解できます。コンパイル時に確定できるのなら最大限それに努める思想はたとえば constexpr にも現れていると思いました。 >抽象クラスは実行時にディスパッチする仕組みなのでコンパイル時に確定するはずのことを実行時にするのはクソザコという風潮。 うーん、たぶん私が周回遅れなだけだと思いますが、じゃあ、ひところ、あれほどまでにもてはやされたデザインパターンは、どこにいってしまったのでしょう…もう誰もやらないのかな…
909 名前:はちみつ餃子 mailto:sage [2017/11/20(月) 04:13:43.35 ID:mEO8F9pQ0.net] >>887 なんでこうなってるかっていうのは割と感覚的にやっちゃってるからうまいこと説明できひんのやけど。 クラステンプレートの中に関数テンプレートも書けたりするので template<class T> class foo { public: template<class U> void bar(void); }; 実装書くときはどれがどれに掛かってるかわかるようにせんといかん template<class T> template<class U> void foo<T>::bar(void) { } みたいな話なんじゃないかとコンパイラの気持ちになる仁奈ちゃんの気持ちになってた。
910 名前:はちみつ餃子 mailto:sage [2017/11/20(月) 04:30:34.82 ID:mEO8F9pQ0.net] >>892 抽象クラスを使うパターンなんてのがあるわけ? GoF 本とか読んだことないから知らんけど。 それはインターフェイスをまとめた何かを作れって話とかじゃないの? C++ の抽象クラスを使えって話とは違ったりしそうだけど。 デザインパターンはあくまでデザインの話なんだから言語の具体的な機能はその時代に有るものでやるしかないし、 よりよい機能が提供されるようになったら使うだろ、そりゃ。 抽象クラスを使うやり方しかできないなら「デザイン」を学び取れてないってこった。 まあ今は C++ への理解も十分でないからってのもあるだろうけどさ。 ところで QZ って C++ スレの常連みたいに思ってたけど、 その割にアレなのでひょっとして共通トリップだったりするの?
911 名前: mailto:sage [2017/11/20(月) 04:42:32.81 ID:Y8ntE/6M0.net] >>894 >その割にアレなのでひょっとして共通トリップだったりするの? 単に、あれよあれよと、また、次から次へと忘れていくので、ぜんぜん進歩しないだけなのでした。 こんな感じ… https://www.youtube.com/watch?v=Hflpt1-kAl4
912 名前:デフォルトの名無しさん mailto:sage [2017/11/20(月) 07:05:19.03 ID:8Dez9ldp0.net] 手元に古いGoF日本語訳(1999年初版)があったので覗いてみたら、 Iteratorのサンプル(C++)が>>880 みたいに抽象クラスで実装されていてびっくりした。 抽象クラスを使わなくても、処理の共通化を考えないなら問題ないし、 共通化したい場合でも、そこだけテンプレート化すればよいような気がする。 https://ideone.com/sFzBq4
913 名前:デフォルトの名無しさん [2017/11/20(月) 08:00:57.16 ID:GfOPAtNP0.net] VC++とか今でこそまともだけど昔はテンプレート周りがうんこすぎて風呂釜洗剤教の人のやり方に頼らざるを得なかったらしいね
914 名前:デフォルトの名無しさん [2017/11/20(月) 09:24:05.14 ID:9q5rB25R0.net] そういう「まとも」を求めてVCを選ぶのは情弱のすることだ 意味の違う「まとも」で定評のあるコンパイラであって
915 名前:デフォルトの名無しさん [2017/11/20(月) 09:46:04.69 ID:Veq8ZMOx0.net] Vistaまではgccでコンパイルしてたらしいからな。
916 名前:デフォルトの名無しさん [2017/11/20(月) 10:17:12.94 ID:5dn4op1oM.net] 初心者なんですがusing使い方を教えて下せえ
917 名前:デフォルトの名無しさん mailto:sage [2017/11/20(月) 10:36:08.17 ID:Fx3rJ6pW0.net] usingは時代によって使える機能が異なる 昔はnamespaceから使える宣言を取り出す役割 最近は=を用いてtypedefの簡略化っぽい書き方が出来る
918 名前:デフォルトの名無しさん mailto:sage [2017/11/20(月) 10:42:51.51 ID:Fx3rJ6pW0.net] 将来的にはusingがプロパティの役割まで担ってくれると余計な予約後増やさなくて済む希ガス
919 名前:デフォルトの名無しさん mailto:sage釣 [2017/11/20(月) 12:17:25.71 ID:OatlO4rKM.net] >>897 最初なんてタダのマクロだったし、 4.xだってテンプレート使うと名称長さ制限にかかったり STLのBUGは何時までたってもそのままだし
920 名前:デフォルトの名無しさん [2017/11/20(月) 14:57:25.95 ID:ZHV8ZCmh0.net] ratioのバグとかinitializer_listとかね しっかりしているようで時おり大ボケで笑いを取る謎な会社だ
921 名前:デフォルトの名無しさん mailto:sage [2017/11/20(月) 16:59:42.71 ID:CB3KD7K4p.net] >>883 重箱の隅だけどC++にもfinal導入されたよ、C++11からだっけ stlに付いてるかどうかは覚えてないけどw
922 名前:デフォルトの名無しさん [2017/11/20(月) 17:06:25.94 ID:ZHV8ZCmh0.net] 重箱の隅じゃあんめえ 仮想デストラクタがないことと継承禁止は近いが違う
923 名前:はちみつ餃子 mailto:sage [2017/11/20(月) 17:20:13.60 ID:mEO8F9pQ0.net] std::vector とかを public 継承してもスライシングが起こらないように使う分には全然問題ないわけだしな。 でも人間はアホだからスライシングするし、スライシングしたときにコンパイルエラーにしてくれないから避けようっていう「習慣」なだけで、 言語機能としてはデストラクタが仮想になってないからといって継承が禁止されているってわけではないんだ。 そこらへんは確かに意味づけが違う。
924 名前:デフォルトの名無しさん mailto:sage [2017/11/20(月) 17:54:47.05 ID:4sV97R+K0.net] デザパタは基本的にGC言語向きだしな C++とは相性が良くない
925 名前:デフォルトの名無しさん mailto:sage [2017/11/20(月) 19:05:49.28 ID:RcaXyFV8d.net] C++の基本的なコーディングを学ぶのにオススメな書籍あるかな? テクニック集とかもあると読んでみたいと思っている
926 名前:デフォルトの名無しさん [2017/11/20(月) 19:11:23.76 ID:q0WTO8Pn0.net] EffectiveC++シリーズ Exceptional C++ C++ Coding Standards あたりの定番中の定番でいいだろ
927 名前:デフォルトの名無しさん mailto:sage [2017/11/20(月) 20:12:37.95 ID:rJCmscgl0.net] ここって本職でやってる人らばっかりなんかね 日曜プログラマが気安く書き込んでもいいのだろうか
928 名前:はちみつ餃子 mailto:sage [2017/11/20(月) 20:21:38.03 ID:mEO8F9pQ0.net] >>911 いいよ。 俺も趣味プログラマだけど偉そうに書き込んでるし。
929 名前:デフォルトの名無しさん mailto:sage [2017/11/20(月) 21:53:59.25 ID:gqHMI2DN0.net] GoF本のうち Stateパターンは抽象クラス必須 Abstractなんちゃら系も抽象クラス必須 な印象
930 名前:デフォルトの名無しさん mailto:sage [2017/11/20(月) 22:05:37.00 ID:vFwnmuVP0.net] >>911 プロがここでうんちく垂れてたら引くわな