C++相談室 part133
■ このスレッドは過去ログ倉庫に格納されています
次スレを立てる時は本文の1行目に以下を追加して下さい !extend:on:vvvvv:1000:512 C++に関する質問やら話題やらはこちらへどうぞ。 ただし質問の前にはFAQに一通り目を通してください。 IDE (VC++など)などの使い方の質問はその開発環境のスレにお願いします。 前スレ C++相談室 part132 http://mevius.5ch.net/test/read.cgi/tech/1507561894/ このスレもよろしくね。 【初心者歓迎】C/C++室 Ver.102【環境依存OK】 http://mevius.5ch.net/test/read.cgi/tech/1509780815/ ■長いソースを貼るときはここへ。■ http://codepad.org/ https://ideone.com/ [C++ FAQ] https://isocpp.org/wiki/faq/ http://www.bohyoh.com/CandCPP/FAQ/ (日本語) VIPQ2_EXTDAT: default:vvvvv:1000:512:----: EXT was configured VIPQ2_EXTDAT: default:vvvvv:1000:512:----: EXT was configured pairを戻り値とする関数内でmake_pairを返そうとしてる pair<string, string>( vector<string> vec) { return make_pair<string,string>(vec[0],vec[1]) } 要素数が2より小さいときにペアが作れないから他のものを返したいのだけど こういう場合は何を返せば良いのだろうか? 受けてる先では map<string,string>にinsertをしてる >>137 見直して意味わからんかったので直しました pair<string, string> XXX( vector<string> vec) { return make_pair<string,string>(vec[0],vec[1]) } int main() { map<string,string> map: map.insert(XXX(vector)) } >>137 C++17の std::optional を使うところかな 戻り値をstd::optional<std::pair<string, string>>にして 意味論的に不正な場合は std::nullopt を返す C++17以前なら boost::optional もあり あぁスマンmapに入れるのか でも1つしか無かった場合もmapに入れたいのかエラーにしたいのか?? あとmake_pairは関数だからテンプレート引数は省略できるよ >>127 キチガイ死ね 韓国人死ね >>128 それはCへの回帰だぞ。お前は多分理解して無いと思うが。 >>137 nullobjectパターンかね mapで絶対検索されないキーを突っ込んでおくとか >>137 何を返しても嘘になるので、返してはダメ if (vec.size() < 2) throw logic_error{"runt vector"}; もしくはassert(vec.size() >= 2); name=valueみたいなのを分割してmapに入れる感じ? 俺も例外投げて止めてしまった方がいいねと思うね だが待ってほしい。 例外を投げるということは誰かに責任を押し付けることではないだろうか。 >>129 C++より簡単でお気軽な言語が大量にある今、C++で全くの初心者用の環境を要求すること自体が間違い。 それはトレーラやユンボでド初心者を教習するのに近い。 そうではなく、まず普免を取ってからこれらの特殊車両だろ。 お前は「俺はトレーラー乗りになりたいから、最初からトレーラーでやってくれ」とゴネている教習生なんだよ。 C++のオブジェクト指向でいい本が「世界中に」ない=C++やるような奴にはそんなもの需要がない でしかない。お前はそれすら理解出来ない馬鹿なのに、 > C++の本を書くような人はオブジェクト指向の説明をするのは沽券に関わると思っているのか、 > あるいは「C++の専門家」にはオブジェクト指向を教える能力がないのか。 ってのは自意識過剰すぎる。世界はお前を中心に回っているわけではない。 C++を使う必要がある局面でC++を使う人たちには、今更オブジェクト指向なんて教える必要がないんだよ。 それは自明だから。 そして本を書いている奴らも別段崇高な精神を持って布教しようとしているわけでもない。 いや、そういう奴もいるかもしれないが、当然「売れるから書く」という下俗な奴も世界には必ず居るはずであり、 そういう奴らすらいない=売れない=需要がない=みんな既に知っているから、でしかない。 だいたい、オブジェクト指向ってのはプログラミング手法であり、 言語とは別の軸なのだから、「『C++の専門家には』オブジェクト指向を」ってのも論理的におかしい。 そもそもオブジェクト指向がさも特別で崇高な存在だ、なんてのはJava教団がそうしたがっているだけで、 実際のところは、Cで大規模コードを扱うと、最初はstruct*、次に関数ポインタの嵐になり、 これらをどうにかしてコンパイラに自動的にやらせよう、として生まれたのがC++のオブジェクト指向だ。 だから既に言ったがC→オブジェクト指向は完全に地続きなんだよ。 これは出自からしても当然で、 Cの典型的な問題点を新たな言語サポートにより解決することを目指したものがC++だから。 逆に言えば、C++98で搭載されている機能はほぼ全てCの問題点の克服であり、 Cを使いこなしていた連中にとっては当たり前に「その気持ちは分かる」ものでしかない。(なお同意するかは別) そしてオブジェクト指向もこの中に入っている。 だから当初からオブジェクト指向の有効性をわざわざC++で語る意味はなかったし、 他お手軽系言語が乱立している現在、さらに輪をかけてその必要性がなくなっている。 それでも初心者が「オブジェクト指向自体を学びたい」ときにはどうすればいいかと言えば、 俺個人は「まず3k行程度なら平気で書けるようになってからでいい。そうすればおのずと分かる」という立場だ。 しかしそれでもHellowWorld直後のド初心者に教えようってのならJava教団みたいに洗脳していくしかない。 どう見ても実行に直接関係ない記述の嵐であり、ド初心者にとっては「無駄じゃね?」としか見えないだろうし。 だからこの意味ではJava教に入信しろ、というのもありではあるのだが、 問題はJava教団はJava教の不備は絶対に認めないというか、気づいてないことだ。 関数ポインタさえあれば非常に単純に実装できることを、無理に継承を導入したおかしな構造で対応し、 しかもそれをデザインパターン(キリッと公式化しようとしている所が滑稽だ。 しかし、Java教信者は関数ポインタの存在を知らないから、この教義がおかしいとも気づけない。 また、Javaのオブジェクト指向は今既に邪道で、オブジェクト指向するのが目的化してきてる。 例えばprivateにすること、イテレータを実装することが目的になってるだろ。 だから実際に前スレ896みたいな事も平気でやる。本当に全く意味が無い。 (これについてはLinusはC++erも同様だと言っているが) だからJava教でオブジェクト指向を学ぶのは、邪教というか、 邪オブジェクト指向を学ばされる可能性がかなり高いのでオススメしない。 結局、オブジェクト指向は「学ぶ」物ではなく、本来は「悟る」物なんだよ。 そしてそれは涅槃の境地で解脱しろ、みたいな崇高なものではまったくなく、 「この交差点、信号無いと危なくね?」位の、普通に運転してりゃ分かるだろ、程度の物でしかない。 だからわざわざ解説するほどのことでもないんだが、結果的に、 「オブジェクト指向しろ」と言われる割には解説本がなく、初心者にとってはなんだかよく分からん状況になっている。 そしてお前みたいな馬鹿は「幼稚園で『どこに信号を立てるべきか』きっちり教えるべきだ! 俺は教わっていないから分からない!教えられる先生もいないのか!」 と主張するわけだが、完全にモンペ通り越してキチガイだろ。 オブジェクト指向は幼稚園で教えるべき内容ではないし、教えなくとも自然と理解できる物だし、C++は幼稚園ではないし。 そして脱線すると、「結局オブジェクト指向はよく分からんね」というゆとりが逃げ出した結果が関数型祭りだ。 いや結果的にはC++/C#/Javaの全てがラムダを導入したのだから、一定の成功を得た、と評すべきかもしれんが。 しかしErlangみたいに「オブジェクト指向での限界を突破する」為の明確な方策がなく、 単に馬鹿な連中がより簡単な関数型に逃げ出しただけであり、そこで何か新しい境地が拓けるものではなかった。 そしてGoも俺はこれに似た匂いを感じてる。C++出来ないゆとりが集まっただけじゃんこれ、みたいな。 ただし、確かにC++は無駄に複雑化しているのも事実だが。 > Java鹿 それ、読み方は「Ja馬鹿」ね。ただ表記上分かりやすいので「Java鹿」にしてるが。 まあ俺はゆとりは死ねとしか思って無いからな。 つか、この程度の文も読めないのなら、お前ら仕様書や本も読めないだろ。 向いて無いからプログラマ辞めろよ。 >>148 そこはまぁその関数の仕様として、呼び出す側が確実にcatchする責任があるわけだな。 それを忘れると例外が呼び出し階層を突き抜けていっちゃう。 そういう事態を防ぐために考えられたのが検査例外だけど、これはこれで使いづらい面があるんで Java以外にはあまり採用されなかった。 そんなことを考えてみると>>137 程度の目的で例外などという暴力的な仕組みを使うのがそもそも 適切なのかどうか。Goの選択もそういうことなんだろう。 ttp://nekko1119.hatenablog.com/entry/20120625/1340602468 main関数の最後にあるstringへのキャストでエラーがでるのですがなぜですか。 エラー C2440 '型キャスト': 'Any' から 'std::string' に変換できません。 コンパイラはvc++2017です。 >>158 > Goの選択もそういうことなんだろう。 Goのって「自分でthrowしないといけない例外」だろあれ。 あれなら普通の例外のほうがよかったんじゃ…と思ったけどね俺は。 >>159 (string)をany_cast<std::string>にすれば通りそうだが >>161 通す方法ではなくてなぜ通らないのかが聞きたいのですが template<Type> operator Type() で暗黙の型変換のオーバーロードを定義しており、 int型やHoge型に対して代入する際にそれが使われているのに std::stringに対してだけうまくいかない理由はなぜかが知りたいです。 >>162 intのとこもHogeのとこもキャストは使われてないように見えるが… でもまぁ確かに呼ばれてほしい気もするね static_castでもだめ? すいません。勘違いしてる部分がありました。 std;;stringだけじゃなくて他の型でもダメみたいですね。 質問取り下げます。もう一度自分で考えてみます。 >>161 失礼しました。 >>162 gcc 7.1.0とclang 6.0.0では通った ただしstd::type_infoと書くべきところをただtype_infoと書いてる個所があるので、それは直したけど。 それより下のコンパイラバージョンだとエラーになった。(ambiguous conversion) そして (string)val の代わりに (const string&)val と書いたらclang 4.0.1でも通った。 (int)valはいけますけど (Hoge)val, (std;;string)valはダメのようですね。 で、ご指摘のとおり (Hoge&)val, (std::string&)valは通りました。 前者と後者の違いは分からないですが。 & の意味が分からないなら、プログラミングできない (int)val 普通、こういうキャストの書き方は、しない static_cast など数種類あるキャストの書き方の中から、 キャストの種類を指定してキャストする 君は、入門書を読んでいないだろ >>143 newの代わりにmalloc使ってるとか思ってるアホ? 今時new使うやつは以下のどれか * Javaから来たC++初心者 * 化石コンパイラ使わさせられてる可哀想なやつ * 自身が化石な可哀想なやつ * パフォーマンスのために用意されてない構造の実装が必要なライブラリ設計者 お前は1番目と3番目の複合型だろうね。 template<class Type> Any::operator Type() const 上をやめて、下の2つを定義したらmain関数の記述そのままでうまくいきました。 template<class Type> Any::operator Type&() const template<class Type> Any::operator const Type&() const 理由は分からないです。分かる方がいたら教えてください。 & の意味が分からないなら、プログラミングなんて出来ない。 初歩の初歩なのに まず、入門書を読むこと >>144 >>139 >>145 基本的には2以下は存在しないから例外処理組み込もうと思ったけどnullobjectってのがあるのね おそらく俺の理想的にはこいつが適してそうだからこいつを調べてみるよ >>145 の言うとおりに絶対に呼ばれないキーをいれておくのも検討違いな気はしてる >>147 まさにそれをしようとしてる そこのロジック的には空文字入れる予定だから必ず2以上になるのだけど 関数分割していて関数としては何が返ってくるか不明なため 問題が起きたときのコードを記載しようとしてる vectorのsizeが0や1の時にアクセス違反になってしまうからどうやれば回避できるのかなぁと悩んでる 例としてはこんなん =value key=value key= ==value >>171 確かにそうだね それにclangの最新だと通ることから、それなりにややこしい話かと思う >>173 > key=value これは正常ケースだよね > key= 仕様によるけどvalueに空文字入れときゃいいんじゃね? > =value > ==value エラーでしょ? 例外発生させるなり、ログ採ってnullptr返すなりしなよ そんなものを無理矢理 map に突っ込もうとするのがおかしいと思うぞ >vectorのsizeが0や1の時にアクセス違反になってしまうからどうやれば回避できるのかなぁと悩んでる vectorの要素数が不確定の場合はatで取り出せばいいよ、なんかあったらout_of_rangeが飛んでくるから >>175 空文字入れるのはできてる ただベクターの生成は別関数が行うから引数に渡されるベクターにいくつ値が入っているか不明 だからマップ作成側で個数を意識する対策する必要あるよね?って話 ベクターの生成に関しては実際問題ない >>176 try catchするしかないのかな nullopt返そうとしたけど実装無理だったわ... 例外投げるかなにかしとけばよいって ロジック的に要素数2未満はあり得ないし想定してないんでしょ? 余計なことする必要ないって、以降の処理が余計ややこしくなるだけだから エラー処理が適切 あってはいけないことなら assert で止めてしまえよ assertは良いがリリースビルドで消えてなくなるから それがあってるかどうかだな よほど条件に自信があればassert >>178 おいおい、例外をエラー処理以外に何に使うってんだよ >>182 だから、エラー処理が適切だから 例外投げてエラー処理でもしとけば?と書いてあるはずだが・・・ ただこの手合い、例外投げて、それを受け取ったからと言って リカバリーしてプログラムを再開できるかはわからないよなぁ プログラム本体の状態を一切汚さずに(書き込まずに) 新規領域のみで何か処理をして 例外が飛んで来たら全てを無かったことにする・・・とか 例外でやる場合は例外安全を確保するのが結構面倒なんで プログラムの末端から例外投げるのは最後の手段にしたい だから「実際に実行してみないとエラーが出るかわからない」系のエラーが無いのであれば 早期の段階で入力データにエラーがあるかどうか精査して、エラーがあればその旨返して 以降はエラーが発生しない前提で処理する(ので巻き戻すことは考えない) もし不慮のエラーが発生したら、バグであるからログ吐いて異常終了 可能なかぎり、なるべくこちらで行きたいわけで >>177 optionalを挙げたものだけど 惑わせたようで申し訳ない insert 前にチェックして不正ならそもそもinsertしない設計を考えてました 結局 optionalを返す insert / find を自前実装することになるから そんな面倒な事せずに 素直にXXXで例外投げても全く構わないと思う 一応詫び代わりに書いてみたけど 鵜呑みにはしないでください C++17 例外なし 読みやすさのためにautoなし https://wandbox.org/permlink/rag4d7YPqwPKQpNq 検査可能な事前条件はそりゃ呼び出し側の責務にしたいわな >>177 > ただベクターの生成は別関数が行うから引数に渡されるベクターにいくつ値が入っているか不明 .size で取ればいいだけだろ そもそも name=value のパース結果をベクターで渡してくると言うの設計もどうかと思うが > だからマップ作成側で個数を意識する対策する必要あるよね?って話 そうだよ、その対策を>>175 にかいたつもりだが... もしかして name= と =value の両方とも vec[0] にしか入れてこないとかなってるんじゃないよね? だとしたら生成部分を直さないとどうしようもないけど 色々とありがとう 最終的には呼び出しもとでtrycatchすることにしました >>188 両方とも0 1の要素に値いれてるね もう一個別件なのだけど ファイルの存在チェックとファイルのオープンエラーについて教えてほしい ある設定値は特定の設定ファイルが存在するにも関わらず読み込めなかったときに有効になるものとしたい 且つ設定ファイルが存在しないときもある (設定する値が二つある。ひとつはkey=valueの形のvalue、もう1つは正常にファイルから値がとれたか否か) ファイルが存在しないときはvalueの値をデフォルトで扱う必要があるので、 単純にファイルオープン処理を用いて一度で処理できなかった (ファイルがなくて開けないのか、あって壊れていて開けないのか判断できないので) そのため statでファイル存在有無チェック→ファイルオープンとしたのだけど タイミングが一致してないので刹那のタイミングでのファイル焼失を担保できないと言われている どうすればファイルがなくて開けないのか、ファイルが壊れていて開けないのかを判断できますか ファイルオープンの開けませんでした例外をキャッチしたらええやろ keyにデフォルト値が存在するなら、最初にデフォルト値のmapを持つ。 ファイルを読み込んで存在したキーだけ上書き更新する。 だけでいいだろ。ファイル読み込まれなければ全部デフォルト値のままだ。 例外見ろよ std::ifstreamならstd::ios_base::failureだからcode()の戻り値見ろ 何のために投げてると思ってるんだ >>168 ゆとり死ね お前は何も分かってないし、学ぶ知能もない >>190 > 刹那のタイミングでのファイル焼失を担保できないと言われている てかそいつに聞けよ。 課題として与えられてるのなら、そいつは「考えさせることに意味がある」と思っているのだから、 こんな糞上司に付き合ってられるか、と思ってないのなら自分で考えろよ。 ここで聞いているのは宿題の答えだけ写しているようなもので、全く上達しないぞ。 ファイル存在チェック→オープンがアンチパターンなのは常識だろ何言ってんだお前 相変わらず持論展開ウザ杉るの自覚してないな アスペウンチ君 割とタイムリーな話題というか、ここ一週間ぐらい、実行時エラーやら例外やらが発生したとき どうやったらプログラムを安全に再開するか考えてた で、至った考えは、ひとまとまりの一連の処理を二つに分割して まず前半はread onlyセクションで、プログラム本体の状態を書き換えてはならないが そのかわり例外が発生したら、無かったことに出来る(なのでread onlyにしておく) 後半はwritableセクションで結果をプログラム本体に反映させるが、その代わり例外(失敗)は許さない bool func(){ hoge_type result; try{ result = sub1(); sub2(); }catch(...){ /*リカバリ可能*/ return false; } try{ hoge = result; }catch(...){ /*リカバリ不可*/ abort(); } return true; } ただこれでもあまりうまくいかなくて、sub1()とsub2()が上記ルールに従ってたとしても sub1()は成功してsub2()は失敗した場合に困る 全体としては失敗だけどsub1()は既に成功していて結果も反映されているので sub1()の実行を無かったことにして巻き戻すのは難しい sub1()をsub1_read_only()とsub1_writable()に分解するという方法もあるかもしれないが データの受け渡しで苦労するし、可読性が落ちるうえ、複雑なことはしにくくなる もう一つの別の要求もあって、重たい処理は別スレッドで実行して即座にGUIスレッドに制御を返したい ということはユーザーは重い処理のキャンセルが出来るだろうが 処理のキャンセルは例外からのリカバリと本質的には全く同じこと また、先ほどのread onlyセクションはプログラム本体の状態を書き換えない前提なので 別スレッドで実行したり非同期に同時並行で実行したりが出来る (ただし、誰かがwritableセクションを実行したら、そいつ以外の処理結果は無効になる 古いデータに基づいて処理した結果ということになるので・・) 上記のようなことを総合的にまとめると void func(){ // read only セクション barrier(); // writable セクション } という結論に至った ただし、func()はコルーチンから呼び出す read only セクションでは、必要であれば処理を別スレッドで処理を実行することが出来、自身はyield_returnする 投げた処理が終わるとメインスレッドにて続きから再開してもらう read only セクションでは、新たなコルーチンを作成することが出来、作成元のコルーチンと親子関係を構築する 親子関係を持つコルーチンの全てがbarrier()に到達するか終了してからでないとbarrier()以降は実行されない 親子関係を持ついずれかのコルーチンがread only セクションにて補足されない例外を発生するか もしくは外からキャンセルされると、無かったこと扱いになって 全ての親子関係を持つコルーチンにおいてbarrier()以降は実行されない (親子関係の有る複数のコルーチンの処理が一端barrier()で止まって、全てが成功したのを確認してからbarrier()以降が再開される) コルーチンにはグループNoを設定することが出来る 違ったグループNoを持つコルーチンを同時に実行することはできない(終わるまで待つ) 同じグループNoを持つコルーチンは同時に実行できるが いずれかのコルーチンがyield_returnした段階で、それと親子関係のあるコルーチン以外はすべてキャンセル扱いになる たとえばボタンAを押して処理Aが始まったが処理Aが終わる前にボタンBが押されたら 処理Aはキャンセル扱いになって処理Bが反映される キャンセルされると困るような処理は別のグループNoにしておく というような感じでひとまず落ち着いた グループNo周りはかなり暫定的な感じだが・・・ 以上日記 32 名前:デフォルトの名無しさん (ワッチョイ 07eb-5mWG)[sage] 投稿日:2017/11/26(日) 17:30:11.12 ID:DaGrByo80 [1/4] C++入門書でよく勉強したはずなのにautoとかconstexprとか知らんもんが一杯… 35 名前:デフォルトの名無しさん (ワッチョイ 07eb-5mWG)[sage] 投稿日:2017/11/26(日) 17:38:44.74 ID:DaGrByo80 [2/4] >>32 やさしいC++第3版 大体9年前に買ったのを寝かしといて最近になって勉強し始めたが、そんなに仕様変更ないと思ってたが間違いだったようだ 36 名前:デフォルトの名無しさん (ワッチョイ 07eb-5mWG)[sage] 投稿日:2017/11/26(日) 17:39:04.93 ID:DaGrByo80 [3/4] >>33 だった 39 名前:デフォルトの名無しさん (ワッチョイ 07eb-5mWG)[sage] 投稿日:2017/11/26(日) 17:52:39.37 ID:DaGrByo80 [4/4] Effective Modern C++17出たら買ってみるわ 95 名前:デフォルトの名無しさん (ワッチョイ 07eb-5mWG)[sage] 投稿日:2017/11/27(月) 12:49:42.23 ID:vi7VqSly0 [1/2] 遠回しに他の言語の本読めって言っとるようなもんだ 98 名前:デフォルトの名無しさん (ワッチョイ 07eb-5mWG)[sage] 投稿日:2017/11/27(月) 13:23:45.26 ID:vi7VqSly0 [2/2] >>97 ああそういうことね 132 名前:デフォルトの名無しさん (ワッチョイ 07eb-5mWG)[sage] 投稿日:2017/11/28(火) 12:26:15.71 ID:+ODnZXKO0 [1/2] Java原人がいるようだね 156 名前:デフォルトの名無しさん (ワッチョイ 07eb-5mWG)[sage] 投稿日:2017/11/28(火) 23:59:58.99 ID:+ODnZXKO0 [2/2] ワッチョイって神だわ 199 名前:デフォルトの名無しさん (ワッチョイ 07eb-5mWG)[sage] 投稿日:2017/11/29(水) 21:47:36.72 ID:ZCDC/+v90 実際にスレ汚しとるのはお前だけどな さすがゆとり、これらが役立つ投稿のつもりらしい。 バックアップの、3-2-1 ルール 同じデータをコピーして、3つ持つ。 2つの媒体に保存する。 1つは、離れた場所に持つ >>200 SQLite3使ってみろ。 >>201 C++はyeildも入れたのか?と思ったがstd::yieldはただのsleep(0)か。 まああまり凝ったことしても、とも思うし、そもそもGUIはC++で無理に組む意味無いぞ。 それも含めて自由にやればいいとも思うが。 >>125 君は何が言いたかったのだ? 分かると思うが俺がゆとり死ねと言っている奴だ。 見る限り、君は話す気はあるようだ。 125は唐突過ぎてスルーしたが、相手してもいいぞ。 ただし125はバラけ過ぎているからテーマを絞れ、と言いたいところだったが、 その日記を読む限り上段落の話は一連のテーマか? だったらWeb系の連中ならそこは「DBを使う」って事になっている。 C++は自前で何でもできるから、無意味なほど精神論で速度を追求するわけだが、 そこらへんをサクッと割り切るあいつらのやり方にも学ぶ物はあるぞ。 そもそも自前でトランザクションを実装するとか、検証の手間まで含めたらありえんだろ。 精神論でゴリゴリではなく、上手く手抜きするコツも覚えるべきだ。 実際問題、メモリやデータだけを復元の対象とするとしたら DBなど使わなくとも原本を保存しておけば何があっても元に戻せるのだが そういう話ではないし どのみち非同期処理にC#よろしくコルーチンが使いたいわけで ただしそのままでは並行して細切れに処理が走って危険なので 書き込む前にbarrierを設けようというアイデアがまずあって そうすることでついでに例外安全性も確保できるし ならばキャンセル処理もできますわなぁという巡り合わさった面白い話 >>194 確かにそうだね ありがとう 自分なりに調べて回答も出たのでそれでいくことにします >>206 > 巡り合わさった面白い話 まあ俺は単に張り切りすぎだと思うけど、 そういうところを含めて無駄に熱いのがC++erのいいところでもあるとは思う。 Web系の奴らは上手くこなすことだけを考えていて、自分で考えることを止めてしまってる。 あれでは上達しないのも分かる。 >>200 一応捕捉しておくと、SQLite3はDBだが鯖形式ではなくCのライブラリ(DLL)だからC++から直接呼べる。(はず) ソースはパブリックドメインだからDLできるし、もちろんincludeしても使える。 (https://www.sqlite.org/quickstart.html // サンプルが extern "C" ではなく include かよ!) DBはメモリ上にも置け、当然爆速だ。自前でトランザクション/ロールバックの仕組みを作るよりだいぶ楽。 公式に素晴らしいドキュメントがあるから詳しくはそこを読みまくったほうがいい。 C++erなら問題はSQL位だが、どうせいつかLINQもC++に導入されるだろうし、予習だと思ってやっとけ。 例外投げるってのは自分の責任の範囲外の事象が起きたときじゃないのかね 有効無効の意味合いならブール値返したほうがいいと思う 一応いまのところこんな感じで書けるようになってる やってることが非同期処理なので多少ややこしいのは本質的に仕方がない int func_async( int n ){ if( n == 0 ){ return 0; } a_wait() << [&]{ sleep( 10*1000 ); }; //↑非同期で何か重たい処理 //↑別スレッドに投げたのちyield_return; int resunt; a_sync() << [&]{ //コルーチン作成 resunt = func_async( n - 1 ); //再起呼び出し }; //throw nanika; //↑仮に誰かが例外を投げれば親子関係のあるすべてのコルーチンの処理が //↑キャンセルされて、どのコルーチンもbarrier以降は実行しない //barrier前なのでresultの値は不定 barrier(); //barrier後なのでresultの値が決まる return n + result; } int main(){ a_sync() << [&]{ //コルーチン作成 int result; a_sync() << [&]{ result = func_async( 10 ); }; //コルーチン作成 barrier(); printf( "%d\n", result ); } message_loop(); return 0; } C++の名前空間と呼ばれるのがあまり理解出来ないんだが Javaでいうパッケージ的なやつ? それともそれを使うためのパスワード的なやつですか? >>212 複雑っていうけど、元から非同期処理なんか、どう書いたって複雑だろ >>211 はお遊びでワザとコルーチン作りまくってるだけだし あの程度の事なら本当はこれでいけるわけで int func_async( int n ){ if( n == 0 ){ return 0; } a_wait() << [&]{ sleep( 10*1000 ); }; //非同期処理 return n + func_async( n - 1 ); } int main(){ a_sync() << [&]{ printf( "%d\n", func_async( 10 ) ); }; message_loop(); return 0; } 別に複雑と言うほどでもないし 非同期処理を同期処理みたいにかけるというだけ あとはキャンセルと例外安全のためにbarrierの機能を追加しただけ >>214 まず、君が書いているんだから君が好きなようにやるべきだし、 実験的な意味合いも含めて色々やること自体はいいと思うが、、、 非同期にしてるのは何故?GUIからの呼び出しでC#のasync Taskと同じ状況か? それなら確かにどうしようもないが、しかし今見てみるとC#のasyncもだいぶ筋が悪いとは感じるね。 そのケースなら、普通にマルチスレッドした方がすっきり書けるはず。 あと、コルーチンからのthrowって、君の意図しているようにドミノ倒し的に回収できるものなのか? これは俺が仕様を知らないだけではあるが、普通はコルーチンってそういう使い方しないと思うし。 >>あと、コルーチンからのthrowって、君の意図しているようにドミノ倒し的に回収できるものなのか? そういう風にコルーチンを実装した 具体的にはコルーチンのメンバにキャンセルフラグを持たせておいて コルーチンを外部からキャンセルしたいときはそのフラグを立てる・・・だけ コルーチンがyieldから再開したら真っ先にそのフラグを読みに行って もし立ってたら自発的に例外を投げてスレッドを巻き戻す >そのケースなら、普通にマルチスレッドした方がすっきり書けるはず。 あくまでこれは例だからなぁ 上で書いた内容もそうだけど、ひとつコルーチンがシングルスレッドというのがミソになってて マルチスレッドだと排他処理が非常に面倒なことになる場面でも コルーチンはシングルスレッドだから問題にならない ただ、yieldの前と後ろで時間的につながりが無いことが問題になるので 誰かが何かを書き換える前にbarrier()を設けるルールを作って、他のコルーチンを無効にする 非同期処理なんかまともにやったら頭がおかしくなるに違いないので 横断的に静的に管理したいなぁと 今までコルーチンは全然使わなかったし、完全にマルチスレッド脳だったんだが コルーチンはかなり脳の負担が少なくてよい 自分が動いているときは必ず他人は止まっているという性質が良い yieldの前後だけ気を付ければ後は完全にシングルスレッドのノリで排他処理が要らない ただ逆に同期オブジェクトをLockしたままyieldしたら終わるという >C#のasyncもだいぶ筋が悪いとは感じるね。 正直、あれの使いどころは俺もよくわからないんよなぁ 複数のコルーチンが同時並行で走ったら危ないから結局画面をロックせざるを得ないんじゃないかとか キャンセルを受け付けられるようにするためには例外安全についても考えないとダメなんじゃないかとか 色々思うところは有るが、実はよく知らん >>216 async/awaitのしくみはawaitするタスクの完了時に呼ばれるべきコールバック関数登録の糖衣構文にすぎないとかそんな感じ、 ttps://qiita.com/ryosukes/items/db8b45c8ea42f924f02f (まんまC#の関数で説明したページもあったはずだがどっかいったのでJavaScriptの例↑ で、ネイティブスレッドX上でasync/await呼び出しをいくつ書いても上記コールバック関数は単一スレッドで実行されるので Xに対して同期的なデータへのアクセスはロック不要 ウィンドーズホンのGUIをぬるぬる動かすのがほぼ唯一の存在意義 つまり同一スレッド内であればasync/awaitをいっぱい書いても複数のコルーチンが順不同でresumeされる感じにはなるが真に同時並行で実行されることにはならない なお順不同なresumeというシチュは、関数A内でawaitされるasyncタスクB内でタスクCをawaitする…とかいったケースで容易に生じる この場合A内のawaitに引き続くのコードと、B内のawaitに引き続くコードのは順不同でどっちが先にresumeされるかわからん しかし真に同時並行ではなく、同期的 ttps://stackoverflow.com/questions/1724036/splitting-templated-c-classes-into-hpp-cpp-files-is-it-possible Your template classes must represent only data structures not the algorithms. This enables you to hide more valuable implementation details in separate non-templatized class libraries, the classes inside which would work on the template classes or just use them to hold data. この回答の具体的な例を教えて頂けないでしょうか。 std::vector(データ)とstd::algorithm(アルゴリズム)と思ったのですが、 std;;algorithmはnon-templatized classではないですよね。。。 >>217 > あくまでこれは例だからなぁ もしかしてコルーチンを自動的にマルチスレッド展開して加速させる為のラッパを用意してるってことか? それならまあそのコードの感じになるのかもしれん。 ちなみに言っておくと、俺が普通に実装したら>>215 と同じようなものになる。 単純に、「ディスパッチして、joinを待って、commitする」としか読めないコードにする。 ただこれは君ももちろん分かっていて、あのコードなのだとは思う。 なお俺はC#のasyncは設計ミス、 ・UIコンポーネントがUIスレッドからでしか触れないこと の対策だと思っている。あれが無いと毎回invokeするとか、ちょっと回りくどい書き方をするしかない。 実際、Thread->backgroundWorker->Task->async Task だったっけ?何度も変更されていて、 こういう場合は通常、 ・修正している奴が馬鹿だから修正のたびに新たなバグを仕込んでしまい、収拾がつかない わけだが、ヘルズバーグとMSがそこまで馬鹿なはずも無く、もう一つのケース、 ・根本の問題を修正せずに表面的に対策をしているから、収拾がつかない のだと思っている。そして、根本の問題は、最初に書いたUIガー、って奴。 これについて「根本のUIスレッドの問題直せやボケエ」ってをずいぶん前にC#スレで議論した覚えはあるが、 UIをマルチスレッドにして悲惨だった歴史が既にあるらしく、 「オメーがラップすりゃいいだけだろボケエ」と返され、あ、確かにそうだな、と思って終わった。 ま、とにかく、UI関係のコードをスッキリさせる為の物だから、気になってないのなら放置でいいと思う。 > yieldの前後だけ気を付ければ後は完全にシングルスレッドのノリで排他処理が要らない コルーチンの方がいいケースについてか。 うーん、どうなんだろうなあ?俺もコルーチンはほぼ使ってきてないが、 マルチスレッドする場合にはほぼ干渉しない場合に限っていたから、 逆に言えば、コルーチンを使えばもっと並列化できるということか? Eigenで透視投影変換行列を作るのは次の書き方でいいんでしょうか? なんか結果をみても微妙にずれているのですが... Eigen::Matrix4f perspectiveMatrix(float left, float right, float bottom, float top, float near, float far) { Eigen::Matrix4f m; m << 2.0f*nearZ/(right-left), 0.0f, (right+left)/(right-left), 0.0f, 0.0f, 2.0f*near/(top-bottom), (top+bottom)/(top-bottom), 0.0f, 0.0f, 0.0f, -(far+near)/(far-near), -2.0f*far*near/(far-near), 0.0f, 0.0f, -1.0f, 0.0f; return m; } await/asyncのコルーチンは並列化じゃなくて非同期処理を同期処理っぽく書くための物だとおもうよ 「これを実行して、終わったらこれを実行してね」 っていうときに、スタックの内容がそのまま残ってるからデータの受け渡しが楽というだけだろう ただ>>220 が言ってるように順不同のresumeが起こったらアブナイので 何か書き込む前にbarrierを張って自分に関係が無い実行中のコルーチンを全部キャンセルして始末してしまおうという (実際にはbarrierだけじゃなくawaitのタイミングでも始末するようにしているが) ただキャンセルするために例外安全性とかも重要になってきて ここでもbarrierとコルーチンの仕組みがそのまま活躍するのが、なんか不思議な感じなんだが 読み込みオンリーだけどキャンセルできるセクションと、書き込みできるがキャンセルできないセクションに 処理を分けるというアイデアはなかなか汎用性が有るんじゃないかと で、二つのセクションは別関数にせずにコルーチンでつないで一つの関数に収めbarrier前/後とし barrier前ならawaitも使える、と、2,3のことが同時にかたづいて気持ちが悪い exec execve などいくつかあるけど こいつらの違いを理解できない ここの人たちはmanページを読んで理解できるもんなの? >>227 解決しました。あれで合ってました。 間違ってのはモデル変換行列の方でした。 >>224 最終的に何をしたいんだ? 俺にはそこが見えない。 一つずつ詰めると、頭三行 > await/asyncのコルーチンは並列化じゃなくて非同期処理を同期処理っぽく書くための物だとおもうよ > 「これを実行して、終わったらこれを実行してね」 > っていうときに、スタックの内容がそのまま残ってるからデータの受け渡しが楽というだけだろう については同意する。これは>>218-220 含めて3人の共通理解でいい。 (ただし俺には逆に、君自身は「並列化の為に」async/awaitを使おうとしているように見える) > ただ>>220 が言ってるように順不同のresumeが起こったらアブナイので これについては、一般的には逆だ。順序が逆になったら危ないような物を非同期にしてはいけない。 違う言い方をすると、非同期の結果をbarrierを張ってキャンセルするのではなく、 barrier後に非同期にして、結果は必ずcommit出来る構造にする。 ちなみにJavaScriptの連中はここら辺が分かっていなくて、 (というより連中は制御構造云々を議論できるレベルではないのでこれ以前なのだが) 同期前提の制御構造で非同期を扱おうとするからおかしなことになる。 JavaScriptには非同期しかないんだから、選択の余地もないんだが。 C#のasyncはこれとはちょっと違って、イベントで起動するから必ずUIスレになるんだが、 それにジョブをやらせるとUIがカクつくから他スレッドを起動しろ、 しかしそれだと結果を画面に表示できないからそこだけUIスレッドを呼び戻せ、 ただこれだとソースが汚いから、asyncというキーワードをつけ、あたかも全てUIスレッドが処理しているように見せる、 みたいな、なんだかなあ、という状況になっている。 つまり処理順と処理スレッドを入れ替える為の糖衣構文のようなものであって、 本来のasync/awaitのように、非同期を同期的に書くための物自体ではない。ただしそうとも使えるから流用してるが。 それで話を戻すと、君は非同期部分に一般とは逆の「非同期の結果を普通にキャンセルできる構造」を作ろうとしているようだが、 これは何故?或いは何のメリットがあると考えている? Java厨はハードの基本がわかってないニワカなんちゃってPGが殆どだからな ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.5 2024/06/08 Walang Kapalit ★ | Donguri System Team 5ちゃんねる