C++相談室 part155
■ このスレッドは過去ログ倉庫に格納されています
>>88 のサンプル画像からすると、分割された領域の頂点は格子点上にないといけないっぽい ボロノイ境界の交点は都合良く格子点上に来るとは限らないから、ボロノイ「領域」 の作図式にやるのはいろいろな点でイマイチ感が、 ちゅか要件定義的に(三角形は良いとして) (1) 四角形や五角形への分割において凹図形を許容するのか否か (2) ある図形の1つの辺を2つ以上の隣接図形で共有することを許容するのか否か とか決めねばならない いや決めたからといって別に頂点決定アルゴリズムの妙案とか無いが_○/|_ ここは飛ばしてゲーム作ります(´・ω・`)、、、別に面白さと関係ないしね、、、。 processingで似たような事できますか?ちょこちょこ練習しようかな ゲームエンジン使うほどでもないので https://processing.org/download/support.html これダウンロードできます?寄付しろと言われるんですけども c++言語をググるとビャーネも必ず出てきて 彼が設計者だとのことですが、コンパイラを作ってるのは彼ではないですよね 具体的に彼は何をしたの? 言語仕様の策定だろ まあ最初のコンパイラー(コンバーターかも)ぐらいは作ってるとは思うけど 当初はCのプリプロセッサだから今で言うとTypescriptみたいなものだな それとも国際標準化機構(ISO)か何かの配下なの? >>105 K&R Cにクラスの概念を取り入れて見よう ということを思いつきcfrontを実装した TC++PL及びARMを著しC++を広く世界に知らしめた ビヨーン先生の功績は ハゲても立派なプログラマになれるという勇気をくれたことだろう 質問ですが std::vector<SomeBigObject> arr; std::vector<int> indices; というデータがあり、 SomeBigObjectは大小比較可能だがarr自体は未ソートで、 for (int i = 0; i < N; i++) { indices[i] = i; } auto cmpFunc = [](int a, int b)->bool{ return (arr[a] < arr[b]); } std::sort(indices.begin(), indices.end(), cmpFunc); としてindices上で間接的にソートされているとき、 指定されたSomeBigObject x以上の値が現れるarr[i]の最小のiを高速に取得するには どうづればSTLでやるには良いですのん? arrがソートされていれば auto cmpFunc2 = [](const SomeBigObject& a, const SomeBigObject &b)->bool{ return (a < b); } std::lower_bound(arr.begin(), arr.end(), cmpFunc2); で済む話なんだども、SomeBigObjectはコピーの手間がかかるので直接std::sortしたくないという、 また手動で組めということなら明らかに組める int custom_lower_bound(int bgn, int end, const int N, const SomeBigObject& x) { while (bgn < end) { int mid = bgn + (end - bgn) / 2; if (arr[mid] < x) { bgn = mid; } else if (x < arr[mid]) { end = mid; } else { while (mid > 0 && arr[mid - 1] == x) { mid--; } return mid; } } while (bgn < N && arr[bgn] < x) { bgn++; } return bgn; } みたいなことをしたら多分逝けるが、しかしこんなもん使う都度書きたくないし、 ライブラリとして展開して責任負いたくもないんじゃー STLはこういうケースのためにあり、論理的に実現できる以上やり方が考えられていないとおかしいはず…… auto cmpFunc3 = [](int a, int b)->bool{ return (arr[a] < arr[b]); } i = std::lower_bound(indices.begin(), indices.end(), cmpFunc3); arr[i]; じゃいかんのかしら >>115 lower_bound()の第3引数に検索キーxを指定する必要があるから >>115 では解決しないっていうかビルドエラーなヨカン、 ここで気づいたが>>113 のlower_bound()の例は間違ってたわスマン、orz ↓これに訂正 auto cmpFunc2 = [](const SomeBigObject& a, const SomeBigObject &b)->bool{ return (a < b); } std::lower_bound(arr.begin(), arr.end(), x, cmpFunc2); // 3番目の引数は検索キーx ところがソートされているindices上の検索キーは、検索したい実際のオブジェクトxから ただちには求められない(普通にやったら線形探索の手間がかかる、。n_ auto cmpFunc3 = [&](int idx, const SomeBigObject& xx)->bool{ return arr[idx] < xx; } auto i = std::lower_bound(indices.begin(), indices.end(), x, cmpFunc3); arr[*i]; じゃあこれで >>117 ムリス、 つか次のように死ぬほど腐った書き方をしたらとりあえずできるた、 /// 間接ソート版lower_bound int custom_lower_bound(const std::vector<SomeBigObj>& arr, std::vector<int>& indices, const SomeBigObj& x) { // SomeBigObjの間接ソート用比較関数 // xのコピーを避けるため[&](a, b)とする。 auto cmpFunc = [&](const int a, const int b)->bool { // 有り得ないindex値が渡ってきたらxとみなす。 const SomeBigObj& obj1 = (a < 0) ? x : arr[a]; const SomeBigObj& obj2 = (b < 0) ? x : arr[b]; return (obj1 < obj2); }; // lower_bound()の第3引数(検索キー)を有り得ないindex値にしておく。 auto found_it = std::lower_bound(indices.begin(), indices.end(), -1, cmpFunc); // Indexに変換 return (int)std::distance(indices.begin(), found_it); } 動作するサンプル例: https://ideone.com/xbSHmi const int lb = std::distance(indices.begin(),std::partition_point(indices.begin(), indices.end(), [&x,&arr](const int i){ return arr[i] < x; })); これでどうかな? >>122 動かないのをおま環言うのはよく聞くがその逆を聞いたのはこれが初めてかも 確かに動いているように見えるが(呼び出し回数も2分探索相当に見えるが) Compにそんな引数渡して委員会?! 錯覚じゃないの;;; std::lower_bound(first last, value, comp); という呼び出しにおいて、compはcomp((firstやlastと同じ型のiteratorが指す要素), value) という呼び出され方しかされないこと、および valueの型はfirstやlastが指す要素の型とま無関係に好きな型にして良いと規格で決まっている?! チラッと規格見た限り value は first、last と無関係でいいし comp の第一引数はfirst、lastのiteratorが指す型で、第二引数はvalueの型に決まっているように見える >>51 じゃないが、オブジェクト指向で設計する意味が分からなくなった 汎用性の高いフリー関数が沢山あればそれで良いじゃん >>126 > comp の第一引数はfirst、lastのiteratorが指す型で、第二引数はvalueの型に決まっているように見える そこは決まってないと思う。 ・・・いや、 lower_bound() 限定なら引数の順番もその想定でいいのか。 upper_bound() だと comp(value, x) になったりするから、交換可能にしとくのがいいけど、 片方だけ使うなら交換可能にする必要はない、と。 c++20からpreconditionsって書き方に変わったのか。 >>129 upper_boundのpreconditionsには第一引数がvalueのほうしか書いてないよ 質問者ですレスdクス、 >>117 の書き方で>>121 が正しく動いているように見えるのは未定義動作でなくてSTLの仕様ってことでFA? >>126 や>>129 のような巧妙っていやー巧妙だが風が吹いたら桶屋が儲かるみたいなかりにくい仕掛けなのは ステパノフあたりの発案なんですかね…… >>132 あ、ごめん。比較関数の引数順を交換可能にするのは lower_bound, upper_bound 両用にすることを想定しての話。 生魚にあたって、 入院した病院の天井みながらSTL考えてたもんな ニダーランが終了になるそうだ もう糞スレは立てにくくなるな ざまあ >>135 STLなんてかっこつけたネーミングだけど やってることはリニアサーチwww C++11でのstd::swapは、次のようなコードになっているそうですが、 仮に、もし(1)が終わった直後にt1の中のポインタ型やshared_ptr<A>のメンバに nullptr的なものが代入されるんでしょうか。 仮にt1のポインタ的なメンバにnullptr的なものが代入されない場合、 (2)でt1への代入に置いて何が起きるのか心配です。 質問の仕方を変えるならば、 share_ptrは参照カウンタ方式ですのでカウンタのアップ/ダウンは正確でなければ なりませんが、以下の例では、いったいどの行のどの演算子(またはどの部分)で カウントアップ/カウントダウンされるんでしょうか。 template<typename T> void swap(T& t1, T& t2) { T temp = std::move(t1); // (1), or T temp(std::move(t1)); t1 = std::move(t2); // (2) t2 = std::move(temp); // (3) } >>139 誤:仮に、もし(1)が終わった直後にt1の中のポインタ型やshared_ptr<A>のメンバに nullptr的なものが代入されるんでしょうか。 正:(1)が終わった直後にt1の中のポインタ型やshared_ptr<A>のメンバに nullptr的なものが代入されるんでしょうか。 >>138 C++03にもstd::binary_searchあるぞ >>139 > nullptr的なものが代入されるんでしょうか。 この場合はされる。 ムーブセマンティクス一般においてはムーブ後の抜け殻は「無効なオブジェクト」なのでアクセスに対して保証がないことがあるが、 標準ライブラリのスマートポインタについては所有権を移動させた後にそれが空であり メンバ関数 get で nullptr が返ることも、 nullptr と == で比較して真であることも保証される。 > いったいどの行のどの演算子(またはどの部分)で > カウントアップ/カウントダウンされるんでしょうか。 = がその役割を持っている。 ムーブコンストラクタとムーブ代入演算子によってカウントされる。 >>140 どうやら、 (1) の中央の = では、TからTへの move-constructorが呼び出され、 (2)や(3) の中央の = では、TからTへの move-assignment operatorが呼び出される、 ということのようですが、 Tのmove-contructorやmove-assingment operatorは、ユーザーの実装次第で、 ユーザーがそれらを明示的に書かなかった場合の「デフォルトの定義」は 現在もまだ論争中で、標準的な仕様が決まってない、ということらしいですね。 間違っていれば指摘してください。 >>141 そんなのも、ちょっとc\c++をかじったことあるなら 誰でも書けるじゃん わざわざ誰が書いたかわからないようなものより自作できるなら自作するだろ >>143 以下のサイトによれば、「標準的な仕様は決まっている」ようです: drafet C++11 standareのsection 12.8のparagraph 15に implicitly-defined copy/move constructor は、 「a memberwise copy/move of its bases and members」 であると書いてあるそうですから: https://stackoverflow.com/questions/18290523/is-a-default-move-constructor-equivalent-to-a-member-wise-move-constructor The implicitly-defined copy/move constructor for a non-union class X performs a memberwise copy/move of its bases and members. [ Note: brace-or-equal-initializers of non-static data members are ignored. See also the example in 12.6.2. —end note ] The order of initialization is the same as the order of initialization of bases and members in a user-defined constructor (see 12.6.2). Let x be either the parameter of the constructor or, for the move constructor, an xvalue referring to the parameter. Each base or non-static data member is copied/moved in the manner appropriate to its type: if the member is an array, each element is direct-initialized with the corresponding subobject of x; if a member m has rvalue reference type T&&, it is direct-initialized with static_cast(x.m); otherwise, the base or member is direct-initialized with the corresponding base or member of x. Virtual base class subobjects shall be initialized only once by the implicitly-defined copy/move constructor (see 12.6.2). >>142 >ムーブセマンティクス一般においてはムーブ後の抜け殻は「無効なオブジェクト」なのでアクセスに対して保証がないことがあるが、 >標準ライブラリのスマートポインタについては所有権を移動させた後にそれが空であり >メンバ関数 get で nullptr が返ることも、 nullptr と == で比較して真であることも保証される。 なるほど。 行(1)の場合、 1. 右辺でstd::move()をt1に行った段階では(実行段階で)マシン語は全く実行されない。 2. 中央の = は、move-constructor と解釈され、Tのmove-constructorが呼び出される。 3. Tの暗黙定義のmove-constructorは、メンバ同士のmove-construcotrなので、 メンバに shared_ptr<A> a があると、shared_ptr<A>のmoveコンストラクタが呼び出される。 そして、shared_ptr<A>のmoveコンストラクタは、実行後に「src側(from側)」をnullptr相当の 状態にしてしまう。 ということのようですね。 >>146 逆に言えば、Tのメンバに、A *pA; のような生ポインタがあると、 Tの暗黙のmoveコンストラクタ/move代入演算子では、恐らく、 「src側(from側)」にはnullptrが代入されない(??)ので、非常に困った 問題を招くかも知れないと? >>147 Tのデストラクタに if ( pA != nullptr ) { delete pA; } などと書いていた場合、問題を生じそうですね。 c++についてうんちく垂れるやつに限って仕事ができない そんなうんちくどうでもいいから、さっさと作れよって思われてる先輩いるわ >>150 プログラマは怠惰であれ、を地で行ってるんだろう >>144 > わざわざ誰が書いたかわからないようなものより自作できるなら自作するだろ おまえは一生二度とライブラリもOSも使うな ベアメタルだけで食っていけ それができたら、おまえに付いてくる者たちが顕れるだろう できなければ人知れず消えるだけだ どうなりたいかは、お前の人生だ 俺がどうしろとは言えない >>150 またお前か。さっさとプログラミング覚えろよ std::binary_search()は戻り値とかなんとboolや こんなのよかちゃんと位置を返してくれるstd::lower_bound()の方がよっぽど使いでがある ちなstd::lower_bound()が2分探索か線形探索かは使うイテレータの条件次第 std::lower_bound()が線形探索だと断言してくださる香ばしいblogも世の中にはあるが https://rsk0315.hatenablog.com/entry/2019/09/10/173708 これがまつがいであることは比較関数の中でprintf()でもしたらたちどころにワカル ゴメソリンク先は必ずしも断言はしていなくって、std::set<T>にstd::lower_bound()を適用する例か、 これのイテレータはrandom-access iteratorでないから確かに線形探索になる >>144 こういうのが井の中の蛙ってのだな 蛙くん >>149 生ポインタのメンバ変数がある場合で、デストラクタで>>148 のように 書いている場合は、暗黙のmove関数は自動定義されないようです。 なぜなら、暗黙のmove関数は、デストラクタがユーザー定義されている 場合には自動定義されないためです。 他にも、コピーコンストラクタ、コピー代入演算子、move代入演算子 がユーザー定義されている場合も、暗黙のmove関数は自動定義されない そうです。 >>158 誤:暗黙のmove関数 正:暗黙のmove-コンストラクタ コンパイラはともかくリンカに計算負担をかけるのはバカな設計だなと思うわ。 暗黙のmoveがnullptr代入してくれないとか生ポあるクラスに暗黙のctor定義してくれるのか、とか 学ぶ順番間違えて勘違いしてるやつ上の方にいるけど そもそも生ポの扱いに言語が介入するんならdtorでdeleteしてくれるのか、とか考えつかないのかね・・ 質問者はポインタ型とshared_ptrについて聞いてたのに、shared_ptrのことしか答えなかった餃子が悪い。 謝れ!俺に 皆さま御機嫌よう、ちょっと質問させてください class hogeの内部でenum class fugaを定義し、 そのfugaをclass hogehoge でメンバ変数として使用したいのですが、 hogehoge のヘッダーにはなるべくhoge をインクルードさせたくありません。 もちろんfuga変数はヘッダーに置いて使用したいのですが…… 前方宣言でfugaを宣言してもhoge::fugaと互換?が無いため代入が出来ません。 キャストで戻したりして使っているのですがこれならintでもいいかなと…… クラス内クラスの前方宣言は難しいのでしょうか? 何か方法がありましたら教えていただきたく…… class hoge{ enum class fuga{ one,two,three,SUM }; }; //ヘッダーはソースにインクルードしたい class hogehoge{ hoge::fuga mfuga; }; こんかかんじで使いたいのですがエラーになってしまいsまずorz enum classはグローバルに置いた方がいいんでしょうか? 任意のクラス内部で規定したいenumが見た目も便利だと思ったのでなるべく入れ子にしたかったのですが >>167 hoge をインクルードしないところで hoge::fuga を使いたいということは fuga は hoge にそれほど強く結びついていないということで、外に出すのが妥当なのでは? 外に置いたうえで hoge 内で using fuga = outer_fuga とでもすれば、見た目は損なわれないだろうし。 >>168 名前に「ホゲで使うフガ」と名付けるのがいいですかね? 前方宣言で定義したクラスは不完全型みたいでクラス内クラスにアクセスする場合は別途定義が必要みたいです…… 難しい感じですかね std::sortがセーフソートかどうかって決まってないんですね? 安定ソートのことならstd::stable_sortを使え std::stable_sort<T>はどうしてもstd::sort<T>より遅い からstd::stable_sort<T>で安定ソートするテクニックが存在するし需要がある もちろんタダでというわけにはいかずn個のTのソーティングに対しn個の整数型の配列が別途必要だがとにかくできる まつがえたorz 誤: std::stable_sort<T> 正: std::sort<T> 計算量の仕様からすると何だかんだ言って std::stable_sort<T>の中身はマージソートで、 std::sort<T>の中身はイントロソートとクイックセレクトとクイックソートの複合技 ぐらいしかありえない みなさんありがとうございます 安定ソートのことでした > std::stable_sort<T>の中身はマージソートで、 これはまあそんなもうだろうけど > std::sort<T>の中身はイントロソートとクイックセレクトとクイックソートの複合技 なんでここまで限定するんだ? https://cpprefjp.github.io/reference/algorithm/sort.html >C++11以降: O(N log N) (N == last - first) 計算量での比較 >クイックソートは平均計算量がO(N Log N)だが、最悪計算量がO(n^2)である。そのため、C++03の計算量要件には合致するが、C++11の要件には合致しない ubuntuでの開発環境って何があるんでしょうか? openglなのでc++を使うことになると思うんですが、c++はideとしてvscodeでいいですよね guiは何が一般的なんでしょうか? > この関数には、特定のアルゴリズムで実装すべきという規定はない 古典的なソート議論はユニプロセッサ前提 今どきの並列化の流れに必ずしも当てはまるとは思えない boost::sort::pdqsort(), boost::sort::block_indirect_sort() あたりならヘッダーだけで並列ソートできる >>181 GUIなんか使わないのが一般的だよ 開発環境にわざわざC++とLinuxを選ぶような人は自分用アプリにGUIなんて組み込まないだろうし、 他人に使わせるならどうせWindowsでテストしなきゃいけないからLinuxなんて時間の無駄だ OpenGLだったらOpenGLの描画結果を表示するウィンドウとターミナルでいい 自分用アプリねえ 俺の定規ウインドウなんてGUIだけど ぐぐったら沢山出てきた 頭が悪くて理解出来ないけど需要あるんだね unique_ptr<hoge> 自体が型名なんでしょうか? class unique_ptr<hoge>で前方宣言してもいいのかな? 素人なんで自分の説明が難あると思うんだけど自分なりに精一杯説明すると、 ヘッダー部の引数にclass unique-ptr<hoge>& uhogeを載せて、 ソース部にhoge.hをインクルードして定義する感じでつかいたんだけども…… 試してみたけど動くんだけどなんか怖い 想像ではunique-ptr<class hoge>が前方宣言だと思ってたもので…… どこをどう調べればいいのかだけでも教えていただければ…… >>191 テンプレートのインスタンス化は暗黙にやってくれるので基本的にはする必要がない。 どうしても宣言したいのなら extern class unique_ptr<hoge>; と書くことは可能。 ただし、このように宣言した場合には暗黙のインスタンス化は抑制されるので、 別の場所で明示的インスタンス化をしておく必要がある。 テンプレートの展開はその仕組み上、各翻訳単位ごとにやった上でリンク時に統合されるというクソみたいなことになってるので、 コンパイル時間を抑制したいなどの理由でこういった変なことになってる。 ユニークポインタ自体の大きさが、ポインタだから4バイトくらいに統一されているのかな? 型テンプレートがどんな型でも、定義部分で明示してあればポインタ長のメモリをアロケートされているから、宣言自体はある程度の許容範囲があるということなのかな? 理解が違ってたらすいません >>191 1行目yes 2行目はその場合クラステンプレートの明示的実体化になる 前方宣言の場合は template <class T, class D> class unique_ptr; (もちろん名前空間std内 テンプレートは引数与えられてない限りあくまでテンプレートであってコードは生成されないよ >>194 え、明示的インスタンス化しておけばコンパイル時間抑制できるの? ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.4 2024/05/19 Walang Kapalit ★ | Donguri System Team 5ちゃんねる