◎正当な理由による書き込みの削除について: 生島英之 とみられる方へ:C++相談室 part165 ->画像>3枚
動画、画像抽出 ||
この掲示板へ
類似スレ
掲示板一覧 人気スレ 動画人気順
このスレへの固定リンク: http://5chb.net/r/tech/1698705458/ ヒント: 5chスレのurlに http ://xxxx.5chb .net/xxxx のようにb を入れるだけでここでスレ保存、閲覧できます。
!extend:checked:vvvvv:1000:512
!extend:checked:vvvvv:1000:512
↑同じ内容を3行貼り付けること
次スレは
>>980 が立てること
無理なら細かく安価指定
※前スレ
C++相談室 part164
http://2chb.net/r/tech/1683600652/ VIPQ2_EXTDAT: checked:vvvvv:1000:512:: EXT was configured
>1 乙です 前スレ 例外はループ脱出に使うような物じゃない、との意見に賛成です。 自分は、例外は「起こり得るけどいちいちエラー処理を書いたらアホな話を」「処理呼び出し毎ではないレベルで」「エラー対処コーディングするもの」と思ってます。 具体例は、 リンクリストなどコレクション操作でメモリ不足が起きた場合、のエラー処理。 コレクションの追加や削除を頻繁に行うコードって、大体はもっと概念レベルが高い事をやってるので、1件の追加 レベルでエラー処理書いてたらアホな感じになる。 しかも、GUI プロセスを作ってて何か上手く動かないから特定のエラーだけを画面に表示したい、など、ことさら明確に対処したい場合です。プロセスが落ちればいいだけなら、main()の外側、の仕様がやってくれる。 古い本の情報だけど、SBリップマンによると、MS VC++と、sun、hp-ux の C++コンパイラで、例外を使う/使わないで速度性能調査したそうで、 4~6% の速度劣化があったとの事です。
スレ終了間際に現れる質問いいですかオジなんなの?w.
Pythonで言うと forのStopIterationは へっ? だし int()のValueErrorですら微妙
>>3 ヘッダーの最後の行の #endif みたいなものだよ
…(いくら5chとは言え、複数の人が集まる場所で、何かを教えて頂いてもお礼も言えず、面白い返しもできない人がいたとして。その人がプログラムに関してだけは素晴らしいコードを書ける、なんてことはあるのかな?と思う瞬間が人生の中であったり、なかったり)
(今日の昼飯はセブンのサバ塩焼弁当にしとくか・・・)
コードにはある程度そいつの人間性は反映されるな スレチな話題ではあるけど
(でもPythonは使ってもいいのかな?って時々思う)
まちゅまちゅの3Dライブみた 前も思ったけどみこちとかなたそのダンス、めっちゃシンクロ率高い リズムがぴったり一緒なんだよね ダンスほんとにうまくなったよな
(まちゅまちゅの3Dライブ?・・・ちょっと気になる)
(((お前ら括弧ばっかり使ってlisperかよ?)))
コピーとムーブの挙動、というか管理難しい。。難しくない?
コピーやムーブはパターンに沿って管理できるからそんなに難しいとは感じないな。 ワイとしては参照の畳み込み (Reference collapsing) や変換の規則を毎回のように確認するんだけど全然頭に入ってこない。 参照はオブジェクトではないので逆に言えば値に対応する型が参照になることはないのだが、それはそれとして参照を含む型があり得るというのが今でも腑に落ちない。
参照しか知らんものだけど、ムーブて何か簡単に教えて 参照は実装上ただのポインタじゃん ムーブはなにがどうなるん?
>>24 考え方としては、shallow copyを二重開放リスクを避けて行うための仕組み。
右辺値という特別な一時変数のコピーで特別なコピー(ムーブコンストラクタ)を実行するようにして、クラス設計者が必要に応じてshallow copyを実装しやすくしている。
>>24 moveはRustで言う所有権の移動じゃないか
>>24 aに戻り値などの一時オブジェクトbをコピーすると通常は
aでメモリを確保
bからメモリコピー
bのデストラクタでメモリを破棄
という動作になるけど、moveの場合
aにbでメモリをポインタで持ってくる
bのインスタンスでは破棄したことにする
とすれば無駄なメモリ確保とコピーが発生せず効率が良い
標準ライブラリでのムーブは所有権 (ownership) の概念を前提として構築されているし、 慣例としてもそのようにするものではあるんだが 言語としてはムーブコンストラクタ (またはムーブ代入演算子) を呼び出すというだけで 所有権の面倒をみる機能は何もない。 (辻褄が合うようにするのはプログラマの責任。) 何が起きているのかは所有権の概念と実装レベルで分けて考えたほうがいいと思う。 どう説明していいかわからんから関連する要素を箇条書きにしたらこんな感じかな。 ・ それがコピーの文脈であるかムーブの文脈であるか区別は出来る ・ 一般的にムーブの文脈であった場合 (寿命が尽きる直前の一時オブジェクトの再利用が出来る場合) にコピーより効率が良い動作が出来る可能性がある ・ どのように効率がよくなるのかはそのクラス (のムーブコンストラクタやムーブ代入演算子) の定義次第 ・ 典型的なムーブの実装はリソース本体を指すポインタの交換によって実現される ・ ユーザーが定義を与えなかった場合のデフォルトのムーブは全てのサブオブジェクトをムーブすることになっている
で、このmove動作を定義するために、 一時オブジェクト(右辺値)に対する参照動作を関数定義できるようになっている
ムーブされるとそのポインタは変わってしまうと思うけど、そういうケースはないの?
言っている意味がよく分からないが、純粋なポインタにはムーブという概念はないよ ムーブを定義できるのはクラスに対してだけ 他の人も言っているようにムーブといっても実体は単なる関数呼び出しなので、その中でプログラマが自分の責任で必要なコードを書くことになる
質問した人じゃないけど説明ありがたいです ムーブ難しいと思ってたけどもっと早く勉強して仕事で使うべきだった (文法解析した要素をポインタいじって並べ変えるんだけど… 二重所有を防ぐのを手作業コーディングで責任を持たなければならないプログラムを作ってしまった)
ただ、右辺値参照を使うと、通常の参照や代入と使い分けるためにconstやnoexceptを厳密に指定しないといけなくなりがちだから、 その辺の総合的な理解が必要になってくるのは注意点だね constは一度付け始めるとライブラリ全部に伝染するからな・・・それを嫌って使わない派も結構いる(いた)よね
実際のコードだとポインタのムーブはunique_ptrとかにぶん投げで、自分で移動コード書くことはまずないな 自分でムーブ特殊関数の中身書くのはハンドル的なもののムーブを実現したいときくらい
とにかく unique_ptr が便利すぎるから何でもかんでも全部 unique_ptr 使うようになってしまった まあそれでいいのかもしれないが
>>33 銀の弾丸ではない
手作業コーディングで責任を持たなければならないのは変わらない
所有権管理も結局はプログラマが書く (間違いを部分的にコンパイルエラーとして検出できることはある)、 所有権って具体的に何なんだってのはクラス定義に押し込めるという風に管理のレイヤを分けることが出来るってわけ。 クラス定義をした後は具体的に何をやってるのかを忘れて 所有権というものだと思い込むことが出来るという抽象化の仕組み。
>>37 アホか
普通に考えて、そのコード(クラス)の利用者が所有権について明示的に何かしなきゃいけなかったということだろ
>>33 エスパーするけど多分その用途だとmoveは使えない。
データを共有している感じなので素直にshared ptrを使うのがいいかと。shared ptrで性能的にキツイならshared ptrを参照渡しするか。
>>40 ちょっと補足すると、戻り値をshared ptrの参照にするのはNGですな。そこは素直にRVOに期待するのが良いか。
VC++なんだけど32bitで_thiscallを関数ポインタ経由で呼ぶことってasm使わないと不可能? メンバ関数を関数ポインタ変数とすることは出来てもそこから第一引数にインスタンス入れたりしてもコンパイル時エラーになる
>>42 メンバ関数をポインタ経由で呼び出したいってことならstd::bindでできるはず
VC++ のことは知らんけどメンバ関数ポインタは関数ポインタより大きい実装になってる処理系がある。 メンバ関数ポインタを関数ポインタに変換した時点で呼び出すのに必要な情報が失われているかもしれない。
基本的には言語の規定内でやるに越したことはないので無理な型変換をしないで済ませられるように出来るものならそうしたほうがいい。 どうしてもそうできない事情がある(と質問者が認識している)ならもうちょっと詳しい状況をコードで示して欲しい。
>>43 ありがとう、逆アセ見たら完璧にthiscallになってた
メンバ関数っていうかthiscall指定したものは32bitだとecxレジスタにthisポインタが隠されていてそれ以外はstdcallと同じ
なので下みたいに第一引数にインスタンスのポインタを入れる事でecxに代入される感じになりそうだなーと思ったら無理だった
ちなみに64bitの場合はどちらもfastcallで同じだから単純に第一引数にthisポインタが隠されてるだけ
auto pFunc = CDate::addDay; // CDate addDay(int value)
CDate tomorrow = pFunc(&instance, 1);
てかググったら簡単なシミュレーション方法載せてるブログあった _fastcallで宣言して第二引数のedxを捨て駒にする事で疑似_thiscallになる つまりint(__fastcall * pFunc)(CDate*, void*, int)とすれば一応アセンブラ的な辻褄は合う事になる
質問なのですが型Tの参照を返す関数 const T& foo() の戻り値をautoのいくつかのバリエーションで受けてアドレスを見て見たのですが auto x = foo(); auto& y = foo(); const auto z = foo(); const auto& zz = foo(); const volatile auto& zzz = foo(); cout << "&original=" << &g_vec << endl; // &original = 00B013D8 (このアドレスは一例) cout << "&x=" << &x << endl; // &x = 010FF8AC // コピー(意図しないかも?) cout << "&y=" << &y << endl; // &y = 00B013D8 // 参照(OK) cout << "&z=" << &z << endl; // &z = 010FF888 // コピー(意図しないかも?) cout << "&zz=" << &zz << endl; // &zz = 00B013D8 // 参照(OK) cout << "&zzz=" << &zzz << endl; // &zzz = 1 // !!!! という行末コメントに記載の結果になったお Q1. 参照で受けたい場合は auto でなく auto& とせねばならない、で正しい? Q2. 間違えてauto で受けても動いてしまい発見し難いケースが多いと思うのですが 意図しないパフォーマンス低下になるので防ぐ対策とか無い? Q3. zzzのアドレスが1になるのは一体…… MSVC2019使用、言語の設定はC++14、
>>50 A1. 単に auto としたときに参照になることはない。 参照として受け取りたい場合は auto& にせねばならないというのは正しい。 A2. 参照かどうかで自動的に場合分けして欲しいなら decltype(auto) とすればいいが…… 参照で受けるのが正しい状況なのかどうかは状況による。 テンプレート内など自動的な場合分けが必要な場合を除いては参照は参照として明示したほうがよくない? (個人的感想です。) A3. いくつか用意されている operator<< の基本的なオーバーロードの内で bool にマッチするから。 void* もあるのだけれど C++ では任意のポインタは void* へは暗黙の型変換されないのでマッチング候補にならない。 アドレスとして解釈して欲しいなら void* へ明示的に型変換しないといけない。 ごめん。 間違いがあった。 ポインタは void* へ暗黙に変換できる。 この変換はオーバーロード解決時の候補になりうる。 ただ、 bool への変換とは優先順位に差がある。
>>51 >>52 ㌧クス、 なるほど わかりた ↓こうなったわ decltype(auto) z = foo(); const auto& zz = foo(); const volatile auto& zzz = foo(); cout << "&original=" << (void*)&g_vec << endl; // &original=010213D8 (このアドレスは一例) cout << "&z=" << (void*)&z << endl; // &z=010213D8 // 参照(OK) cout << "&zz=" << (void*)&zz << endl; // &zz=010213D8 // 参照(OK) cout << "&zzz=" << (void*)&zzz << endl; // &zzz=010213D8 // 参照(OK) cout << std::boolalpha << "&zzz=" << &zzz << endl; // &zzz=true // boolean boolへの変換は使うことは無いと思うが正体は調べてみるわ >テンプレート内など自動的な場合分けが必要な場合を除いては参照は参照として明示したほうがよくない? 非constなら考えるがこの場合foo()はconstオヌジェクトと参照を返してくるし、 これはもうdecltype(auto)一択で良いような気がが、
volatile を追加する変換は出来るが除く変換は出来ないから volatile 付きのオーバーロードを用意していない operator<< では候補から消えて bool だけが候補として残ってしまうってことになるみたいだな。 volatile が付いていない場合は void* への変換のほうが bool への変換より優先順位が高いので そっちが呼ばれる。
ラムダの参照キャプチャってconst参照に指定できないんだっけ?微妙に不便だな。
>>60 これじゃだめ?
#include <iostream>
using namespace std;
int main () {
const int a {0};
int b {0};
[&a, &b = const_cast <const int &> (b)] () {
++ a; // X
++ b; // X
} ();
return 0;
}
C++20 RangesはMicrosoftの説明がわかりやすかった
ふと今更思ったんだけど ポインターpに対して演算子*が返す*pは、 値じゃなくて参照?
#include <type_traits> #include <iostream> using namespace std; int main () { int value {0}; int *p {&value}; cout << is_reference <int>::value << '\n'; cout << is_reference <int &>::value << '\n'; cout << is_reference <decltype (value)>::value << '\n'; cout << is_reference <decltype (*p)>::value << '\n'; return 0; }
>>63 参照ってのが何を意味しているか分からんが
普通はポインターの示す場所の内容だ
>>63 ポインター p に対して *p とした場合の型は参照ではない。
たぶん
>>64 は *p が参照と言いたいつもりで書いているんだと思うけど
decltype に与えられる式の型が T 型の lvalue だった場合には T& が返されるルールなので
その式が参照でなくても参照が返されることがある。
あ、ごめん。 完全に間違った説明してたわ。 忘れて……。 恥ずかしい。
と思ってよく仕様を読んでみたらやっぱりこの (
>>66 ) 考え方で正しいはず。
式が識別子式の時に限っては decltype は参照にならず式の型そのままで返すせいで decltype(value) は参照にならないが、
value と *p は型システム的にも値カテゴリ的にも同じだわ。
巷のスマートポインタはoperator*で参照型を返すので 生ポインタも同じかと思ってたよ
互換性の都合とかがあるから仕方ないね。 場合分けが大量にあって単純な一般原則の組み合わせにはなってないから仕様を読み解くのがしんどい……
ある構造体Aがあります Aの比較関数が複数ありますcompA0,compA1,compA2,... 比較関数の関数ポインタがありますcompA compA = &compA2; 別の構造体Bがあります BはAを内包しています struct B{ A a; ... }; この構造体Bを、Aの比較関数ポインタcompAで比較してソートするにはどう記述すればよいですか? std::vector<B> bs; bs.push_back(...);... std::sort(bs.begin(),bs.end(),?); できればラムダ式を使わずにできるとありがたいです
>>72 ラムダ式使った方が良いと思うけど本当にラムダ式なしが良い?
使われると、ラムダ式の質問をすることになると思います・・・
>>72 もし C++20 を使えるなら (std::sort と違って) std::ranges::sort では比較関数とは別に
比較すべき要素を取り出す操作をプロジェクションとして与えることが出来るから
これ一発でいけてだいぶん楽できる。
std::ranges::sort(bs, compA, &B::a);
>>74 思い出すのがしんどくなってきた
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;
struct A {int value_;};
bool compA2 (const A &lhs, const A &rhs) {
return lhs.value_ < rhs.value_;
}
struct B {A a;};
int main () {
vector <B> bs;
bool (*compA) (const A &, const A &) {compA2};
sort (bs.begin(), bs.end(), bind (compA, bind (mem_fn (&B::a), placeholders::_1), bind (mem_fn (&B::a), placeholders::_2)));
sort (bs.begin(), bs.end(), [compA] (const auto &lhs, const auto &rhs) {return (*compA) (lhs.a, rhs.a);});
return 0;
}
>>75 >>77 お二方、ありがとうございます
参考にして組んでみます
その場で合成するのはさすがに見通しが悪すぎるので、 C++11 頃の C++ を仮定して私がやるならまずアダプタを作ると思う。 ちょっと雑ですまんがとりあえずこんな感じ。 class compB_adaptor { private: using comparator = std::function<bool(const A&, const A&)>; comparator compA; public: compB_adaptor(comparator comp) : compA(comp) {} bool operator()(const B& x, const B& y) { return compA(x.a, y.a); } }; 使うときには間にひとつ挟むだけで済む。 std::sort(bs.begin(), bs.end(), compB_adaptor(compA));
>>79 求めていたものそのものであったため、採用させていただきました
ありがとうございます
int x; std::cout << x; でxが正ののときは「+」符号を付けさせるのってどうするんでしたっけ…… cout.form("%+d", x)とか以外で
てきました㌧クス、 iosヘッダで探せば良かったのか、、、
C++23だとこれ std::print("{:+}", x);
PythonやC#のようなf"{x}"構文が作られる事はないんだろうか
>>85 リフレクションが充実すればその上に実装できるので
直接的な言語機能として用意すると
辻褄合わせが後で面倒になるだろうし、
現時点で考えるのは時期尚早だと思う。
質問なのですが自作クラスFooのストリーム出力演算子に引数付きのマニピュレータを追加したいのですが ↓こんなやつ Foo obj; cout << custom_setw(10) << obj; // 整数のベクトル的なオブジェクトobjの要素を幅10文字で出力 custom_setw()で与えた10という数値をつつがなくFooのストリーム出力演算子 std::ostream& operator<<(std::ostream& os, const Foo& obj) に渡すには一体どうすれば……orz
グローバル変数渡しは最初に思いつくのですが、ostringstream os1, os2とFoo obj1, obj2に対して異なるスレッドで os1 << custom_setw(30) << obj1; // スレッド1 os2 << custom_setw(20) << obj2; // スレッド2 とかやったら詰むし std::setw()とか一体どうやってるんじゃ……
>>87-88 特定の型を出力するときにだけ作用する書式を設定するマニピュレータってこと?
std::setw がやってるのはストリームのメンバ関数 width を呼ぶのと同じ。
ストリームのオブジェクトが幅に関する情報を保存するデータメンバを持っていて、それを変更してる。
もちろんあなたが定義した独自の型 (この例では Foo) に結び付いた書式を保持するところなんて存在しないから単純にはできない。
私が思いつくのは
・ ストリームのほうも新しいものを定義する、つまり basic_ostream を継承して Foo 用の書式を格納するデータメンバを増やす
・ ストリームに対応付いたデータを格納するものを std::map かなんかで保持しておいて Foo を出力するときはそれを参照する
ということくらいかな。
スレッドが絡むと面倒くさいけど、しょうがないね。
既存のcoutとかstringstreamとかで使いたいなら、グローバルのstd::unordered_map<std::ios_base*, MyManipData>にでも置いとくしかないだろうね ストリームオブジェクトの状態で持たせるクソ設計が悪いんだ
レス㌧クス、 >ストリームのオブジェクトが幅に関する情報を保存するデータメンバを持っていて、それを変更してる。 なるほど…… これはユザーの立場からはメンバの追加ができない領域なので、Fooの側にメンバを持たせることにしますか…… class FooWrp { const Foo& m_objRef; int m_nWidth; public: FooWrp(const Foo& obj, int width) : m_objRef(obj), m_nWidh(width) { } friend std::ostream& operator<<(std::ostream& os, const FooWrp& wrp) { ...(wrp.m_objRefの要素をwrp.m_nWidthに描かれている幅で出力する処理)... } };
// 使い方 Foo obj; cout << FooWrp(obj, 10); ダッサwwwwwwwwwwwwwwwwwww しかし、「たかが表示の整形」のために排他制御しつつmapを弄ったりTLSの利用を考えるのもアレなのでこれはこれで仕方が無いのか、orz
ストリーム用の演算子なんか作らずに オブジェクトの文字列表現を返す関数を用意したほうが汎用性高くない?
Foo obj; std::string s = obj.str(10); // 10億ギガ文字 cout << s; 出力を完遂できるんかこれ……
C++20 からは std::formatter を特殊化して書式指定を解釈するコードを入れておけば std::format で独自の型を表示しようとしたときにその特殊化が使われる仕組みになってる。
オブジェクトの文字列表現が10億ギガ文字もあるの!? FooWrpオブジェクトをうっかりログに出力しちゃったら大変だね!!
実験せずに質問するますが、 int a, b; cin >> &x >> &y; に対し、 Q1. 「100 a」を入力したら例外もタイムアウト待ちも発生せず、cin.fail()がtrueになるだけ? Q2. 「100」とだけ入力してそのまんま(リダイレクト元のファイルハンドルか何かが タイムアウトもエラーもクローズもしなければ)ならそれっきり返ってこない?
EOFが抜けてたorz Q2のケースにおいて「100 [EOF]」なら(多分)cin.fail()でとりあえずすぐ返ってくるのかそうか、
>>97 実にしょうもない確認なんだけど、
言いたいことは
int x, y;
cin >> x >> y;
でよいんだよね?
>>99 >int x, y;
>cin >> x >> y;
おk
スマンカッタorz
エラーとEOFのどちらかを検知したかったら!cin.good()が正しいっぽい?
https://blog.emattsan.org/entry/20110819/1313743195 ここまでは分かった気がするが、
ストリーム入力演算子std::istream& operator>>(std::istream& os, Foo& obj)の中で入力に失敗した場合
どうやってエラーを呼び出し元に通知したらええんじゃ……
クラスFooの入力ストリーム演算子の中で整数を2個読むとして、 std::istream& operator>>(std::istream& os, Foo& obj) { int x, y; os >> x >> y; if (!os.goot()) { return os; // エラー発生時は単純にreturn os; でおk? } obj.m_x = x; obj.m_y = y; return os; }
>>100 ストリームのフラグを立てるメンバ関数は setstate だけど
>>101 の状況ならフラグはもう立ってるから戻るだけで問題ないよ。
わかりた ていうかエラー判定(eofbit以外のビットのセットを判定)なら!os.good()や!os.goot()ではなくて os.failed()か!osですたね……orz これらに関して追加の質問が出たら初心者スレに書くわサーセン;;;
class A{ char buf_[size]; } このbuf_に任意のオブジェクトをplacement newして使用するのだけど このオブジェクトをコピーしたりムーブする場合、単純にコピー元のbuf_からコピー先のbuf_にmemcopyしてしまって大丈夫ですか?
POD は削除された。 trivially copyable の要件を満たすならその型は memcpy でコピーしてもよい。 std::is_trivially_copyable で判定できるのでどこかに制約を入れておけば安心かもね。
削除されたんですか?(バージョンいくつで?) c++20 で非推奨になった、てのはすぐ調べられたんだけどその先が分からんです
>>109 規格の文面としては C++20 で POD はもう削除されていて POD の概念を使わない形で再編されてる。
std::is_pod はまだある (非推奨) からこれが POD の定義だという意味ではまだあるとも言えるけど。
>>104 まず自分でコード書いてみ
よろしくないところは指摘してやるから
POD が削除されたかどうかは重要ではなくて、 POD より弱い制約 (trivially copyable) で memcpy が許されるというのが主旨。 その点は C++11 からそうなってる。
「構造体」ってのも C++ 用語的にはイケてないと思うよ。
アライメントは基本型のどれかと同じアライメント制約に合わせれば良いいということなら 使おうとしているうちで最も厳しいアライメント制約に一致する基本型を含むunionで解決するというのがC言語における伝統的な手法という印象、 C++でunionにしたら(それが可能なメンバのみなら) memcpyは安全とかにはならない?
>>116 コンストラクタや代入演算子がトリビアルであることなどの制約を守れば共用体も trivially copyable になりうる。
(C++ の共用体はコンストラクタやメンバ関数を定義できるがそこらが制限されることになる。)
>>112 とりあえず書いてみたけどどうですかね?
template<std::size_t buf_size>
struct A {
private:
struct base_ {
virtual ~base_() {};
};
template <typename F>
struct derived_ : base_ {
F f_;
derived_(F f) : f_{ std::move(f) } {}
};
base_* p_;
alignas(alignof(std::max_align_t)) uint8_t buf[buf_size]={0};
public:
A() :p_(nullptr) {};
template <typename F>
void assign(F f) {
if (p_ == nullptr) {
p_ = ::new (buf) derived_<F>{std::move(f)};
}
}
//コピーコンストラクタ
A(A& src) {
p_ = ::new (buf) decltype(src.*p_); //ここが怪しい
};
};
decltype(src.*p_)ってbase_なのでダメだろう
ていうか、decltypeで型指定してるだけだからコピーもなにもされてないぞソレ
A::base_に以下を足してA::derived_で実装し Aのコピーコンストラクタから呼べば? virtual base_ *clone (void *p) = 0;
void*って、ポインターの先のサイズ未知だよなぁ
derived_かそのメンバf_の型を知るにはRTTIしかないのですかね?
>>121 decltypeだと派生先の型はわからないのか
>>122 実体のコピーの処理が抜けてました…
>>124 こんな感じです?
struct base_ {
virtual base_* clone (void *p) = 0;
virtual ~base_() {};
};
template <typename F>
struct derived_ : base_ {
F f_;
derived_(F f) : f_{ std::move(f) } {}
base_* clone (void *p_buf){
return new(reinterpret_cast<derived_<F>*>(p_buf))(f_);
}
};
A(A& src) {
p_ = src.clone((void*)buf);
};
derived_(F f) ←この時点でムダなコピーが1度発生していることには気付いてる?
バッファの中にオブジェクトを作れたら、それで何をしたいのかが気になる
>>127 cloneの中ってplacement newでcopy constructorを呼ぼうとしてるんだよな?
いちおうあってるけどundefined behaviorまみれ
たぶんやりたいことは std::allocator_traits::construct なのかな
例外って全部mainで捕捉すべきかな?
調べてみたら例外が捕捉されずにプログラムが終了する場合スタックアンワインドが起こるかは実装定義みたいなんだけど、それじゃグローバルなオブジェクトのデストラクタが呼ばれないんじゃないかって思って試してみたのよ。
https://ideone.com/wSLZfL やっぱりデストラクタは呼ばれなかったからリソースリークが起こりうるんじゃないかと思うんだけど、例外に対してはどういう態度でいるべきかな?
A. リソースリークはまずい。だから例外は全部捕捉するべき。
B. 例外はロジック上捕捉する必要があるものだけ捕捉して、それ以外はほっといていい。
C. 例外が捕捉されなければstd::abortが呼ばれるので、コアダンプなりで色々調べることもできる。だからmainで例外を全部握りつぶすようなことはすべきではない。
D. 時と場合による。
例外時の挙動とか仕様とか調べてるうちに頭ぐるぐるしてわけわかんなくなってきた
そもそもプログラムが終了してリソースリークするのかな? メモリー、ファイルハンドル、ソケット、ミューテックスなどのリソースはOSが責任持って解放するよね どのようなリソースがリークしますか?
>>133 すべてじゃね?
それらの選択肢は別に排他的な選択肢じゃないかと
OS管理なリソースはアプリの終了なんか知らないってのもあるからなぁ 得にドライバ関連とかな
>>136 あれ、少なくともAとCは排他的だと思うんだけど
全部の選択肢を選ぶとすると具体的にはどうなるのかな
今どきのOS使ってたらOSリソースはリークしない まぁプロセスがゾンビになるのはよくあるが
そもそもアプリ的にデータの不整合とか出るから論外だろう ファイルやなんかの外部データ使わないなら関係ないだろうけど
よくあるのは異常終了時にファイルをフラッシュしておきたいとかだろ 汎用的にこれを実現するのは結構むずい
あとコアダンプの観点では例外飛ばさずに即死したほうがいい
エラーだからって一時ファイル山盛り残して放置しないでください
質問した者だけど 確かに近代的なOSであればリソースの始末はよしなにやってくれるだろうし、「絶対にデストラクタが呼ばれなきゃ困る」って状況でもなければいちいちすべての例外を捕捉する必要はないのかな(毎回ボイラープレートコードみたいに書くのもやだし)
例外処理って、メモリ破壊やファイルシステム破壊みたいな絶望的な状況を想定しなきゃいけないんだよ。 ファイルに何か書き込んだら他のファイルを壊しちゃうかもしれない、みたいな。 だからファイル関連の操作をしていいのは、ファイルシステム周りの無事を確信できるときだけ。 データを上書き保存とかしていいのは、データとファイルシステム両方の無事を確信できるときだけ。 何も確信できないときは、何もせずに墜ちなきゃいけない。 ってことで例外機構はデフォルトで何もせずに異常終了するようになってるんだよ。
理想的には全ての例外はキャッチされるべき。 ただ、現実は理想的ではない。 キャッチするのは対処するためなので想定漏れで思ってもなかったような例外が上がってきた (対処が出来てない) ならそれはバグなんだから検証して修正する必要があるわけだし、検証しやすい形で止まったほうがいい。 C++ ではスタックの巻き戻しの途中で例外を送出したときの挙動は未定義なので通例ではデストラクタから例外を投げないように設計される。 つまりデストラクタでの後始末に失敗したらもうそれを (例外機構の仕組みでは) フォローできない。 想定されてない例外が上がってるときに後始末がちゃんとできずにわけのわからない動作を引き起こしたら検証にも支障がある。
じゃあ「投げられうるすべての例外に適切な対処ができるのが理想的だが、対処しきれない例外は投げられっぱなしにする(そしてプログラムを即座に異常終了させる)方が、思考停止でとりあえず捕捉しておくよりはまだマシ」ってことになるのかな みんなありがとう
いやいや、ちゃんとデバッグしろよ こんなやつとは絶対一緒に仕事したくない
ライブラリ書くときはライブラリで対処できない例外は握り潰さずに上位で伝搬させろ!と言われてるよね アプリも同じだと思う 明確に対処すべきことがあるなら例外をキャッチすればいいし ないならそのままプロセス落としてOSに任せればいいんでない?
投げられっぱなしにするって言い方が不適切だったかな、別に例外のせいでプログラムが実際に異常終了するのを見ても知らんぷりするって意味じゃないよ 実際にプログラムが異常終了したんだったらその都度原因は突き止めて修正するし、そもそもすべての例外に網羅的に対処するのが現実的なときは最初からそうするよ
想定される状況には対処しているならどこで想定漏れがあるかはやってみないとわからない。 経験を蓄積し続けるしかしょうがないんだよな。 蓄積がテストケースの形などになっているとより良いと思う。
自分の知らないライブラリの奥底からいつ投げられるかわからない例外なんて対処しようがない かつスタックアンワインドしたらデバッグの手がかり消えるだけ
やっぱC++の例外は悪…… 構造化例外ならwindbgでコアダンプを開いて!analyze -vで発生源を調べられる(仕組みは知らん がC++の例外は例外オブジェクトが持ち出した情報が全て…… という印象……
やっぱ例外というブツは、
アプリケーション領域においてプログラミがいろんなリソースを取り扱うようになった結果、
C言語流に関数の戻り値で起こり得る全てのエラーを網羅してチェックする方法が
現実的でなくなってきたから設けられたブツなので
>自分の知らないライブラリの奥底からいつ投げられるかわからない例外(
>>154 すなわち設計に対して想定外の事象が起きた知らせとしてが飛んでくるというのが基本的かつ本来的な姿
起こりえる全ての例外の処置を書かなければ設計とは言えない主義の人(
>>149 )は
寧ろ例外の使用をやめてC言語的な書き方で全てのエラーをチェックすべき
(他人様が作ったライブラリが例外を飛ばしてくるのは仕方が無いから全てcatchする
つなみにOSの内部ではすべてのリソースをOSが管理する前提なので例外の出る幕は無い OSの設計に対して想定外の事象がOS内部で起きるとかあり得ないじゃない レトロな(しかしメジャーな)OSがC++ではなくC言語で書かれ続けるのはそういう理由
何が返ってくるかわからん (ドキュメント化されていない) なら返却値の形になっていても正しく対処できないのは同じだろ。
例外だとテストしないドキュメントにも書かないというモラルハザードがおきやすいとは言えるだろう 返り値はエラー体系を自分で定義しないといかんからそうはなりにくい まぁそれでも失敗を安易にfalseに丸めるどアホは多いけど
>>157 >すなわち設計に対して想定外の事象が起きた知らせとしてが飛んでくるというのが基本的かつ本来的な姿
それ一般にはリリース後に起きちゃいけないことでは。プロダクトにもよるが防ぐ努力は必要だと思うがね。
>>138 全選択肢を同時に選ぶって意味に捉えられちゃったかな?
そうじゃなくて、その選択肢自体が同時に適用すべきレベルのものじゃないと思うの
例外をキャッチするって決めたなら、そこには目的があるよね?
設計手順としては目的を決めてから例外を使おうって判断になるわけ
その目的次第だよね?っていうのがD
目的がリソースリーク防止ならA
Aのような目的を達成するために、目的範囲内でB
デバッグ目的ならC
製品等で客の目に見せたくないなどの営業目的があるならCはダメで、のべつまくなしBというのもあるかもしれない
大きな目で全工程トータルを考えると全部の選択肢を適用する必要があるし、適用のしどころが違うと思うってのが
>>136 の真意でした
>>148 これが正しいかどうかはおいといて、人命に関わらないなら、自分はその考え方に賛成!
完璧にデバッグしろというのは自動車と医療機器など人命にかかわるものだね
重要度に応じて工数のかけ方が変わってくるので、すべてのソフトウエアで一概にこうしなさいとは言えないかな
そういう意味ではD
>>162 ああ、なるほどね
分かりやすくありがとう、助かりました
人命にかかわらない場合であっても、末端の関数が投げる例外の種類を見落としただけでプログラム全体が いきなり落ちるのは勘弁してほしいし、それを防ぐために全部の関数が投げる例外の種類を全部把握するというのも 無理ゲーに近い。 なので適当なレイヤーごとにざっくり std::exception をキャッチする造りにしてるな。例外の種類で選択したりはしない。
何するか思い付かないならPG辞めろ 貴様には向いてない
>>167 そのtryブロックの処理が失敗したものとして処理を続ける。
んでテストケース爆増の話は?処理の具体例次第で話が変わったりするとか?
依存関係のあるものに影響あるのは当たり前 原因不明の例外起こっても突き進むんだったら擬似的にそのケース作ってテストするわな普通は 出し渋るなら別にださなくていいよ 参考にならなさそうだし
それはいったい何のテストなんだろう。原因不明の例外を首尾よくキャッチできるかどうかテストしろと言っているんだろうか。 そもそもそういう例外を想定するなら、スルーして影響範囲が広がる方がテストは厄介になると思うがなあ。
たとえば業務用のラベルプリンターでAPIが提供されてるとか とりあえず try ~ catch して「印刷中に不明なエラーが発生しました」みたいなまとめかたはあるかなー
すみません。質問させて下さい。次のコードがMinGW-w64 g++ v13.2では --itrでエラーになります。わからないのはVisual studio 2022およびVisual StudioがサポートするClang LLVMでは通って正しく 実行しているように見えます。--itrの仕様がないのはMinGW-w64 g++v13.2が正しいのでしょうか?それともVisual Studioが正しいのでしょうか? #include <iostream> #include <unordered_set> using namespace std; int main() { unordered_set<int> us = { 1,2,3,4,5,6 }; for(auto itr = begin(us); itr != end(us); ++itr) cout << *itr << endl; auto itr = us.begin(); ++itr; ++itr; cout << *itr << endl; --itr; cout << *itr << endl; cin.get(); return 0; } MinGW-w64 g++ v13.2のエラー // error: no match for 'operator--' (operand type is 'std::__detail::_Node_iterator<int, true, false>')
>>177 unordered_set は forward iterator をサポートしているという規定がある。
https://timsong-cpp.github.io/cppwp/n3337/unord.set.overview#1 forward iterator は進めることは出来ても戻ることはできない。
この場合は operator-- がないのが正しい。
拡張してより高機能なライブラリを提供しても仕様に反するってわけではないけど
マイクロソフトのドキュメントでも特に拡張しているという文面は見当たらないから
あんまりあてにしないほうが良さそうには思う。
https://learn.microsoft.com/en-us/cpp/standard-library/unordered-set-class?view=msvc-170#iterator >>173 横やが関数foo()で1つの例外が発生したらその時点のfoo()呼び出しに至る10個かそこらの関数が中断されるわけや すなわち関数bar()が 処理A→B→C→D→return の順で処理が進むことを気体しているところに、Bで呼び出している関数baz()がfoo()を呼び出している結果、foo()で例外を生じると 処理A→B→return という処理順に変更になる。こうなっても大丈夫なようにtry { 処理B } catch ((fooが投げる例外)& e) { (eに対する適切な処置) } を書かねばならず、 これが実は潜在的には処理A、B、C、Dのどこでも起き得るから厳密なことを言えば全てについて書かねばならず、 それがfoo()呼び出しに至る10個かそこらの関数それぞれについて行われねばならない。 検証もそんだけ組み合わせが増える。 というわけでそんなの現実には不可能なので、現実的な処置としては ・ライブラリ製作者はなんか都合が悪い事が起きたら何でも呼び出し元に返す。 第1選択としてはエラーステータスを返すことを検討し、それではコードが煩雑になりすぎる場合は例外を投げて異常を知らせる ・ライブラリを使う人はライブラリが例外を投げない条件で使うことを心掛け、自前のコード内でtry { } catch() { }を極力しない という処置になるわ けや
catchしようがしまいが、例外が起きて 処理A→B→return となるのは同じだと思うが。 その場合の検証が必要だというならどっちも必要だろ。
>>182 >catchしようがしまいが、例外が起きて 処理A→B→return となるのは同じだと思うが。 それは問題の認識がおかいし 例えば以下のコードにおいて、スレッドのゾンビを生じさせないためにはfuncB()をtry { } catch () { } は必須になる。 void bar() { funcA(); // スレッドxを起動 funcB(); // 中でbaz() → foo()の呼び出し funcC(); // スレッドxに停止シグナル発酵 funcD(); // スレッドxの終了待ち return; } このように一般に例外が飛んでくる関数にはcatchするかしないかの選択権など無い 例外安全なオブジェクト「だけ」で事が済んでいない限り、例外を受けると決めた時点でcatchせねばならない 一方、例外を生じないライブラリの使い方(関数の呼び出し方)を心掛けるかどうか。これなら選択肢がある 訂正orz 誤:例外安全なオブジェクト「だけ」で事が済んでいない限り、例外を受けると決めた時点でcatchせねばならない 正:例外安全なオブジェクト「だけ」で事が済んでいない限り、例外が飛んでくる想定であるならばcatchせねばならない
>>183 それはfuncB()に失敗の可能性がある時に必ず必要な話だろ?例外どうこうじゃないじゃん
funcB()が例外を投げずに古き良きintのエラーコードを戻り値で返す場合は何かが変わるの?
まさか「funcBの戻り値をガン無視すればfuncCもfuncDも実行されてくれるから完璧!だから例外はクソ!」っていうゴミカスみたいな主張をしたいわけじゃないよね?
>>183 それはcatchが必要かどうかの話だろ。
catchしたらテストケースが増えるかどうかという話とはなんも関係がない。
そもそも未知の例外飛んできた時点でそれを通したライブラリの例外安全性が守られてるか怪しいと考えるべき
例外安全性を守るのに例外の種類やそれが既知か未知かは関係ないだろうが、 仕様に明記した例外以外は堰き止めるのが正解だろうなあ。
思い立って結城さんのデザパタ(古いjava で記述)を総称型(テンプレート)もちゃんと使ってC++ に書き直しているけれども、
new/delete からptr::shared_ptr に書きなおすと、もう構造がわかりにくくなってしまってどうしようもない
デザパタ=抽象クラスプログラミングは C++ ではオワコンなの?
Visitor パターン
new/delete:
https://ideone.com/6d43LO スッキリ書けてきもちいい
std::shared_ptr:
https://ideone.com/oYzkxh 恐ろしい宣言の連発
>std::shared_ptr<Iterator<std::shared_ptr<Entry>>> iterator() { return std::make_shared<VectorIterator<std::shared_ptr<Entry>>>(v); }
なんかもう書いてても意味不明
CONSTRUCTOR(CONSTRUCTOR *p) とかコピコン以外にもみたことのないコンストラクタが要求されるし
>>189 スマートポインタを使わないバージョンも C++ 的にはすっきりしてない。
動的多態の必要が必要ないのに持つべきメンバ関数を強制するためだけに抽象クラスを使っていて不恰好に見える。
コンセプトの導入がだいぶん後回しになった C++ の問題でもあるんだが……。
設計理念が妥当かどうかはともかくとして、元が Java なら直訳めいた C++ への置き換えがすっきりと書けるはずがない。
ざっと見た感じだと抽象クラスとして必要なのは Entry だけかな。 ジェネリックラムダが visitor パターンで使いやすいのでそういうのが使いやすいように配慮するといいかも。 std::visit が C++ での visitor パターンのお手本だよ。
>>189 usingなりtypedefでエイリアス作れば?
using Entry_Ptr = std::shared_ptr<Entry>;
面白そうだからちょっと書いてみた。大きな変更点はこんな感じ。
・accept が受け取るのは単に Visitor の参照でいい。ここで shared_ptr を使う必要はない。
・Visitor が受け取るのも File や Directory の参照でいい。
・SizeVisitor もいらない。File と Directory はともに Entry の子クラスとして getSize() を実装してるんだから、無理に visitor パターンを使わなくても単に getSize() を呼べばいいだけ。
・iterator() が返すのも VectorIterator の shared_ptr ではなく、単に VectorIterator を返せばいい。
全体的に使う必要がない場面で shared_ptr を使ってるのが目立ったと思う。
https://wandbox.org/permlink/ZBKbF5iMVpb7Looi だいぶすっきりしたんじゃない?
なんかもうポインタをいじるのが面倒になったので値としてやりとりしていいやという気持ちと
標準ライブラリを積極的に活用することにしたらこうなった。
https://wandbox.org/permlink/BQCNjfdJRKWAR3dg >>193 拝読させていただきました。なるほど、関係性を示すポインタ=参照なら std::shared_ptr でくるむ必要ガない、というわけですか。
>>194 拝読させていただきました。Entry を値で持つのはいやだなあ。 dectype の使い方を学ばせていただきました。
>>194 std::size_t()
あたりから読めていません。operator() をどう使っているのでしょうか?
スマートポインタを使うにしても std::shared_ptr って必要?
この場合は std::unique_ptr でよくない?
https://wandbox.org/permlink/dMolraFpQHKzYtF3 設計思想によるけどファイルシステムを表現するという前提だと
ひとつのルートディレクトリに連なる全てのエントリは実質的に一体のデータ構造なので
ルートディレクトリエントリの寿命が尽きれば全て解体ってことにしたほうが簡単でいいと思う。
ハードリンクの表現とかも考えるなら事情が変わってくることもあるだろうけど……。
>>189 c++
https://ideone.com/p3li2Y ・
https://ideone.com/oYzkxh を元に若干の整理を行った
・他の人と同様shared_ptrを削除
値で持てるところは単に値で持つほうがC++っぽいと思う
ただ「Entry を値で持つのはいやだなあ」とのことなので部分的に残してる
Javaの参照型変数をshared_ptrに置き換えようとして困るのは
size_t File::accept(std::shared_ptr<Visitor> v) { return v->visit(std::make_shared<File>(this)); }
ここがJavaだと単にvisit(this)で済むからスッキリするんだけど
しかもこれmake_shared(this)だと多重開放するよね??
>>189 c++
https://ideone.com/2uUpwH ・
https://ideone.com/p3li2Y を元に若干の整理を行った
・make_shared<File>(this)の多重開放?を修正
std::enable_shared_from_thisを使ってJavaの参照型変数っぽい使用感を得た。
・struct this_is_private {};
これは単にコンストラクタを実質的にprivateにするためだけに使ってる
https://en.cppreference.com/w/cpp/memory/enable_shared_from_this https://stackoverflow.com/questions/8147027/how-do-i-call-stdmake-shared-on-a-class-with-only-protected-or-private-const このへん参照されたし
https://wandbox.org/permlink/LEl2MT7OdGIlVKC4 なんか「子クラスのコンストラクタに親クラスのオブジェクトを渡して子クラスのメンバを初期化する」(?)みたいなことができちゃってるんだけど、これってどういう仕様でこうなってんの?
Wandbox上だとC++2aではコンパイルできてC++17ではコンパイルできなかったからcpprefjpのC++20の機能の一覧も見てみたけどそれらしいものはなかったし
>>199 designated initializer も C++20 からの機能なんだけど……それは脇に置く。
この場合は集成体初期化に該当する。
C++17 から基底の初期化も集成体初期化で扱えるので
child c{p};
というように初期化出来ていた。
更に C++20 では集成体初期化を丸括弧で書いても良いことになったので
child c(p);
とすることが許されるようになった。
>>198 >size_t File::accept(std::shared_ptr<Visitor> v) { return v->visit(std::make_shared<File>(this)); }
> ここがJavaだと単にvisit(this)で済むからスッキリするんだけど
> しかもこれmake_shared(this)だと多重開放するよね??
多重解放(二重解放)しないことはラッパをかませて確認済みです。そう簡単に std::shared_ptr は破綻しないと信じています
https://ideone.com/GUPcSu それはともかく、皆様のご意見には感謝しております。これからもお伺いさせていただいた際にはよろしくお願いいたします。
>>200 https://cpprefjp.github.io/lang/cpp17/extension_to_aggregate_initialization.html これかあ
実は「childにコンストラクタがある場合」とか「childにprivateメンバがある場合」とか「childがparentをprivate継承している場合」とかはコンパイルが通らなくてもう意味が解らなかったんだけど、それもchildが集成体じゃなくなってたからだったんだね
ありがとう、勉強になった
>>198 >値で持てるところは単に値で持つほうがC++っぽいと思う
時代の流れを感じさせるお言葉です。なにせ K&R1 で育った世代なので(K&R1 では構造体の実体渡しはできず、かならずポインタで渡さなければならなかった)。
C++ においても、コピコンを働かせないために const & を多用する毎日です
>>203 内部的に値で持つのでもポインタで持つのでもいいけど
「簡単に値として取り出せる」のはあまりよろしくないと思う。
これ (
>>189 ) がおそらくファイルシステムを表現しようとするもの
だという前提を考えたらオブジェクトの構造も
ファイルシステムのモデルを抽象するものであるべきだと思うから。
ファイルはそれがある場所にも意味があるからファイルを象徴するオブジェクトが
場所から離れてやりとりされるのは違和感がある。
まあファイルシステムのモデルをどう捉えるかは私の感想でしかないから
何が妥当とは強くは主張しないけど、
いずれにしても実装上の都合じゃなくて使う側の感覚でどうなってて欲しいかという視点が要ると思う。
はちみつさん頭いいね アドバイスが丁寧かつ的確でいつも感心する
ある構造体(集成体)Aについてconstexprでa1, a2, a3・・・といくつか作りました 別のクラスBのメンバ変数にconst A* m_ptrAがあってconstexprで作ったインスタンスのどれかを指すことにします この時Bのメンバ関数などで、 if(m_ptrA== &a1) という比較・条件分岐を行うのは意味のある比較になっているのでしょうか?
意味はある でもなるべくそういう判定は無しでいけるように設計したいところだよな Aクラスを作ってる意義が薄れる あと細かいこと言えばaddressofを使ったほうが汎用的というのはある c++のクソっぷりが如実に表れている関数
ありがとうございました 本当に列挙型代わりに使えるのなら面白いとも思いましたが まあ変なコードには間違いないですね
分岐の内容次第ではあるけど……Bが指しているAのオブジェクトごとに処理を切り替えるってのなら a1, a2, a3 …… がそれぞれ関数 (関数オブジェクト) を指す (所有する) ようにするのが常道ではあるね。 Bのメンバ関数の中では呼び出しを一文書くだけでいい。 分岐条件を網羅しそこなうしょうもないミスはよくあることだから 手作業での網羅を避けられるならそのほうがいい。
「The C Standard says that array indexes are (signed) integers. The reason behind that is that pointers and arrays are close in C. For example, tab[index] is strictly equivalent to *(tab + index). You can use pointer arithmetic with negative values, hence an array index can be negative」 とあるので、C 言語での配列添え字は符号付き整数 ですね。 しかし、C++ では、size_t とされ、符合なし整数 のようですが、矛盾しませんか? VC++の以下のマクロでは、 #define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] eが偽の時にエラーになるようになっているようです。 これはつまり、 typedef char aaa[-1]; がエラーになる事を前提にしているようです。 しかし、もし、配列の最大要素数が、符合なし整数 であるならば、32BIT 環境の場合、 -1 は、0xffff_ffff と同じと言えば同じであるはずで、 コンパイラ内部で効率よく区別するのは難しいはずです。 どうしてるんでしょう。
何がいいたいかと言えば、32BIT環境だと 符号付き整数の最大値は、 0x7fff_ffff ですから、 char a[0x7fff_ffff]; は合法ですが、 char a[0xffff_ffff]; はエラーです。よって、 char a[-1]; はコンパイラは難しい処理をしなくても、 -1 は内部表現が 0xffff_ffff ですので そもそも範囲外の数値と見なせます。 ところが、もし、配列最大数が unsigned の領域まで許されるならば、要素数が 0xffff_ffff の配列も合法だということに なります。 ならば、要素数の[] の中に-1 を指定した 場合の処理は難しくなりそうだ、ということです。 なおそもそも、32BIT の Windows 環境 だと、ユーザーが使えるアドレス空間は 最大で 0x7fff_ffff 程度までですから、 バイト数的に確保は出来ませんが。 ならば、そもそも、C++がunsigned 型 であるところの、size_t を採用しているもの なかなか不可思議であります。
長いからよく読んでないけどコンパイラは型を認識をしてんだから-1と0xFFFFFFFFは区別してるだろ
C++の配列添字はstd::ptrdiff_t(符号付き)です
配列を宣言するときの構文と添字演算子を使うときの構文を混同してない?前者はブラケットの中身が正じゃなきゃだめで後者は負でもいいってだけの話だと思うんだけど int main() { int hoge[-1]; // ここで負の値を指定することはできない hoge[-1]; // でもこれはいい (*((hoge)+(-1)) と解釈される) } せっかくだからC++23の仕様書も見てみたけど、§9.3.4.5の1には「配列のサイズはstd::size_t型(に変換された)定数式で、その値は0より大きくなければならない」って書いてあって、§7.6.1.2の2には添字は「スコープ無し列挙型か整数型」て書いてあったよ(該当箇所だけつまみ読みしたから正しく読めてる保証はできないけど)
>>210 C の配列宣言子の角括弧内に書ける数値は 0 より大きい値に評価される整数定数式であることが条件で、具体的な型に規定はない。
式の型がなんらかの具体的な型に強制 (型変換) されたりはしないので signed int なら signed int だし、 unsigned int なら unsigned int のままだ。
VLA のときは定数式という条件は外れるけどそれ以外の制限はだいたい同じ。
C の添字演算子の場合もそう。 型は整数であればよい。
(値は制限の範囲内である必要はある。)
どこで見た説明を根拠にしているのか知らんけど、その signed が括弧書きなのは signed 「でもよい」という意味だと思うよ。
std::functionって、有効な関数がセットがされているかどうかでブール値を返しますが、 一旦有効化した後にこれを無効化したい場合って、nullptrを代入したりしていいんでしょうか そしてその場合std::functionの中身はうまいこと解放されたりするんでしょうか 場合によってはラムダ式を使ってオブジェクトをキャプチャしていたりして あまりその辺りの説明が見当たらない感じがしました
>>212 >長いからよく読んでないけどコンパイラは型
>を認識をしてんだから-1と0xFFFFFFFFは
>区別してるだろ
char a[100-101];
みたいに結果的に -1 になった場合は、
32BITコンパイラの場合、果たして内部で
0xffff_ffff
と区別をつけているかどうか。
unsigned型と考えれば0xffff_ffffであり、
signed型と考えれば -1 です。
ターゲットが 32BIT Windows どちらもエラー
になる可能性は高いですが、理由は結構異なる
と言えば異なると思います。
もっと言えば、32BIT ターゲットで、 char a[0x80000000 | 1]; みたいな場合、中味は signed と 捉えれば「負数」ですが、unisgned と 捉えれば、0x80000001 という大きな値 に過ぎません。 どちらもエラーになる可能性が高いですが。
リテラルにも型がある 1はint 0x80000000はunsigned int 演算結果はunsigned int ルール決まってるから
x86のアセンブラのディスプレースメントは符号付いてるけどな 他のマシン系はワカランけど
>>222 32bit環境には64bit整数はないと思ってるの??
>>223 なるほど。そうなるわけですね。
本当に書いた人の意図がどうかに関わらず、
規則で決まっていると。
1UL のように書いてあれば unsigned。
そして、UL のようなものを書いてない場合、
1 のように小さな値は、signed ですが、signed の
範囲を越えるようなものは、unsigned になる、
などの規則があるわけですね。
>>185 >>183 の主張の
>一方、例外を生じないライブラリの使い方(関数の呼び出し方)を心掛けるかどうか。これなら選択肢がある
が完全に読み飛ばされている件について:
例外を生じないライブラリの使い方で設計したら、funcB()から例外が飛んでくるのはバグなので
調査と修正の対象になる。
(結果的にやっぱtry { funcB(); } catch (/*略*/) { ... } いるじゃーん?となる可能性はあるがたいていはそうはならない
>>188 のように自分が何をやっているのか認識しないまませき止めるのは論外すぐる……
>>186 >catchしたらテストケースが増えるかどうかという話とはなんも関係がない。
あっる
catchする必要性箇所を設計で厳選すればcatchが減るのだからテストケースは減らし得る
例外を使う場合:
スルーしたりcatchして再スローが生じるfoo()の呼び出し箇所(とするのが現実的でないなら呼び出しパティーン)がm個、
スルーしたりcatchして再スローする段数が(簡単のためここでは平均とする)a個、
foo()が例外を生じるパティーンがn個なら、m^a^n個のテストケースが必要なところであるが
catchする必要性箇所を設計で厳選した場合:
foo()の呼び出し箇所(とするのが現実的でないなら呼び出しパティーン)がm個だとしたら、
例外が飛んでこないことを確認するのテストケースがm個のオーダーで要るだけ……
>>228 読み飛ばしてねえよ
funcB()は処理を中断すべきエラーが発生する可能性があるんだろ?だったらそれを適切に処理して後続の処理をやったりやらなかったりする必要があるわけだろ?
それはfuncB()がエラーを例外で返そうと戻り値で返そうとなんか他の方法で返そうと何も変わらないはずじゃないか
>>229 >例外が飛んでこないことを確認するのテストケースがm個のオーダーで要るだけ……
いったい何をテストしようとしているんだろうか。
仮に「例外が飛んでこないことを確認するテスト」なるものができたとして、catchしたらそれができなくなるのか?
前半のよくわからない計算はcatch句を書いたらそのC0網羅のためのテストケースが必要になるとかいうことなんだろうか。
>>228 >
>>188 のように自分が何をやっているのか認識しないまませき止めるのは論外すぐる……
どこが論外?
>>169 でぜんぜん問題ないが。
>>232 それは未知の例外投げてきたライブラリを信用し過ぎ
製品ならそういう「たぶん大丈夫っしょw」的なのは許されないね
>>233 逆だろ。catchしないのはライブらにが未知の例外を投げてこないだろうと信用してるってことだろ。
>>234 catchしないということは終了させるということ
見かけ上動き続けたらいいってもんじゃない
>>232 それは未知の例外投げてきた原因を調査しなさすぎ
製品ならそういう「たぶん大丈夫っしょw」的なのは許されないね
>>233 ドキュメント通りに例外発生条件にならないように呼んでやったのに
例外を飛ばしてくるライブラリって一体……
製品やぞ……
質問なのですが Q1. std::ldexp(0.0, 0.0) が0.0なのですがこれは 0^0 = 0という大胆な主張なのですが何で決まっているの? STLがIEEE735に従っているだけ? Q2. 最小の(絶対値が最小の正の)非正規化数は const auto min_expn = std::numeric_limits<double>::min_exponent; const auto digits = std::numeric_limits<double>::digits; として、std::ldexp(0.5, min_expn - digits + 1) で正しい? (実際 std::ldexp(0.5, min_expn - digits + 1) > 0.0 やが std::ldexp(0.5, min_expn - digits + 1) / 2.0 == 0.0 であっる Q3.にもかかわらず、 std::ldexp(0.5, min_expn - digits) > 0.0 になるのはなんで……orz
訂正 |||。n_ 誤1: IEEE735 正1: IEEE754 誤2: 非正規化数 正2: 非正規数
>>237 決まっていない。言語仕様としては未規定。
std::numeric_limits::is_iec559 が真であるならその挙動をあてにしていいがそうでないときは各環境の事情による。
>>236 あんたの認識じゃ catchする=見かけ上動き続ける なんだ?
なんか根本的に勘違いしてる気がする。
例外は「関数外にエラー発生を伝える」ための「方法の一つ」でしかない 関数の処理がどんなエラーを発生させうるか、受け取った外側の処理がその情報をどう取り扱うべきかという問題とは完全に直交してる (言語ごとにある程度の慣例はあるけどあくまで慣例) 例外に変なこだわりや的外れな批判をしてる奴は大体そこを勘違いしてる
アンカ間違えた、すまん
>>241 は
>>235 宛な。
>>242 お前はバグのないお花畑を考えてるからそういう理想的な抽象論を持ち出すんだよ
c++の現実は道を踏み外したら即カオス
stlのコンテナのpopに返り値がない理由は知ってるか?
あのレベルの考察でソフトウェア設計している人間が世の中にどれだけいると思う?
>>241 >>169 を否定している
知らない例外が飛んできた場合にcatchして握りつぶしてそのまま動作を継続するかどうかって話な
>>244 バグのあるなしなんか関係ない設計の話だし、「例外はエラー伝達の具体的方法の一つ」って話のどこが抽象的なのかも分からないし、
「C++の現実」とか「カオス」が具体的に何のことで何の関係があるかも分からないし
STLにpopがないのはnoexcept moveがない時代に例外安全に出来なかったからだけど今の話に何の関係があるかわからないし
そんなのまともなC++erなら誰だって考えて設計してると思うけど、そうでないタコの話が何の関係あるかわからないし何もかも分からなすぎてすごい
仕事でそんなドキュメントやレビューコメント出すなよ
>>245 知らない例外を握り潰すのも、知らない戻り値をガン無視するのも一緒
errnoが変わってるのを無視するのもint*err引数に渡した変数の値を無視するのもexpected<T,E>で帰ってきたEを無視するのも「知らんエラーを無視した」という結果は一緒
知らんエラーを無視していいかどうかの意味論と、そのエラーがどう伝播して来るかかは関係ない
関係ない話を混ぜるからお前のC++はカオスなんだよ
>>245 ?
そのtryブロックの処理が失敗したものとするって書いてあるじゃん。
>>231 >前半のよくわからない計算はcatch句を書いたらそのC0網羅のためのテストケースが必要になるとかいうことなんだろうか
例外が関数の階層をぶち抜いてfall-throughしてくることを忘れている発言
1. catchが書かれた関数が正しくcatchし、適切に処理するか(処理してせき止め or/and 必要な場合再スロー)(←要テスト!
2. fall-throughする関数が例外による処理の中断でおかしいことにならないか(←要テスト!
2をテストもせずに放置するとおかしくなる例は
>>183 のとうーり
これにより、例外を生じる関数foo()の呼び出しパティーンn個それぞれに対し、a個のテストが必要になっる
例外を発生させない使い方をするなら、n*a*mではなくmの定数倍(例外を飛ばさない使い方に依存擦る定数)。
例外が飛んで来たらバグ。わかりやすい
例外を多用しつつn*a*mをよくわからない計算とか言っている時点で以下略
>>244 以下の主張のどこが抽象論なのかkwsk、 1. ライブラリのドキュメントに従い、可能な限り例外を生じない使い方で設計する(>>236 2. 例外が生じない前提としたところは例外が生じないことをテストする(m個のオーダー)(>>229 3. 1と2の過程で意図に反して飛んでくる例外がある場合は原因を調査し、修正を試みる(>>228 例外が飛んで来たらバグ 4. 3を意図通りの形で解決できないことが判明した場合は (ライブラリの使用方法の当方の誤解、ライブラリのドキュメントの不備、ライブラリの作りの粗さによりこれはあり得る、 結果的にtry { } catch (/*省略*/) { ... }を付ける可能性もある(>>228 5. 例外を複数段fall-throughか再スローを許し、かつそれが起きた後もプログラムの 正常な動作の継続を意図する場合はテストケースが爆発する(>> 設計し、検証し、必要とあらばtry { } catch ( ) の追加も含めた修正を行うと言っているのやぞ;;; いっぽう藻前らの主張は 1. 例外をせき止めれば良い(←処理不能な未知の例外が飛んでくることが無いというライブラリに対する全幅の信頼 2. 例外を処理したりfall-throughしたり再スローしたりする関数はn*a*m個のテストしなくても動くっしょ (←自己のコードに対する無制限の気体 3. ドキュメントは100%信頼せず、読まない の3成分からなるわけやが…… >>248 >例外が関数の階層をぶち抜いてfall-throughしてくることを忘れている発言
やっぱり意味不明だな。catchすれば「階層をぶち抜いて」ってことはないわけだが。
>2. fall-throughする関数が例外による処理の中断でおかしいことにならないか(←要テスト!
もしそのテストが必要なんだとすれば、catchしない場合はその例外が通過する
呼び出し階層全部でテストをしなきゃならないってことになるが。
>>249 >1. 例外をせき止めれば良い(←処理不能な未知の例外が飛んでくることが無いというライブラリに対する全幅の信頼
なるほどな。
catchする⇒無視する、握りつぶす って脳内変換されてんだな。
catch書いたからといって上に挙げられたようなテストができなくなるわけじゃないっしょ。必要と思うならやればいい。
3.の意図しない例外の原因調査なんて main() に例外が上がってきてプログラムが落ちてからより
発生個所に近い下層で catch できた方がはるかに調査しやすいと思うんだがな。感覚が違うなあ。
仕様書や規格書はその意図を正確に読み取ろうとするのに 掲示板の他人の書き込みは積極的に曲解しようとするのは何故か?
例外は糞!危険!意味不明!テスト漏れる!って言ってる奴ほど if (err != 0) { return -1; }が大好きなんだよな 本質的にやってること変わらないのに
ファイル名に年月が使えないの困ります。 2024/02/11_データ.txt とか
>>256 それ検索性最悪だから良くないんだよなぁ。
データ/2024/02/11/データ.txt
データ.txt/2024/02/11/データ.txt
あたりならまだ許せる。
スラッシュを使う習慣が悪いわけではないが プログラマの感覚だと ISO 8601 の方式に馴染みが有ることが多いってのはある。
年月日は「ふつう」がないのでみんなが苦労している 日本とアメリカとイギリスで順番が違うし 日本には「令和」とかあるし
Windowsでも / をディレクトリ区切り文字として使えるけど(場面は限定的かもしれないけど)、その認識で使ってるのかな…
Linux で * という名前のファイルを消そうとして うわあぁぁぁとなった話はたまに聞く。 使えたとしても使うべきでない文字もある。
262>> それ以外のファイルをすべて退避した上でディレクトリごと削除したことがあったな
すみません、261ですが、Windows限定の話ではなかったですね 失礼しました…
Linuxならi-nodeをしていすれば findと組み合わせてどんな名前のファイルも消去できるんだけどなあ windowsはなんか複雑だったような気がした
iso8901にしない人はたぶんこの規格を知らないわけで意識低すぎだろと思ってしまう
>>266 ISO 8901 は情報交換用 (要するに機械同士のやり取り) の時刻フォーマットを定める規格であって
言葉や文章で使うもの (人間が読み書きする目的) ではないと適用範囲の言及がある。
ファイル名はどちらの用途もありうるので
>>256 がどのような状況を想定しているかによって
ISO 8901 が適切かどうかは違う。
もし非技術者向けのシステムなら
文化固有の日付表現に対応できてないほうが意識低いという見方もある。
>>267 エンドユーザーの文化的背景に配慮したデータフォーマットの利点は、エンドユーザーの知識やメタファーを利用した学習曲線の低勾配化であって、技術的には負の遺産になりやすいことには注意が必要。
典型的には小組織から始まるURLの並びですな。木構造との相性がひどく悪い。
あるいは大きな桁から始まるバイト列とか。あんなの1桁目から始めればエンディアン問題とか無かった。
> 典型的には小組織から始まるURLの並びですな。木構造との相性がひどく悪い。 それは人間から見たときと機械から見たときの見やすさの違いでしかないような気がする でも日本の住所は大きい方から始まるんだよな アメリカは個人から始まる 文化の違いやけども、日本人は機械生命体だったのかもしれぬ
enable_shared_from_thisなクラスで、shared_from_this()はコンストラクタの中では 呼べないようですね コンストラクタの中の処理でthisを渡したい処理があるのですが、どうしたら... そもそもそれ自体が間違っているのでしょうか コンストラクタが呼ばれる行の次でその処理を呼べばいいという説もありますが、 現在のコードがそれをやりにくい形になっていて
>>250 >>2 . fall-throughする関数が例外による処理の中断でおかしいことにならないか(←要テスト!
>もしそのテストが必要なんだとすれば、catchしない場合はその例外が通過する
>呼び出し階層全部でテストをしなきゃならないってことになるが。
その通り。テスト不要としたいなら、例外が出た原因を調べて出ないようにするのが筋
原因を調査して対策せずに予防的にテスト不十分のtry { } catch () をてんこ盛りにする方がソフトウェアー品質が上がるという考えのはおかしい
>>251 >catchする⇒無視する、握りつぶす って脳内変換
脳内変換ではなくて、予防的に入れたtry { } catch ()部分のテストが不十分な限り事実じゃーん?
>>252 >本質的にやってること変わらないのに
別に。
return -1; は呼び出し側のバグで見落とすかもしれないが
throw std::logic_error("*** ERR ***"); なら悪評千里を走ってバグの兆候が嫌でもワカル
むしろ予防的なtry { } catch () が例外のメリットをreturn -1; に縮小してゐる
>>253 藻前が二の句をつげないのは藻前の見識と資質の問題であって
漏れの責任ではないのでお間違えなきよう、
なのですよ……
テストって想定した動作環境、データ入力に対して想定した動作をするか確認をするわけで 想定しえないエラーや割り込みに対してはテストのしようがないんだけどな そのための例外処理だろ
例外が上がってくるってことはどこかで例外を投げてるってことだぞ。 問題が起きたところでその問題に対して例外を投げるという対処をしてる箇所がある。 想定してないなら例外送出すらできないよ。 その上で人間は大きいプログラムの全体を把握することは困難だし 機械的なチェックがしづらいという現実はあるって話だ。
アプリケーションを作っているのとOSを作っている人は別 それと同様に利用するライブラリがどのような例外を投げてくるか、もしくはそのライブラリがさらに下位のライブラリから投げられた例外をどう処理しているか アプリケーション開発者はそれらすべて想定できているとでも? ハードウェアやシステム含めて全部ひとりで作り上げる(もしくは密に情報共有できている)ならお前の言う通りだけどな
>>276 「把握することは困難」という現実の話もしてる。
想定してはいて、しかしそれが伝わってない。
コミュニケーションの問題、自動化の問題として捉えるべき。
俺も、(もしくは密に情報共有できている)なら、と言う話をしているがな ただ「現実の話」と言うならば、伝わっていないことをコミュニケーションの問題、自動化の問題と言うのはナンセンスだわな お前自身がこう言っている > その上で人間は大きいプログラムの全体を把握することは困難だし > 機械的なチェックがしづらいという現実はあるって話だ。 ではWindowsと言う巨大プログラムにおいてMSの中の人はどの程度全体を把握していて、発生しうる例外を公開しているのか アプリケーション開発者はその公開情報をもとに *想定し* プログラムを組まなくてはならない さてアプリケーション開発者はOSなど下位のモジュールから飛んでくる例外をすべて想定できるのか? そもそも致命的な例外でアプリケーション自身の継続が困難な場合を除いて どんな例外でもあっても継続的な処理を可能にするのが例外処理だろうに (ここで言う継続的な処理とは問題なしとして先に進むだけでなく、異常があったとして正常な(処理の)出発点に戻るという意味でもある) 起こりえる例外をすべて想定せずともプログラムを安全に継続するための仕組みが例外処理だろ
C++ の設計理念としては「そうは言っても現実はこうなっとるやろが!」という 状況に対処する方法があることも大事にしてはいる。 たとえ綺麗な方法ではなくても。 どのような問題が起こりうるのか (それなりには) きちんと想定するのは当然の大前提で、 それでもこれからリリースするソフトウェアに何が起こるかわからんのは仕方がないという話であって、 想定が不十分でも構わないという話でもない。 よくは無いが悪いときでもなんとかなるという程度の仕組みだよ。
>>271 一番いいのはコンストラクタの中でthisを渡す部分を何とかすることだけど、それが必ずしも間違ってるかは分からないので
コンストラクタの中だけでその処理が呼ばれるなら生のthisを渡すことを許容しつつ、その処理の呼び出し可能範囲を限定するか
そのクラスの構築をファクトリ関数経由に限定して、ファクトリ関数の中に構築とその処理呼び出しをまとめてしまうとか
> 想定が不十分でも構わないという話でもない。 誰もそれで構わないとは言っていないので それでも起きてしまうエラーや割り込みに対応するための仕組みが例外処理だろ 身も蓋もない言い方をするなら そもそも想定できているなら事前に排除するだけで済むわけで例外処理の必要もない (もちろん分かっていても事前に排除せず意図的に例外処理に丸投げすることもあるのは知っている) アプリケーション開発者にとってもっとも想定できない問題ってのは実行環境に起因するもの
>>272 >原因を調査して対策せずに予防的にテスト不十分のtry { } catch () をてんこ盛りにする方がソフトウェアー品質が上がるという考えのはおかしい
相変わらずずれてるな。 catch する == 原因を調査しない じゃないわけ。
>return -1; は呼び出し側のバグで見落とすかもしれないが
>throw std::logic_error("*** ERR ***"); なら悪評千里を走ってバグの兆候が嫌でもワカル
戻り値のチェック漏れは静的局所的にチェックできるが例外は出てみなけりゃ結局澪とされるわけだが。
リリース後にユーザーサイドでその見落とされていた例外が発生してプログラムが落ちたりしたらそれはただのバグ。
>>278 > そもそも致命的な例外でアプリケーション自身の継続が困難な場合を除いて
> どんな例外でもあっても継続的な処理を可能にするのが例外処理だろうに
それは幻想
c++の例外安全の達成がどれだけ難しいか理解していないね
簡単にリークするし、オブジェクトが想定外の状態を持ったりする
動作保証ができない
だから仕様に明示されていない例外が来たら基本は終了だよ
そのまま継続してそれが原因でその後別の場所で落ちられたら無駄な調査の手間が増えるだけ
例外安全と例外の種類には特に関係はないわけで、知らない例外だと例外安全の保証が困難になるなんてこともない。
>>284 例外の種類しか頭にないのか
任意の場所での例外発生に対応するなん現実的にできないということ
>>269 そのあたりの難しさを考えると、例外廃止してoptionalに統一したほうがいいかもな。
少なくとも例外みたいに変なフローで飛んで来ないし。
ぶっちゃけ
>>283 がなに言ってるのかわからない
継続してそれが原因で?
いやいやw
突如落ちるより、保存できるデータは保存してもらう機会を与えることは出来るだろ
なんでお前は何事もなかったかのように作業を続ける前提でしか話を聞かないんだ?
オブジェクトの状態が変わっているかも?
変更前のデータと比較して変わっていたらユーザに確認すればいいだろ
例えば図形情報のうちTopの読み込みで例外が発生した場合に想定してないからとアプリ落として全情報ロストさせる気か?
Topは0で初期化させ読み込めなかったことをユーザに伝えて修正、もしくは再読み込みの機会を与えるだけの話だろ
>>285 >例外の種類しか頭にないのか
>>283 が仕様に明示されていない例外を話題にしているからだが。
>任意の場所での例外発生に対応するなん現実的にできないということ
これはどういう意味なんだろうな。
着目するのは自分が呼び出している処理から上がってくる例外に対して例外安全かどうかであって
それは基本的に局所的に判断できるもの。
下層の、例外が通過してきた処理が例外安全な実装になっているかどうかってのはそっちの責務。
> これはどういう意味なんだろうな。 そうそれ tryブロックで囲った部分(つまり任意)の例外発生に対応するのが例外処理なのになにが出来ないというのか 想定している例外が発生して継続できると判断したなら続ければいいし ダメならユーザに通知してもちょも安全な方法を選択させればいい でもってそれは想定していない例外の発生でも同じ ただ致命的でどうしようもないなら強制終了させるだけの話で、想定していない例外はなんでもかんでも強制終了じゃ例外処理使う意味が薄まってしまう
>>287 ファイル保存するなとか言ってない
それぐらい終了処理のひとつだろ
ログファイルもシグナルトラップして必ずフラッシュさせるのが常套手段だろ
意味不明な例外が発生しました
データが破損してないかあなたが確認してください
動作無保証ですが処理継続しますか?yes/no
こんなUIだすやつセンスの欠片もない
私が20代の頃に見かけた論争が今も繰り返されてるのかわいい🩷
>>291 それを思いついたお前のセンスがないと言うことになるが…
俺は確認しろと言っただけだし確認には様々な方法がある
>>291 まさか、何も言わずにいきなり落とす方が良いとか言うわけじゃあるまい。
>>280 実生活のあれと似てますよね。「引っ越すことになりました。新住所はXXです」と早めに
連絡したら、気の早い知人がそこに押しかけてきて「なんやまだ引越しとらんやんけ」となる
やはり引越し作業完了を待ってからの方がいいのか。ってちがうか
>>282 >相変わらずずれてるな。 catch する == 原因を調査しない じゃないわけ
>249に賛同いただけていないということは、発生してもいない例外について予防的にtry { } catch () を入れようとしていることは
確定的に明らか
で、例外というブツは「例外なく」悪い知らせなので(∵仮に良い知らせを例外で寄越すライブラリがあったらそれ自体悪い知らせである
普通の人は悪い知らせが来る前に処置しようとする。すわなち例外が来ないように(可能な限り)修正する。
try { } catch ( ) でひっかけて原因調査兼確実な修正でざい、それが一番効率が良い方法論である、などと主張するのはおかしい人だけ……
>>284 例外安全というもののスコープに対して考察が足りていない
1.
例外安全なオブジェクト foo のデストラクトが他の例外によって引き起こされるケースでは
foo の安全な終了は(メモリかファイルステムか何かが物理的にぶち壊れてOSがパニックになったとかでない限り
ほぼほぼ保たれるから
>>284 のような言い方はできるっていやーできるが、
システム全体については
>>283 の通りであって全然安全ではない
2.
fooの中の例外処理が本当に完璧かはfooのコードに書かれている全てのtry { } catch () について
全ての例外発生条件についてテストか厳格めのコードレビューでも行わないことには安全性が担保されない。
(つまり例外安全にした実装したと主張するだけでは話がただちには簡単にはならない
それはそうとして、予防的なtry{ } catch () の何が一番駄目かというと、設計上のトレードオフをわけわかんなくすることが確実な点
例外発生後の状況というのはたいてい
>>283 の通りのわけなので、何かを捨てて何かを取る
(例えばシステムは最悪落ちても構わないが、例外安全なオブジェクトfooでリソースAの整合性は死守する等)
のトレードオフが発生するがそういうのこそ慎重な設計と考慮が必要な事項であることは確定的にあきらか
プログラムの全階層にtry { } catch ()入れたら完璧などというアフォはやっぱtry { } catch () しないのが正しい
>>298 自分が呼び出す関数が例外安全にできているかどうかと自分の処理が例外安全かどうかをごっちゃにしてるだろ。
しかも、呼び出す関数からドキュメント化されていない想定外の例外が発生するなら例外安全に作られていないだろうという
変な決めつけが混じってる。
例外安全なコードは例外の種類に依存しない。知ってる冷害に対しては安全だけど知らない例外が飛んできたら安全じゃない
なんてのはそもそも例外安全とは言わない。
>>300 お前さ、すべてのnoexcept関数呼び出しの例外テスト書いてんのか?
それが出来もしない理想論だって言ってんの
>>301 自分でnoexcept指定した関数のことなら投げないことを確認するテストくらい書けよ当たり前だろ
>お前さ、すべてのnoexcept関数呼び出しの例外テスト書いてんのか? 悪魔の証明をテストすんのか
>>302 100%自分で書いてるコードなら未知の例外なんて起こらんだろ
話の筋理解してからレスつけろや三流
なんか予想外に低レなレスポンスを寄越した
>>299 ……
さすがに
>>283 の後に
>>284 のような楽天的なことを言えるだけのことはあるということか……
例外安全は確かに目指すべき境地であり、例外安全なオブジェクトだけでコードを書けば
その関数は例外安全となる。try { } catch ()など一切不要、となるわけで一見実現が簡単に思える
が、例外安全なオブジェクトだけかをもれなく機械的に確認する方法は無い上に、
中断したら別物になる(処理の順序が命)というアルゴリズムというものの本質的特性により、
>>183 のような try { } catch () が必要なケースは隙あらば混ざり込んでくるから(※1)
>>284 が空想するようなシステム全体の例外安全化などは現実には不可能。
せいぜいある程度の規模のオブジェクトであれば、十分テストすれば
(自分が呼び出す関数が例外安全にできているかどうかと自分の処理が例外安全かどうかを慎重に確認せねばならない)
ほぼほぼの信頼度で実現できるというぐらい。
(※1)
>>183 の関数そのものは、例外安全なスレッドオブジェクトでも使ったらtry { } catch () 無しの例外安全な関数うに書き直すことはできうる
あと寝てて思ったがプロセスが死んでもサービスが継続したらお客様には迷惑を掛けずに済むので (直接そういうのをやってちるわけではないので強くは言わんが ウォッチドッグタイマー的な死活監視で異常あらばプロセス再起動とかマシンを切り替えるとか方法はいくつもあって、 十分テストされたプログラムならクラッシュ頻度をポアソン分布とみなして信頼度も出せる やっぱ「お客様の前で落ちたら恥ずかしいから」というつまらないプライドを基本的動機とする try { .... } catch (std::exception& e) { log_e("std::exceptionがスローされました"); }; みたいなコードをリリースコードに含めましょうという>>282 の調査のスタンスは全く正当化されない 100日に一回しか再現しないバグの修正を3日でやれと言われて手元にあるのがメモリダンプの代わりに上の23文字のログメッセージだけだったりしたら >>282 は自○が真剣に考慮すべき選択肢に…… > なんか予想外に低レなレスポンスを寄越した
>>299 ……
299はお前自身じゃないのか、と俺は思う
>例外安全は確かに目指すべき境地であり、例外安全なオブジェクトだけでコードを書けば >その関数は例外安全となる。try { } catch ()など一切不要、となるわけで一見実現が簡単に思える 例外安全だからといってcatchが不要になるわけないだろ。 根本的なところで勘違いしてるから頓珍漢が主張を続けてるわけだな。
例外安全には基本保証・強い保証・no-fail保証がある 例外がスローされない関数を作ればno-fail保証がある 基本保証や強い保証は例外発生後も不整合が発生しないもの たとえば例外が発生した関数をもう一度呼び出すと「すでに実行中です」とエラーを返すようなものは例外安全ではない(おそらく実行中フラグ変数が立ったままになっている)
10行のデータをファイルに出力するとき、例外が発生して5行だけデータが出力されてしまうのは強い保証があるとはいえない 例外が発生した際にデータを書き込む前のファイル状態に戻れば強い保証がある(例外安全である)といえる
誤解のないように念のため補足。 この場合の「強い」という用語は性質の分類であって強いことがより良いというわけではないという話をしてる。(んだよね?) 例外を出さずに済むならそれに越したことはないよ。 でも、ひとつの部品の中では問題を解決できないことがあるからこそ例外を用いて他の部品と連携しての解決を試みるわけ。 連携するには保証の強力さよりも保証範囲の明瞭さ (明瞭でもカバーしようがない設計はあかんが) が大事で、プログラム全体で整合性が保たれていれば例外安全と言える。 仕様が不明瞭なライブラリもあるのが現実だってのはそりゃそうだけど、出来が悪い部品とつじつま合わせをしきらないってのは例外のせいでも C++ のせいでもない。
std::initializer_listについて質問です
下の例ですがコンストラクタの引数に配列リテラルを指定した場合、リストがコピーされてしまいますよね?
これは無駄なので回避したいのですが良い方法はありますか?
https://cpprefjp.github.io/reference/initializer_list/initializer_list.html リテラルのコピーを気にするならconstexprじゃねーの? ほんとにコンパイル時に定数になるかは知らんけど
>>313 C++ に配列リテラルはない。
その書き方で出てくる波括弧はリスト初期化の構文の一部で、
波括弧の部分単体は配列リテラルではない。
実行時にオブジェクトの構築を避けるならコンパイル時に構築することになるが
それはそれで色々と制約があるんでほんまにそれが必要なんか?
というのはよく考えないといけない。
あえてやるならこんな感じかな……。
https://wandbox.org/permlink/HStrLq8ddyC3tby2 とあるtemplateの関数を実装しているのですが、
const指定の振る舞いがよくわからなくなったので
質問させてください。
以下の(だいぶ簡略化した)コードで、
f_without_const<const int*>(const int* a)
はコンパイルが通るのですが
f_with_const<int*>(const int* a)
がコンパイルが通らないのは何故でしょうか。
https://wandbox.org/permlink/OIgKM2DTqvpGduRV >>316 なるほど
ここまでやるメリットはなさそうなので大人しくデフォルトの書き方にしておきます
>>317 templateは型が違うと全くの別物として処理するからだと思う
>>317 template <class T> void f_with_const (const T t);
これに対応させるなら f_with_const<int*>(int *const a)
const T t に対して const int* a が来たら 字句の順序としては T に int* が対応してるように見えちゃうもんな……。
317です、返信遅くなってすみません 確かに言われてみればconstが修飾してるのはint*なので、意味的にint *constが正しいですね… ありがとうございました
先月東京で標準化委員会の会議あったらしいけどなんか情報ないの?
python みたいに何でも格納できる辞書型ってC++には無いよね?
>>326 要素を std::any にすればだいたいどんな型の値でも入れられる。
いろんな型を入れたところで使うときには元の型として取り出さないといけないから
処理は煩雑になってあまり良いことはないけど。
cpprefjpが間違ってるだけ? それともずっと規格から欠落してたけど誰も気付いてなかったパターン?
elifを逆から読んだらfile ラリーはこれを嫌ってPerlではelsifにした(適当
シェルが変だからな case ~ esac if ~ fi
質問なのですが Q1. std::fstreamでファイルを開くときのフラグの指定の仕方は次のどれが正義? std::fstream ofs("foo.txt", std::ios::out | std::ios::binary); // (1) std::fstream ofs("foo.txt", std::basic_ios::out | std::basic_ios::binary); // (2) std::fstream ofs("foo.txt", std::fstream::out | std::fstream::binary); // (3)
fstreamなんだったらfstreamのメンバで書くのがいいんじゃない
(1)は#include <ios>が要るし、
(2)は「basic_」の6文字×フラグの数 だけ長いし、
(3)も同様でありなおかつ
>>337 に従ったとき
use binary = std::fstream::binary;
use ibinary = std::ifstream::binary;
use obinary = std::ofstream::binary;
となってしまい、
どれもこれもコード量最小化原則的にビミョーなことに……
ていうかなんで同じことをするのに複数の書き方があるのかっていうか、
Perlじゃあるまいし……
C++の悪評の4割くらいはiostreamのせいだからな
ここでCmakeとNinjaについて聞くのダメ? どーも関係がよくわからなくて?
>>342 そういう雑多な話題のちょうどよいスレは見当たらんし、単発で終わる質問程度なら許容されると思うが……。
質問の内容が漠然としているなら丁寧な回答は得られないと思う。
「よくわからない」という状況になるときってのは大抵の場合に関連する前提知識が足りてないので
質問が連鎖的に発生してダラダラ続いたりするから。
>>336 第四の選択肢
std::fstream ofs("foo.txt", ofs.out | ofs.binary);
>>344 ofsのスコープの隙間を突きなおかつ静的メンバをドット演算子で参照する等
テクニカルですばらっし
静的解析で文句言われる可能性あるからやめときな 頻発するならスニペット作ればいいだけ そういう表面的なことにこだわる奴は三流
lldb v14.0.0 で正しくプロセスを実行できません
apt insrall でインストールしたもので, 環境はwsl 1 です
具体的には下のサイトのIssue Encountered:と全く同じ症状です
https://stackoverflow.com/questions/78275920/troubleshoot-lldb-on-ubuntu-wsl 改めて書きますと Hello World 表示だけのソースを clang でコンパイルし,
lldb で読み込み run させると
Process 20784 launched: '/home/Hustler/c++/move/move' (x86_64)
と表示されたまま応答がなくなり 放置すると(サイトでは強制終了させてるようですが)
Process 20784 exited with status = -1 (0xffffffff) lost connection
となってコマンド入力待ち状態となります
ちなみにプログラムはそのまま実行して正しく動作しますし gdb でも何の問題もありません
これに関して何か情報をお持ちの方いますか?
今やってみたのですが lldb-14をuninstall(remove)し lldb-15をインストールしてみましたが 状況は改善しませんでした
WSL1 は (ある程度) Linux 互換のシステムコールを windows 内に実装することで実現していて Linux カーネルそのものではないので色々と不足がある。 (そのかわり Windows と親和性がある部分もある。) WSL1 で用意してない Linux の機能に依存したアプリケーションは動かない。 まともな互換性が必要ならWSL2 を使いなさいという話なので手間をかけて WSL1 を積極的にはサポートしないと思う。
>>352 wsl2 ではlldbは問題なく動いてるんですか?
古いCPUなのでwsl2がインスコできないもんで
上のサイトはwslのバージョンは書いてなかったようですし
WSLはlldbが使うシステムコールが足りてないって昔から言われていたかと ターゲット機を別にするとかWSL2にするとかじゃね?
>>354 >WSLはlldbが使うシステムコールが足りてないって昔から言われていたかと
なるほどTHXです
clang使ってなかったので全然わかりませんでした
動かないlldbもさんざんggったんだけど system call未実装にはたどり着けませんでした
ようやくすっきりしました
ざっとググってみた感じたと wsl1 では procfs が提供する情報が少ないのが lldb が動かない直接の原因みたいな数年前の情報は見つかる。 内部構造がまるで違うはずなのに表面的なインターフェースは互換にするなんてのは無理のある話なので互換性が「ある程度」にとどまるのは仕方ない。
んー clangちょっと調べたかったんで Visual Studioにclangインスコして調べますわ できるならwslでやるのが手っ取り早いんですが Q9550とQ9550sしか持ってないもんで 以来CPUの爆値上がりと最近の円の爆下がりで新しく組めてないんですわ ダイサイズ変わらないのにCPU 3万ー> 10万とか購買意欲が萎える
>>355 github のwslのissueを漁れば出て来るかと。
結論がWSL2使えだったかと
自己レスです その後 Visual Studioのインストールオプションでclangを選択し 正しく動作することは確認したのですが... 今や誰でもロハで使えるインテルコンパイラがとっくの昔にllvm化されてたんですね clangに拘りがなければ x86/x64のwin/linux/wsl は素直にopenAPI使っとくのが幸せかも. ちなみにwsl 1にlinux版をインストールしましたが コンパイラicxもデバッガgdb-opwnapiも何の問題もなく動いてます(今のところは) なので Visual Studio はインストールオプションのclang は外してもとに戻し wsl は >apt remove clang clang-15 >apt remove lldb lldb-15 しときました
VS17.10.xでBoostがビルドできなくなってるのに 誰も触れない
MSVC143から144に変わったせいでビルドできないらしいですよ
>>342 CMakeとNinjaはC++の話題なのでOKです
C++、 型の指定が、めんどい 速いぐらいしか、利点ないよな
ランタイムに依存しない(し難い)のが最大の利点だろうに さらに大抵のアーキテクチャには用意されてるからクロスプラットフォームの観点でもなんだかんだ最強なんだよ むしろ最近はChatGPTが他の言語で書いたやつまで適当に書き直してくれるのもあって最強度がより高まってきてると感じるね
全く同意できんな むしろ環境依存上等で使うのがC/C++だろ パッケージシステムも標準がないしビルド環境もばらばら どこが最強やねん 標準ライブラリで完結するようなしょぼいプログラムなら他の言語使ったほうが楽
型の指定のサンプル GetProcAddressに変換をかけるマクロ #define ENTRY_INTERFACE(api) api = (decltype(api)) GetProcAddress(hInst,"_INTERFACE_"#api) ね?簡単でしょ?
>>374 あとテンプレートを使ったダックタイプとかも便利。
>>375 ふむ
実践的な(アプリを作るとか)、c++、書籍かなんか、おすすめ、ありますか?
cmake、とかの、関門もあるのだが
(githubにあがってるやつを、きっちり理解したい)
実践に入る前に言語の入門は読んだほうが良いと思う。 基礎を積まずに実践しようとするのは無謀。
なんでも、まずは改造から入るんだぜ こうですか、うんたぶんこう
C++ には未規定がやたらたくさんあるんだ。 実際の挙動から仕様を想像しようとすると意味不明でグダグダやねん。
ネットでいくらでも勉強できるだろ 書籍なんかいらん
結局ライブラリが重要だから、作りたいアプリで流行っているライブラリの入門をやるのがいい。 作りたいアプリそのものじゃなくても、類似アプリを作るのはやる気に繋がる。
>>377 github にあがってるやつを、理解しようとして、助けになる本は、結局ない希ガス
実際、実践的なものがないので、文法理解で終わってしまうという
https://github.com/TadaoYamaoka/cmajiang これ、再利用して、アプリを作りたいのだが
>>382 言いたいことがわからん。
auto すら知らんかったということは文法もまだ十分に理解してないってことだろ?
文法が分かったら読めばいいだけなんだから何の本が必要なんだ?
>>382 立直麻雀のシミュレーターなら mjx の方がいいんじゃないかな?
マイクロソフトで麻雀 AI Suphx の開発に携わってた人が作ったシミュレーターで
動作検証も天鳳の牌譜で実施したらしい
https://github.com/mjx-project/mjx 他のシミュレーターだと
- libriichi (Rust製 麻雀 AI Mortal に付属 天鳳ルール準拠 AGPL)
https://github.com/Equim-chan/Mortal - kanachan.simulation (C++製 麻雀AI kanachan に付属 雀魂ルール準拠 MITL)
https://github.com/Cryolite/kanachan/tree/v2 とかも参考になると思う
作りたいアプリの内容がわからないけど
ネット麻雀を作りたいなら cmajiang の元ネタの電脳麻将
https://github.com/kobalab/Majiang https://kobalab.net/majiang/ AI 用の対戦シミュレーターなら mjai.app
https://github.com/smly/mjai.app https://mjai.app/ が参考になりそう
>>382 書くのを忘れてた
cmajiang の元ネタ majiang-core は作者が解説本を出してる
実際買ってみたけど、やっぱりソースコードだけ読むより分かりやすい
https://www.shuwasystem.co.jp/book/9784798067889.html ブログでも解説されてるけど、お目当ての記事を探すのが大変だし本の方が見やすいと思った
https://blog.kobalab.net/ >>379 未規定というか、C++11よりも古い規格のは、古参でないと扱いが難しいからね
そういう古い規格のものが仕事で入ってい来たりすると新人は頭悩ますかもしれんね
03~11まで結構間に空いてるしね
>>385 はい、
すべて、既読です
make,
pybind11
とか入ってて、
デバッグビルド、わかりませんorz
ラムダ式が渡された側って、キャプチャの内容をチェックしたりできないのでしょうか。 例えば以下の例で、funcA()の中でfの中のthisをチェックして挙動を変えたりとか? そういうことをしたいなら、ラムダの引数で渡したりすべきでしょうか? #include <iostream> class A { public: void funcA(const std::function<void(int)>& f, int a) { f(a); // can I check 'this' (B class) in f? }; }; class B { public: void print(int b) { A objA; objA.funcA([this](int i) { std::cout << "val = " << i << "\n"; }, b); } }; int main(void) { B objB; objB.print(2); }
>>388 キャプチャした変数はラムダ式の中で使う以外の方法ではアクセスできない。
どのような方法で解決すべきかはそれをしようとする意図によるのでなんとも言えない。
それはラムダ式を使う理由とズレてるな A側で判定が必要なものならラムダ式の引数もしくはfuncAの引数で渡すべき A側は受け取るものを「intをひとつ受け取ってvoidを出力する関数」として抽象化してるんだから、それ以外のことは知れないし、知るべきではない Aは渡された関数が何であろうとintを一つ渡すだけで、その詳細 (関数がどのような値や参照をキャプチャしてるのか、渡した引数がどのように使われるのか) には触れられない ラムダ式を使うのはこのような抽象化が目的のはずだから、キャプチャした値を知りたいというのは用途から外れるかと思う
なんか最近自分でで適切なインターフェースを定義して使うって発想がなくなってる気がする ひたすらありものを繋ぐだけで作り切るみたいな
仕組みを追求することをせずにどっかから完成した㌬をドッキングするだけの作業は情報収集力さえあれば組み込み系の作業員でもできるし己のチカラにはならんのよな で、いろんなもの付け合わせていった結果、とんでもない容量のものが出来上がる上におまえそれメンテとかどうするんだよって方向に走ってって…あとは想像のとおりに
全然関係ないよな 取って貼っ付ける行為とオブジェクト指向は 全体の概要設計を把握してメンテ出来ていれば何の問題もない
素晴らしいなあみなさん。早すぎる!C plus plusは!
>>391-392 チェンジニアをチェンジ
>>395 オブジェクト指向でもクラスライブラリを造る側とただ使う側では理解度に雲泥の差がある
マジっすか?Cの20倍?しかし、専門学校の先生に、青木!バカもん!プログラミング言語Cが一冊で事足りる、と言われても、高校数学でつまづいて大鬱病になったんで、問題が解けない。。。有隣堂本店さんで、リッチーの本置いているから、いつか買います!
今のANSI対応版は易しくなってると思うけどな。 不安ならアンサーブックとセットで買えば良いベ
VMのオーバーヘッドがあるのに20倍って? あるいは20倍時間が掛かる?
いや、プログミング言語は、駿台電子は、国語の倒置法なんです。夜間の一年で、javaからで、二年でCなんです。いや、アンサーブックは、池袋ジュンク堂本店さんには、置いてなかったような。。。。。ありがたいというか、ビックリ。。。。マジか。。。機械語を仕事でプログラミングしていた先生が、喫煙所で、青木、お前、一つのことを本当に深く考えたことがあるか?と質問してくれた恩師なんです。
すみません。教えて下さい。 template<class T, class U>void (T& x, const U& y) { x=y; ... } double ←complex<double> の代入がコンパイルエラーとなるconceptの書き方あるんでしょうか? complex<double> ← doubleの代入ではエラーが出てほしくないです。
あ、上では関数名fが抜けてましたね.concept使わずとも template<class T> void f(complex<T>& x, const T& y)とすればいいでしょうけど、 y=xのときはどうかとか、あるいは complex<double>←float の代入はokにしたいとか、 いろいろ考えているとテンプレート関数なのに関数のオーバーロードが増えてしまって面倒だなと思ったものですから。
y=xのときは忘れてください。(f(complex<T>& y, const T& x)とすればいいだけ)。どういう状況のためにconceptが必要なのか要点がまとまっていませんね。失礼しました。
conceptで無理やりくくるよりか、static_assertのほうが楽そう template<class T, class U>void f(T& x, const U& y) { static_assert(std::is_same<double,T>::value&&std::is_same<complex<T>,U>::value,"絶対にゆるさない!絶対ニダ!!"); x=y; ... }
&& は右辺値参照ではなくてandの意味なんですね。std::is_same<double,T>はdouble型とT型が一致するかどうかを調べるヘルパー変数テンプレート、::value は trueかfalseのいずれかの値をとる定数ですか。static_assertは自分でエラーメッセージを作れるのがいいですね。完全にわかっていないですが、勉強します。ヒントありがとうございました。
最近、初心者にいきなり右辺値参照とかテンプレート教える風潮は良くないと思うんだよなぁ・・・論理andとごっちゃになってるやんけ ともあれis_same自体は構造体で、中にあるvalueは定数値やで 変数テンプレートはis_same_vの方。利便性(::value書くのがめんどい)のために用意されてるだけ static_assertの第一引数(bool)に条件式を与えてるんだが、間違ってる static_assert(!(std::is_same<double,T>::value&&std::is_same<complex<T>,U>::value),"絶対にゆるさない!絶対ニダ!!");
// こういう書き方もある if const_expr ( std::is_same<double,T>::value && std::is_same<complex<T>,U>::value ) { //許されない処理 static_assert(false,"許さんぞ!!"); }else { //正常処理 }
また間違えたw × const_expr ● constexpr
いろいろとありがとうございます。参考になりました。 template<class T, class U> void f(T& x, U& y) { if constexpr ( !(std::is_same<T,double>::value && std::is_same<U, std::complex<T>>::value) ) static_assert(false,"ワシャ許さんぞ!!"); y=x; } template <class T, class U> void g(T& x, U& y) { static_assert( (std::is_same<T,double>::value && std::is_same<U, std::complex<T>>::v alue),"ワシャ許さんぞ!!" ); y=x; } int main() { using namespace std; double x=3.14159265358979; complex<double> z; f(x,z); g(z,x); // 順番変えたり、xをfloatにするとエラー cout<<z<<endl; しかし、コンパイル時にifがつかえるんですねえ。凄いな、constexpr
std::is_same<T,double>::valueの代わりにstd::same_as<T,double>でも良いみたいですね.
#ifdef NDEBUG /*pass*/ #else class dbg_complex { std::complex<double> m_complex; public: // std::complex<double> のメソッドのうち使うやつ同じシグネチャのメソッドを書き並べ、m_complexに移譲 ... private: dbg_complex(doble); // 禁止 }; #define complex dbg_compled #endif ※ 個人の感想です。
いちいち移譲せねばならないのはstd::complex<T>の継承が禁止されているためorz
実際デストラクタが十中八九virtualではないし、
>>416 の最後の
#define complex dbg_complex
みたいな穴だらけの置換手段が嫌ならもうstd::complex<double> を普段からcomplexdbl という別名にすると決めてまう
すると
#ifdef NDEBUG
using complexdbl = std::complex<double>;
#else
using complexdbl = dbg_complex;
#endif
で済む
>>412 これかなり新しめのコンパイラじゃないと動かないので注意
行うべき解放処理が無い上ポリモーフィズムも不要なら、別にデストラクタがvirtualである必要は無いぞ このケースで継承すべきかどうかはまた別として
>>412 constexpr if が使える (= C++17以上) なら std::is_same<T, U>::value よりも std::is_same_v<T, U> を使う方がシンプルだと思う
ま、お好きなの使えいいんじゃないんすか~ こちとら例文示しているだけで極めているワケじゃないからぬ
>>414 テンプレート型引数に require 節などで制約を付けた場合に制約に合致しなければオーバーロード解決候補から除外されるが、 static_assert や if constexpr での判定は解決が終わってテンプレートが実体化されるときに判定される。
つまり、より優先順位の低い候補に当てはめたいかもしれない場合は static_assert や if constexpr での判定をすべきではない。
状況によって使い分けがある。
それと
>>418 が注意しているのは、テンプレートはテンプレート引数に依存しない部分は実体化されなくても検証されるルールだから。
(Two phase name lookup について調べてみて。)
つまり static_assert(false, ほにゃらら) と書いてあったらそのテンプレートが使われるかどうかに関係なく問答無用でエラーとして報告されていた。
新しい仕様では static_assert は実体化のときまで検証しないように挙動が改められたのだが、これは欠陥報告の形で問題提起されて過去の仕様に遡って修正されるので C++11 からこの仕様だったことになった。
新しいコンパイラでは C++11 を指定したときでも新しい挙動になる。
まあ、そんな小難しいこと言われても。C++が嫌われる理由だわ
実体化ってどっちみちコンパイルするときにエラー発生するんだから結果かわらねぇだろバカがよう
static_assert(false, "")は何かしらダミーの値入れて回避してたけど修正されてたんだ、知らんかった
false効かないバカコンパイラはどうしようもないからどうにもならんか //requires を使った方法 template<class T, class U> requires(!(std::is_same_v<double,T>&&std::is_same_v<complex<T>,U>)) void f(T& x, const U& y) { x=y; ... }
特定の引数型についてテンプレート展開を阻止したいんなら 特殊化してその中にstatic_assert(false, "*** ERR ***")書いても昔は駄目だったんか恐ろしい……
しかしまあ特殊化してテンプレート引数の型Tについて 態と存在しないメソッドを呼ぶように書いたらその特殊化ケースについて展開を阻止できうる(適当 クラス内でint型定数が欲しかったら古き良き enum { ONE, TWO, THREE } で十分やし 同じことをやる手段を増やせば良いってもんじゃないぞPerlじゃあるまいし……
まぁ普通にSFINAEなり=delete指定なりコンセプトなりでオーバーロード候補から外す方が利用者視点でいえば自然だな
#include <iostream> #include <complex> template <class T> decltype(auto) f(T x) { decltype(abs(std::declval<T>())) w; w=abs(x); return w; } int main() { using namespace std; cout<<f(-1) << endl; cout<<f(2.f)<< endl; complex<double> z=complex<double>(1.0,1.0); cout<<f(z)<<endl; cin.get(); return 0; } いちかばちかでやったら、通りました。abs! Who are you? sizeof演算子と同じくコンパイル時に評価されるんですか? というか、地味だけど declval が凄い。
>>431 sizeof や decltype のオペランドは評価されないということになってる。
だからその文脈で関数を使う場合でもその関数が定義されている必要はない。 (宣言だけあればよい。)
評価されないけど実体化は起こるのでそのへんの理屈は複雑でよくわからん。
相互参照は必要ない 最近はウェブプログラマのほうが賢くなった すそ野が広がると質が良くなるらしい
プログラムの文法要素が相互参照になっている状況という意味? たとえば前方宣言が必要な場合とか。 それとも (実行時の) データ構造が相互参照ということ? たとえば循環構造の後始末のやり方がわからんとか。
相互参照も自己参照も一緒 自己参照なんて参照してるのは自己ではない ホントの意味での自己参照は循環参照
shared_ptrを使いたくなったら設計を見直すべき
>>440 それは無理があるんじゃないのかね。
データ共有とかインターフェイス共有とか本質的に所有者が複数存在するオブジェクトはsharedptr使うべきかと。
設計ではモジュール間の疎結合・インターフェイスの汎用化を重視すべきで、そのためにはデータの共有方法が重要になる。
>>440 マルチスレッドセーフ考えたら使わざるを得ない場合は多々ある
言ってる意味がわからないならお前は経験不足
recurcive_mutexが欲しくなったら設計を見直したい、なら分かる気もする
C++11あたりから「生ポは使うな」みたいな極論で分かった気になってる思い上がった初心者が増えたからなぁ
>>444 生ポ使うよりかスマートポインタの参照を使った方がマシだったりするからなぁ。スマートポインタがスタックフレームにあるなら安全だし。
スタック変数専用仮引数とかあればもっと安全になるのになぁ。
仮引数の種類はもっとあっていいと思う。
>>445 考え方にもよるだろうけど、確保も解放も所有もしない関数でスマポ受け取る必要あるか?
特定の用途で管理されている特定のポインタしか許容しない、という意図ならスマポの参照でもいいだろうけど、汎用性は無いよね
生ポ受け取る場合暗黙のキャストも効かないし
>>442 むしろshared_ptr<T>でスレッド間共有オブジェクトを保持するのは 生ポに対するshared_ptr<T>のメリットが無い…… 可能な限りスレッド間共有なんてことはやめてconstオブジェクトのコピーにするのが正義…… >>439 自己参照ではないが前方宣言が必須の例、 class TreeNode; class TreeNode { std::shared_ptr<TreeNode> m_pLeft; std::shared_ptr<TreeNode> m_pRight; public: TreeNode(); ... }; んまー前方宣言が必須というのは言い杉やったかもしれんorz TreeNodeみたいなクラスはノード毎にヒープを確保するなんてことはやめて専用のアロケーターを設けて 専用の領域をまとめて確保して、 木全体がいらなくなったら木をトラバースすることなく一気に解放するのが本当やが その場合m_pLeftやm_pRightにあたるのはポインタではなくて専用の領域(配列)のindexとかにすれば 前方宣言は不要、
>>442 使わざるを得ないは言い過ぎじゃね
同期取るのにshared_ptrのアトミック保証に依存するしか方法が無いの?
競技プログラマか何かか?
shared_ptrの内部的な参照カウンタとかはともかく 保持しているオブジェクト自体はアトミックでもなんでもないでしょ ってなんか勘違いしてる?
持ってるポインタの指す先のオブジェクトがアトミックになるとか言ってると思ってんの?アホかw
>>447 お前の理解はshared_ptrの一面だけだな
ようするにunique_ptrの延長でしか見てない
shared_ptrがどうしても欲しくなるのは
オブジェクトのリリースタイミングが非決定的であるとき
これは一般的にマルチスレッド環境
お前のTreeNodeの例はそれこそ生ポで実装しても対して苦労しないが
例えば動的可変multi producerなqueueの場合確実に安全なqueueの解放タイミングを知るにはリファレンスカウントのような制御が必要となる
当然この場合コピーすれば安全なんて寝ぼけたことにはならない
それで自己参照ってのは結局何のことを指して言っていたんだい
あ、相互参照が先か
>>435 >>436の言うところの
木のノードはstd::vector<>で確保する と言われて、だよねってなる人はnewもほとんど必要ない
木の巡回は、巡回方向別にアダプタとしてイテレータを用意することが出来る 良くある行きがかり順のイテレータはスタックを使って作る
それならオブジェクトを保持するためのオブジェクトと moveためだけのインデックスを分けるかな
何やら集中砲火を浴びている
>>442 やが
マルチスレッド状況でshared_ptr<T>を超有効活用できる手が一つあったわ;;;
スレッド間の共有オブジェクトをポインタpで保持する際の問題点は、
そのポインタを知っている複数スレッドの間でpが指すオブジェクト*pへのアクセスを悉く排他制御せなばならない点やが
逆にpを知っているスレッドが任意の時刻につき1つだけなら、オブジェクトのアクセスに対して排他の必要が無い
それでいてスレッドへのデータの受け渡しに関してコピーの手間は減らせる
例:
なんちゃらWorkerスレッドオブジェクトをshared_ptr<Worker>のキューで保持しておく
スレッドfooが使うときWorker1をshared_ptr<Worker>としてpopする(←これは排他が要る
スレッドbarが使うときWorker2をshared_ptr<Worker>としてpopする(←これは排他が要る
...
(スレッドfooやbarはWorker1、2をそれぞれ独占的に使用できる) ←重要
...
スレッドfooが使い終わったWorker1をキューにpushする(←これは排他が要る
スレッドbarが使い終わったWorker2をキューにpushする(←これは排他が要る
ていうか2週間ぐらい前から作っていたやつが今さっき完動すた、
std::vector<TreeNode> nodes; ならnodesを拡張したとき破綻するかもしれんが(nodeをnodesのindexで管理するならその限りではない std::vector<std::shared_ptr<TreeNode> > apNodes; ならapNodesを拡張しても破綻しないYO!(要素の実アドレスは保たれる
それ何のためのshared_ptrなの?unique_ptrでいいというか横からコピーされないようにそうすべきでは
>>466 >>442 を書いたのおれだけど、なんでおれが集中砲火浴びてることになってんだよ
生ポとか意味不明なこといってる
>>447 は一見してわかるクソレスだろ
おまえはそれ以上のクソレスにクソコード
でもお前の勝ちだ
クソコードに2週間かけた情熱に免じて親切におしえてやるわ
shared_ptrはpに誰かがアクセスしている可能性がある間は決してdeleteされないことを保証できるのが肝
(pの先の排他ではこれは実現できない)
もちろんこれも正しく使わないと保証できない
よくあるミスは知ったかぶって参照カウントを操作しないようにshared_ptrを参照渡しとかにするやつな
その間に絶対deleteされない保証がないならやってはいけない
あーなるほど、一貫してshared_ptrの実体を渡してればそういう保証も出来るのか 自分の場合自前で排他処理や生存保証作ってたけど確かに大きなメリットだね (オブジェクト内部の排他は別に必要だとしても)
>>472 c++コードと混在できるようになってからの話だな。
既存c++を捨てなきゃならんのなら要らん。
もちろんRustをやるにはC++を捨てる覚悟が必要 C++コード(特にテンプレやclass)とは相性最悪
>c++コードと混在できるようになって Rustについて言うなら おそらくそんな未来は永久に来ない
誤解の無いように言っておくと (一部機能に限れば今でも混在出来るけど) 基本的にはC++とは相いれない
ならc++にRustの機能が取り込まれるのを待つ。 Rustが大人気になったら、さすがに標準委員の連中も初心者・コーダー向けの"Safe c++"をやる気になるだろ。
>>477 もう Rust を使えばよくない……?
>>478 >>473 だっつうの。
Kotlinみたいなのが欲しいのであって、Clojureみたいなのは要らん。
>>165 C++ のコードを Rust から呼び出したりするくらいのことは簡単に出来るよ。
たぶん (Java に対する) Kotlin みたいなこととして思い浮かべているようなことは出来る。
Rust がやってるような安全性の保障を自動では受けられない。
当然だが安全ではない (安全性が検証されていない) C++ のコードが Rust から呼び出すことで安全になったりはしない。
大抵の場合に Rust の都合に合わせてラッパーを書くことになる。
>>480 KotlinとJavaみたいにソースコードを混在できるレベルの相互運用性てあったっけ?
Rustとc++では無理だと思うけど。
cxxとかあるけど個人的には中途半端だから使わない 普通に共有ライブラリにして呼び出す方が素直で汎用的で良い
スマートポインターを使うように強制できる機能とかなら必要ないなあ
>>482 結局Cが正解なんよ
C++のスレで言うのもなんだけど
>>483 コーダー向けので考えるなら、スマポ強制は最優先だろ。
生ポインタを(コーダーが)保存できなくするだけでも随分安全になる。あと生ポインタdelete禁止とか。
極限のパフォーマンスは別に要らないから安全にしたいという要件なら GC が既に解決しているし 今更生ポインタを禁止したところで C# や Java と同じ方向性のナニカにしかならんじゃろ
gcがあったらメモリリークしないなんて幻想未だに信じてるとはね
>>489 ライブラリとかフレームワークを使う側のコーダーと作る側のライブラリアンは性能要件が全然別。
コーダーに対してライブラリアンが「コーダーのコードに極限のパフォーマンスは別に要らないから安全に「させたい」」というのはあるだろ。
>>492 それならライブラリ側でメモリ周りを隠蔽するような作り方も出来ると思うけど
ユーザー(コーダー)にはインスタンス使わせるけど内部では参照カウントなりスマポなり使ってるみたいな
それですら問題が起きるようならユーザーがクソ
C++はどんな安全策敷いてもユーザー側がその気になればいくらでもぶち壊せるからね ライブラリがあんまりそこ頑張っても仕方ない
C++で書かれたChrome V8エンジンをRustから扱えるRusty V8というライブラリがリリースされたというニュースを見た メモリ安全性を確保して呼び出しオーバーヘッドもゼロなんだって ほんとかな? ただのラッパーじゃないの? C++側でメモリアクセス違反があれば落ちそうだけど
その手の話はMICROSOFTの新機能ぐらいい思っておけば 腹も立たない
>>496 Rust の標準ライブラリだって内部は unsafe だらけだぞ。
unsafe は Rust のメモリ安全性検査の例外とする指定で、検査はされないが安全であることはプログラマが保証しないといけない。
ただ、 unsafe な部分を慎重に押し込めて (押し込めるのが正しく出来ていれば) あとは Rust のメモリ安全性検査に頼ることが出来る。
ずっと気を付けなきゃならない C++ よりは面倒ごとを基盤に押し込めたら後は機械が検査してくれるほうがマシという程度の話。
押し込めた中に問題があればそりゃ当然駄目だよ。
V8エンジンてCVE脆弱性で毎月アップデートの口実にされる迷惑なやつだからさっさとRustで書き直せよ
>>498 >押し込めた中に問題があればそりゃ当然駄目だよ。
当然分かっているだろうが、unsafeの中だけでなく、
それが外側に及ぼす影響にも問題が生じないように作らなければなら
ないが、それにはunsafeとRustの両方に対する深い理解が
必要となるだろうな。
>>500 unsafeの中を通過する時には問題ないが、
戻り値などや、連携する他のメソッドなどが
関係した結果、どこかで分かりにくいメモリーエラー
になるようなことも避ける必要が有るが、
それにはかなりRustの内部構造(?)に対する深い知識
と理解が必要となりそうだ。
>>422 これ、static_assertだけ修正してもしょうがない気がするんだけどなぁ
他にも実体化しないはずの分岐でチェックされてエラーにされることあるし
まぁ条件式に無理矢理テンプレート入れて回避は出来るけど
>>491 Rustのオブジェクトの所有権管理の強制はコンパイラに従う限りリークしない
(病的な反例があるかどうかは知らん
からリークの話ではないが、GC付き言語で解決という香具師が現れたから
>>503 RustはRcの循環参照解決できたの?
公式ソースある?
C++派だが、Rustをもってしても、相互参照みたいなものは、人類には早いらしい (設計段階で)無理しないこったな。。
循環参照をしたいときに出来ないのも困るしな。 なるべくやらないに越したことはないが、やるなら後始末は人が考えないと仕方ないわ。
食事する哲学者の問題…… Rustだと循環参照するコードを書きにくくなっているから 循環参照によるリークとか病的な反例のうちなんじゃないの 知らんけど ノードNode同士が論理的には循環参照し得るんだけど その所有権をスーパーバイザ的な配列superArray: Node[]が持っていて、
Node間の参照はsuperArrayのindexで済ませるというのもRustではすんなり通してくれな いんだっけどうだっけ…… Node& node1 = superArray[0]; Node& node2 = superArray[1]; node1.next = 1; superArray[node1.next].value = 123; // node2.valueに書く node1.nextがsuperArray[]の添え字範囲内であることを機械的に保証するためにRustはどんな魔法を使ってくれる のか
>>510 Rust では実行時にチェックされて範囲から外れていたら panic (C/C++ で言うところの abort みたいなもの) する。
https://doc.rust-lang.org/std/ops/trait.Index.html#tymethod.index C/C++ のように配列がポインタになるということはなく、スライス (C++ で言うところの span みたいなもの) が基本型として組み込まれているので範囲チェック出来る。
コンパイル時に範囲内であることがわかる状況なら最適化で消えることもあるみたいだけど
実行時に外部から入ってくる値に依存することもあるので実行時にチェックしないとどうしようもない。
enum、 文字列への変換、 大変すぎて、ビックリした
俺はenumの機能を拡張するクラスを自分で定義してるな それで文字列変換も文字列からの変換も出来る
autogenerated.txt.c みたいなの使うのも手だぞ 急がば回れ そしてCよりはうまく書ける
好きなように書いて、好きなように変換して、途中でincludeする 簡単に書くもよし、ガッチガチにチェックするもよし
HAGE(CAUWA1) HAGE(CAUWA2) HAGE(CAUWA3) : みたいなテキスト作っといて 手コキストを#includeする手前でHAGEの意味を変えてやるとうまいこと一元化できる
magic_enum教えてやれや じじいは感度低いから知らんか
みてきた それが人気の実装か やりたいこと次第だが、オーバスペック感はある ちょうどほしかったんなら止めないけどね
横からなるほどー! __PRETTY_FUNCTION__ / __FUNCSIG__
あのー、アメリカグーグルで、検索すれば、良いのがでてきた 日本は、でてこない これは、やっぱり、レベルなんだろうね
>>522 アメリカグーグルって言い方からして頭悪そう
magic_enumは個数制限がきついんだよな・・256くらいが限度じゃなかったっけ
c plus plusとjava、電子音楽作成にどっちが向いてるかな?早いのは無論c plus plusだろうけど。
作成というが、記述したいのか、波形合成したいのか、はたまた生成(AI等)したいのか。。
C soundというのはかつてありましたが。javaでやろうかな。C++は自分にはハードル高すぎます。
相談スレなんだから相談しなさいよ。 独り言を書きたいなら X で。
5ちゃん初めてなんでしょ。浮いてるのはほっとこう、じきに慣れてくれる コンパイラがCらしいね。でもjavaからも操作できる実績があるって こういうときは、「やってみて脳汁が出そうなほう」でいいとおもう 結局モチベなんで
Csound は公式に Python や Java 用のラッパーは用意してるみたいだから得意なのでやればよさそう。 ところで固有名詞は正確に表記してくれないと探しにくいやで。
g++とclang++が混ざった環境なのですが、g++でコンパイルしたバイナリはstd::stringとか 名前に__cx11というプレフィックスが付き、一方clang++の方は__1というものが付くようです とりあえず、clang++の方で__cx11が付くようなバイナリを生成するにはどうしたら いいでしょうか?
すみません、__cx11じゃなくて__cxx11でした
>>536 なるほど、要は「C++コンパイラ、混ぜるな危険」ということでしょうか?
C++コンパイラでコンパイルするにしても ソースコードをCの範囲に留めて 関数プロトタイプを extern "C" すれば大丈夫だよ
>>539 なるほど、例えばこんな感じなら大丈夫なんですかね?
g++でコンパイルされたバイナリのグループAとclang++でコンパイルされたバイナリの
グループBがあったとき、AからB(またはその逆)を呼ぶときは必ずCリンケージの関数
経由にする、とか....
>>540 OK。
C インターフェイスの範囲ではどちらも同じ ABI (Application Binary Interface) に従ってるはず。
>>541 なるほど
皆さんどうもありがとうございます
昔std::vector<T>とかstd::stringを前のコンパイラでビルドしたDLLに渡したら以下略 やっぱコンパイラを混ぜるときはextern "C" な関数にプリミティブな型のみを渡すインターフェース設計にするパティーンが安牌 文字列とか渡したかったらあくまでchar[]にすべき……
>>536 この場合は別々に標準ライブラリがリンクされる、つまり2つ動くのかな?
単にリンクするだけではどっちかのライブラリのスタートアップしか呼ばれないから 呼ばれてない方のライブラリの初期化がされなくてまともに動作しない問題が残ると思う
仮にどうにか辻褄合わせが出来てちゃんと動いたとしても将来の開発環境・実行環境でどうなるか予想しづらいというのもある。
こういう感じの実装を見かけたんだけど、ptrって解放済みの領域を指してないよね? int *ptr = NULL; std::map<char, int> m; m.insert(std::make_pair('a', 30)); { std::map<char, int>::iterator itr = m.find('a'); if (itr != m.end()) ptr = &(itr->second); // ここでitrは解放される } if (ptr) printf("*ptr = %d\n", *ptr); // 大丈夫?
>>547 itr が指してる先は m の一部なのでまだ生きてる。
問題ない。
>>545 ヤヴァイやん
>>539 しても全然OKじゃないやん……
ただしウィンドーズのDLLの呼び出し場合は
>>539 に従っていれば問題無いはず……
ランタイムの初期化エントリはDLL毎に_DllMainCRTStartup が用意されてDLL初期化時に呼ばれる
独習C++を図書館で借りました。よく、こんな、難しく、エグい言語が出来ますねみなさん。
他に選択肢がなかったんや😭 あと最近はobjective-cとかいう悪魔合体に比べたらなんでもマシな言語に思えてきてる
>>553 汚いが、必要なものはある。
綺麗に整理されてても必要なものがないよりは良い。
そーだそーだ C++は難しいからObject Pascalやろうぜ!
C++女学院の人々ってまだ読める所ある? 大好きだったんだけど。
>>554 C++と悪魔合体してObjective-C++とかなってるけど自分は実用的に感じた
全部それで書こうとは思わんけど、C++との共存のレベルが高くて鼻血出そうになったわ
OSやその他Apple系APIとのやり取りはObjC++、それ以外のソースはC++のみ、とかも簡単だし
>>553 若い人がCからC++の増築増築で可笑しくなって行った歴史をなぞるのは無意味ではない
>>554-555 Objective-C や Objective-C++ の方がまし
やる気は無いけどObjectPASCALはDelphiだっけ
演算子オーバーロードがもたらす言語仕様の複雑性を理解してたら軽々しくそういうことは言えない
演算子なんてなしでも書けるわけで単なる見た目だよ 些末な話
見た目はとても重要だが 見ただけでは何が実行されるかわからない
JavaのBigDecimalなんか見てると演算子オーバーロードのあるC++羨ましいよ c = a.multiply(b); とか長くなり過ぎて何をやってる式なのか分からなくなる
いや固定小数型を言語仕様に盛り込まずにライブラリとして実装したJavaが悪いのか・・・ 固定小数の取り扱い以外で演算子オーバーロードが欲しいと思ったことはない
自動微分のボトムアップ微分はC++の演算子オーバーロード機能のおかげで簡単に実現できる
Javaが持て囃されてた頃は「演算子オーバーロード?+で引き算もできるってこと?なんて危険な機能なんだ!」って叩かれてて そんな危険なものはJavaにはありません!って売り文句にされてたんだよ アホみたいだけど本当の話
演算子オーバーロードは定義のリスクや手間の割には結局自己満に完結する事が多くて、 しかも結局C++という小さな世界でしか通用しないから、他に楽しい事が沢山ある今の人は時間の無駄と考えるんじゃないかな
std::chronoの時間型なんかは良い例だよね ・clock - clock = duration (例. 13時 - 12時 = 1時間) ・clock + duration = clock (12時+1時間=13時) ・duration + duration = duration (1時間 + 1時間 = 2時間) ・clock + clock: 不可 こういう型表現もできるのは良い点
初見で単に整数で取り出すのに一苦労だけどな 型安全厨くささ感じる
演算の組み合わせが多いユースケースで可読性を上げるためのものだろう。 少ないなら関数のままでも十分。そういう意味で std::chrono は微妙。
>>575 あんた他人の受け売りだろ。fortran90にだって演算子オーバーロードあるのに
>>571 随伴行列(共役転置行列)か? それは演算子オーバーロードじゃなくて普通の関数でいいだろ
いわゆる演算子オーバーロードのメリットは、中置記法が使えるということと、一部の人間が使い慣れている演算子の算数・数学的記法のメタファーが使えることくらいかね。 その代償として文章構造の曖昧さや(その対処のための)優先順位といった規則の複雑化が必要になるので、言語設計観点からはメリット小さいよなぁ。 可能ならば中置記法を捨てて全部後置記法に統一したいところ。
チョムスキーの言語生得説って数学記号(の文法)も説明し切ってたっけ;;; 個人的には数学記号をプログラミング言語の文法に含めるのは悪手に思える 全部言葉にすべき
そうだな (8.0 * std::numbers::pi * G) / (c * c * c * c * mu0)よりも divide(multiply(multiply(8.0, std::number::pi), G), multiply(c, multiply(c, multiply(c, multiply(c, mu0)))))の方がずっと分かりやすいもんな
>>585 君どんくさいな
その括弧やカンマも排除するんだよ
8.0 pi mul G mul c c mul c mul c mul mu0 mul div
>>585 後置記法なら
(8.0 std::numbers::pi G)を掛ける
(c c c c mu0)を掛ける
割る
みたいな感じかな。
絶対数に平方の係数の四倍を掛け、中間項の係数の平方を加え、同平方根をとって中間項の係数を引いてから、平方[の係数]の二倍で割ったものを出力せよ
>>585 は痛烈な皮肉を言った。
>>590 は昔、HPの電卓が採用していた逆ポーランド法を連想して「ポーランドに行け」と言った。深いわ、ここのスレ
>>593 それも算数を習っていて、記号の意味や結合の優先順位、()グループ化のトレーニングを受けている前提だろ。
中置記法ではなく前置記法のトレーニングを受けている想定なら
/(*(8.0, std::number::pi, G), *(c,c,c,c,mu0))
だし、日本語ベースの後置記法なら中置記法のような特別なトレーニング無しで>588ぐらいは使えるかと。
やっぱり、C++は、難しいんで、慣れてるjavaで音楽ソフトウェア作ります。皆さんの健闘を祈ります。best regard
Javaの構文的美しさは素晴らしかったけど 他言語に引っ張られて汚れてしまった それならC++のほうが良い 何でもできるから
やりたいことが出来る言語と やりたいことが出来ない言語
一応、自分の技量と気力で、希望するわがままが通るかは、調べてみるけどね
EchoAPIは私のVS Codeのセットアップに素晴らしい追加となり、APIテストがとても簡単になった
やりたいことはできない。(サボりの)どうでもいいことはできる。ってほっとけww
c++が簡単ってまあ勘違いだろ 脱初級で全部わかった気になるやつ 個人的に尊敬してる人でも難しいと言ってる
javaで、簡単なドラムマシン作りました。C++では、到底オツムが良く無い僕には無理です。皆さんの健闘を祈ります。
xxx.h で namespace A { size_t intval, count, itr; } を宣言。もちろん、インクルードガードしてる。 ところが、作ったライブラリをテンプレート対応に修正したら、「intval, count, itr」が2重定義されてます。」 という旨のLINK1169のエラー(Visual Stuio 2022)が突然出てきた。前のライブラリではこんなエラー出てなかった のに...ナンデダロー、ナンデダロー♪と悩んでいたが、 namespace A { extern size_t intval, count, itr; } を宣言したら解決した。extern_や外部リンケージのことがが良くわからない。調べたら通りいっぺんのことは わかるけど。LINK1169のエラーが出たら、extern宣言してみてLINK1169を殺す、という対症療法だけ学習しました。
それに誤字だらけだし。オワタ。高齢者の認知症検査試験大丈夫かな。5年後だけど。
>>610 定義はプログラム全体でひとつとする原則 (one definition rule) は診断不要な場合がある仕様になっていて処理系が問題を検出できなくてもかまわないことを意味する。
つまりエラーが出てなくても間違っている (未定義の挙動) かもしれないので理解せずにエラーメッセージに頼るのは悪い姿勢。
テンプレートにすると(implテクニックを使わなければ)、定義も実装も同じファイルに書かなければならないからそれが原因かなあ。とりあえず、厄介なLINKエラーは除霊されました。
>>615 テンプレート内でグローバル変数にアクセスする箇所があるってこと?
それなら今はインライン変数を使うのが便利で行儀の良い作法のひとつだと考えられている。
インライン変数は C++17 からの機能なのでそれより古い規格しか使えないような事情があるなら仕方ないんだけど……
>>616 ありがとうございます。調べてみます。
ちなみに、
>>615 定義も実装も → 宣言も定義も ええいくそっ! まーた間違えた
>>616 まーた、言い忘れました。まさにその状況でした。
[][]演算子のオーバーロードが欲しい。行列を1次元配列で実装する場合、C++は行主順(行列を行ベクトルの集まりとみなす)。Blas、lapackのライブラリをビルドしたfortran77は列主順(行列を列ベクトルの集まりとみなす)。()演算子のオーバーロードでは、行主順だろうが列主順だろうが、行列Aのi行j列の要素にはA(i,j)とアクセスできるが、列主順の場合には[]演算子のオーバーロードをどうやってもA[j][i]となってしまう。それでeigenは()演算子のみをサポートしている(本当か?)。だが、A(i,j)が添字0から始まるのが気に入らん。添字が0から始まるのはA[i][j]やろうもん。 [][]のオーバーロードがあったらなあ。
propertyなら簡単に多次元配列扱えそうなのに propertyいつになったら実装されるのやら
>>619 O [][]演算子のオーバーロードが欲しい。
O 行列を1次元配列で実装する場合、C++は行主順(行列を行ベクトルの集まりとみなす)。
O Blas、lapackのライブラリをビルドしたfortran77は列主順(行列を列ベクトルの集まりとみなす)。
X ()演算子のオーバーロードでは、行主順だろうが列主順だろうが、行列Aのi行j列の要素にはA(i,j)とアクセスできるが、
X 列主順の場合には[]演算子のオーバーロードをどうやってもA[j][i]となってしまう。
O それでeigenは()演算子のみをサポートしている(本当か?)。
X だが、A(i,j)が添字0から始まるのが気に入らん。
X 添字が0から始まるのはA[i][j]やろうもん。
O [][]のオーバーロードがあったらなあ。
行頭Xで示した文章の意味が良く分からん
ああ、そう。 ところで、A(i,j)が添字0から始まるのが気にならないんだ。じゃあ、もうええわ。
msvc4.xxにoprater delete[]をoverideする機能が無い 所からCOMの仕様が策定されている所を考えると 面白いな
>>622 日本語の意味が分からんと書いている
0オフセットが嫌ならiやjから1引けば良かろうもん?
>>619 [] がカンマで区切られた複数の引数を受けとる機能は入る見込み。
そのための前準備として [] の中でカンマ演算子を使うのが C++20 から非推奨になってる。 必要なら括弧で囲めばいいだけだから深刻な互換性問題にもならんだろうし。
[][] をオーバロードするとなると辻褄合わせが難しいだろうから入ることは期待できないと思う。
>>625 あ、アンカーを間違えた。
>>619 にすべきだね。
すまぬ。
結局はベクトルや行列の演算の何かなんだろうから 二重配列を直接操作するというよりベクトルや行列のオブジェクトの演算を 定義する、演算子オーバーロードする、とかそういうコードを一旦書くわけには いかないのかな?
[][]演算子が出来たら [][][]の解釈に困るからできない というより []が一つの演算子だから[][]はないし混乱のもと [ , ]が正当
pythonみたいにhoge[:,:,::-1]みたいな描き方したい operatorオーバーロードの仕方教えてくれ
どうしてもやりたいならユーザー定義リテラル使ってhoge[":;:;::-1"_slice]とか書かせるかなあ
[,]とカンマ演算子の優先順位はどうなるんじゃ…… まあすでに関数の引数部分で似たような状況((, , ,))だから良いのか……
>>631 先述 (
>>625 ) の通り [] 内での (丸括弧で囲まない形での) カンマの使用は C++20 から非推奨。
これは変更に対する布石で、 C++23 からカンマは引数の区切りのカンマとして解釈されることになった。
解釈が変わる (互換性が維持されない) 変更なのだが、大量の既存のコードを検証してそれが問題になるような使い方はほとんどない (あっても簡単に迂回できる) と判断された。
>>316 char name[] = "sazaesan";
これ配列リテラルちゃうの?
nameはポインタだが
dc エリアに sazaesan\0 格納されるだろ
>>634 > これ配列リテラルちゃうの?
文字列リテラルは配列の一種ではあるが、この場合は配列一般を表すリテラルはないという意味。
(C にはコンパウンドリテラルがあるし、一部の処理系では C++ でも使える拡張があるけど。)
初期化子に現れる波括弧が配列リテラルだと誤解しているらしいことについての指摘なので文字列リテラルも配列リテラルだというのは関係がない。
> nameはポインタだが
いいえ。 name は配列。
> dc エリアに sazaesan\0 格納されるだろ
これはリテラルかどうかの話とは関係がない。
>文字列リテラルは配列の一種ではあるが、この場合は配列一般を表すリテラルはないという意味。 おおっと苦しいねぇw
>配列リテラル そもそもこの言葉がおかしい 配列リテラルなんてものは存在しない リテラルは数値や文字、文字列の変更不可な定数を指す用語で、配列等の変数とは間逆の存在 配列は文字列リテラルとかで初期化はできるがリテラルには分類されない 主にjavascript界隈で平気で配列リテラルなんて説明してるサイトがあるが全部間違い
>>638 英単語としての literal の意味にそぐわなくても、言語仕様でリテラルという用語を割り当てられたならリテラルというしかない。
JavaScript (ECMAScript) のことはよう知らんけど仕様を見たら [] で囲んで配列を表現する文法には ArrayLiteral と書いてあるぞ。
https://262.ecma-international.org/15.0/index.html#prod-ArrayLiteral >>639 そこ見たけどリテラルについては13.2.3 Literalsで定義されてるし
ArrayLiteralで検索したら13.2.4 Array Initializerと書いてあるから、ArrayLiteralはただの誤植だろ
そんなのを根拠にして配列リテラルなんておかしな説明が広まってるのか
どうだろ? 同じものでも切り口によって呼び名が違うことはあるじゃないの。 たとえば字句的には識別子と呼ばれてるものが構文の上では変数だったり型だったりするわけで。 本当になんの使い分けの意図もなく単なる間違いなんか? いやまあ、私はよう知らんから本当に間違いなんかも知らんけど。
>>643 だから
値による Initialize と Literal がどーちがうというんだ
何をこだわってるの?
用語は概念と結び付いてる。 理屈の建て付けが用語に現れているのだから用語の間違いは理屈の理解の誤り。 こだわるべき。 訳の都合とか歴史的事情でわかりにくい変な用語になってるのもよくあることだけどな。
常に厳密であるべきとまでは言わないけど、必要なときに説明できる程度にはね。
ECMAScript® 2024 Language Specification
A Grammar Summary
https://tc39.es/ecma262/2024/multipage/grammar-summary.html#sec-grammar-summary より抜粋
| PrimaryExpression :
| Literal
| ArrayLiteral
| ObjectLiteral
| RegularExpressionLiteral
|
| Initializer :
| = AssignmentExpression
camel case の『ArrayLiteral』等は文法記法上のシンボルであり専用の(斜体)フォントが使用されている。
『ArrayLiteral』は『PrimaryExpression』の下に『Literal』や『RegularExpressionLiteral』等と並んで定義されているので『Literal』の下には無い。
これを踏まえて、何故『ArrayInitializer』というシンボル名にしなかったのかという疑問なら話が分かる。C や C++ の『Initializer』関連も参考になる。
初心者が聞いたら間違いなく混乱するなこりゃ 普通リテラルってデータリソース「表現」のレベルでメタキャラと対な概念、って点をまず押さえるべきなんじゃないかと Cならバックスラッシュがリテラルかメタキャラかはシングルクウォートで囲まれるかダブルクウォートで囲まれるかで変わる、みたいな感じで あと表現と「実装」(配列orリストorタプルetc.)をごちゃ混ぜに議論してるのも良くない…気がする JSでの用語用法に関しては正直どうでもいい他所でやれとしか
>>646 こだわってるのはお前だけ
しかも値によるInitializeとLiteralは用語の間違いではなく同じものでしかない
寝言ほざくな
このはちみつなんとかて なんでこのスレにずっと張り付いてるの?
コテハンだから目立つというだけで、名無しでずっと張り付いてるのもいるでしょ
むしろこの手のスレで名無しのすべてが毎回入れ替わって別人なんだと思えるほうが異常とも言える
名前が売りたいならtwitterとかで活動された方がいいんじゃないのと思っている
は?w はちみつ餃子なんて名前売って何になるってんだ? ペンネームかなんかで活動しているわけでもないのに
名前が広く知られる必要も意味もない。 話を追いやすくするのが主目的であって「私」というキャラクタを主張したいわけではないので、むしろ意図的に 5ch 上でだけはちみつ餃子と名乗ってる。 (元々はSCHEME餃子と名乗っていたが Scheme スレ以外にも書き込むので変えた。) Twitter (X) のアカウントも持ってはいるけど。
議論してても別の主張と混同されたり自演認定してくるやつがいたりして本筋からズレまくって面倒くせぇことが結構あるんだよ。 コテハンはコテハンでなんだかんだ言うやつがいるからどっちもどっちで面倒くせぇけどな。
動作から見るポインタと配列の違い…… char arr[] = "abc"; char* p = &(arr[0]); assert(&p != &(arr[0])); assert((void*)arr == (void*)&(arr[0])); いや知らんけど多分…… メモリ割り付けまで見たらもっとはっきり違いがわかるパースン
訂正orz…… 誤: assert((void*)arr == (void*)&(arr[0])); 正: assert((void*)&arr == (void*)&(arr[0]));
コンパイル時にsoファイルをリンクする時って参照されるsoファイルを参照している側よりも後ろに書くみたいなルールあると思うんだけど、
このルールに従わずsoファイルを前に書いた時にコンパイル成功する環境と失敗する環境がある
失敗するときのエラーはundefined reference errorでso側を参照しているところでエラーになってる
gccのバージョンは一応同じで、OSはwslのUbuntuとRedHat
Redhat側で成功している
コンパイルするときのコマンドは同じもの
原因ってどのへんにあるのかわかります? あるいは何らかの設定で回避できるとか
似た事象でこの辺が引っかかったけど答えはなかった
https://forums.debian.net/viewtopic.php?t=152808 LD_PRELOADが影響与えるのは実行時なのでは?
せやな 書ける範囲で具体的なオプションを書いてくれると助かる もしかしてディストリでsoの置き場所が違うのにそれに対応してないとか?
使ったことないけどマニュアル見る限り-tでリンクするファイル表示できるっぽいな
今日から、reasonというDTMソフトの、rack extentionを作るために学ぶことに決めました。
core javaみたいな、書籍がC++にも無いかなあ。
GNU Linker では順番通りに一度しか探査しない仕様なので指定の順番に意味がある。 どういう順番でも通るなら GNU Linker 以外が設定されてるんじゃないのかな。 g++ はフロントエンドに過ぎないし、呼び出すリンカを変えるように設定は出来る(されてるかもしれない)よ。
そういえばリンカーが何かって確認してなかった 後で確認してみる。ありがとう
主要なリンカとしては gold, lld, mold などがある。 これらに比べると GNU Linker は単純に遅い。 ただ、オブジェクトファイルの構造には文書化されていない場当たり的に決められた不明瞭な部分も多くてよくわからんところは「GNU Linker の挙動が仕様」みたいな扱いなので確実に「正しい動作」を期待する保守的なディストリビューションは GNU Linker を採用することも結構ある。
グローバルな変数を使う時って、 namespace hoge{ constexpr int hoge; }; と class hoge{ static int hoge; }; のどっちを使うべきですか?
上のconstexprはいらない 何のためにつけたか不明だが
昔はグローバル変数の代わりに関数のstatic local 変数を使ってたけど、最近はどうなのかしらん?
>>677 どちらの変数もグローバル名前空間スコープで宣言されていない。
namespace foo { int hoge; } だとusing foo::hoge; ができるが class Foo { public: static int hoge; } だと using Foo::hoge; できない という印象、
オブジェクトの寿命がプログラムの開始から終わりまでずっとあるがグローバル名前空間スコープで宣言されていないがために グローバル変数と言ってはいけないならが オブジェクトの寿命がプログラムの開始から終わりまでずっとあるがグローバル名前空間スコープで宣言されていないオブジェクトは 何て言えば良いんじゃ……
今やDouble-Checked Locking is Fixed In C++11されたのだから static local 変数を使う意味は無くなた ※ 個人の感想です
>>684 なるほど……
これからはレビューでグローバル変数と口走る香具師が居たらすかさず訂正を要求するわ㌧クス、
言語仕様 (C++23) 内でグローバル変数 (global variable) という語を使っている箇所を検索してみたら二箇所みつけた。
https://timsong-cpp.github.io/cppwp/n4950/diagnostics.general#2 https://timsong-cpp.github.io/cppwp/n4950/fs.op.current.path#5 前者は意味がわからん……英語と C++ に詳しい人は解説してくれんか。
後者はどこで変更されるかわからんものというニュアンスで、文法上の分類としての意味はなさそう。
errnoのことでしょ、昔は本当にグローバル変数だったらしいし、そのせいか今も「errnoはグローバル変数です」って説明がそこら中に転がってる そこセクション概要だし、後者と同じで別に言語仕様上の意味はないと思う お客様の中にC/C++/UNIX/POSIXそれぞれにおけるerrnoの仕様/記述の歴史家はおられませんか
>グローバル変数とは、複数の関数から使用できる変数のことを言います。 >グローバル変数は、関数外で宣言された変数です。 >一方、関数の外側でも変数を宣言できます。 これを グローバル変数 と言います。 ぢつは自動変数以外はTLSもファイルスコープのやつも静的記憶期間の変数も全 部グローバル変数だったりして……
当然オブジェクトのメンバ変数も関数の外でクラスが定義されている限り、 自動オブジェクトであってもメンバ変数は例外なくグローバル変数である という定義にしたら単純で誤解の余地も無い
しかしよく考えたら >グローバル変数とは、複数の関数から使用できる変数のことを言います。 には他の関数に参照渡しされた自動変数も含まれるから、アドレスが関数外に流出して メモリエリアシングの可能性がある変数はみなグローバル変数ということなのかも……
現在C++を勉強しています 規格書を読んで分からないところはChatGPTに質問すれば 大体解決してしまうのですが、こんな楽な勉強方法でいいんでしょうか? 昔、入門書読んでは挫折を繰り返してたのがバカバカしくなりました
>>692 それ何の心配?
そもそもプログラミングをAIにやらせること考えたら?
初心者は何が分からないのか分からない。 つまり的確な質問は出来ない。 要領を得ない質問から上手く察して回答するのは難しいよ。 (人間の指導者でも。) 学習の最序盤では入門書を読んで一方的に知識を詰め込む段階は要ると思う。 (それによって最低限に意味が伝わる質問が出来るようになる程度には。) 基礎を詰め込んだ後なら詳細を規格から探し回るよりは AI のサポートがあると便利ではあるかもね。
超賢い検索サイトだと思って付き合ったらいい いきなり答え出ちゃったり、違うそうじゃないっていうのが出たり 楽しめるようなら楽しめる
>>697 特に初心者向けというわけではありませんが、初心者が駄目なわけでもありません。
C++ 関連の雑多な話題のスレという感じですね。
>>698 ありがとうございます
最近勉強を始めましたので分からないことがありましたらご教示いただければと思います
DTMソフトのReasonのRack Extensionを作るのに、C++を覚えなきゃいけなくなりました。 独習C++とchat GPT頼りになんとか作りたいです。 環境変数の段階で躓いてます。
環境変数の話はC++の話ってより、Unix系の環境でのUIの話になるんだよね。 シェルスクリプトが中心にいるような世界だと、ああいうやりかたで設定するのが便利だったっていう。 正直、とりあえず無視して進んでもいい話だと思うよ。 優先度低いから、必要になってから学び直す感じで。
>>700 プラグイン的なものを作る場合はベースになるソフトの仕様に従わなければならない。
設計思想を理解するのは自分で一から設計する場合とは違った難しさがある。
入門書を読んだ程度で取り組むには ChatGPT の助けを借りても難しすぎるように私には思えるが……。
>>701 開発環境構築にあたって設定しなければならない (処理系や開発環境が参照する) 環境変数がよくわからんとかいう意味だと私は理解してた。
もしそういう意味なら必要になってからというんじゃなくて今必要なんだろ。
Java の経験はあるようなので環境変数の概念がわからんとかではないと思う。
ああ…その発想はなかった。 そういう意味なら全くの見当外れなレスだったから、忘れて。
まだ、chatGPTに「こういうプラグイン作って」で済む時代ではないのか
グルーコードは頼んだら書いてくれそう そういうのこそ、webから情報収集してもらって、AIに組んでもらいたい
「とりあえずHello World出すプラグイン書いて」とか「この情報どうやって取得すんの?」とかは今のAIでもやってくれるから その手のコード書き捨てるのは格段に楽になった
マイナーなライブラリの使い方きいたらデタラメばっかだよ
まぁな
>>708 結局ところ学習ソースはネットだからネットで情報の少ない分野がいい加減になるのはしゃーない
>>710 しゃなくはない
単なる現段階の技術的制約にすぎない
わからんものはわからんと言うべき
簡単に受け入れるな
AI が人間の知能を模倣しようとする試みである以上は人間に似た限界もある。 何もかもの専門家であることは出来ない。 無料で使える ChatGPT はその性質上、汎用 AI として調整されてるし使えるリソースは少なめなのでこれで AI を判断しないほうがいいよ。 プログラミング専用に訓練した AI は本当に賢い。
プログラミングの専門家ってなに?という疑問 言語仕様や構文、標準ライブラリに詳しい人またはAIのことかな? でもそれって特定ビジネスドメインの専門家ではないよね? たとえば高度な会計処理のプログラミングをAIにしてもらうことって可能なのかな? アプリケーションを完成させるにはプログラミングだけでなくビジネスドメインの知識も必要になると思うけど
たとえば高位の税理士や会計士がプログラミング専門に訓練したAIに指示を出すことで会計ソフトを作ることはできるのだろうか?
具体的な話はしないよ。 ChatGPT を試した程度で AI を評価すべきじゃないという主旨。
たとえば、はちみつ餃子さんはC++のこと詳しいけどどんなアプリでも作れるってわけじゃないよね? 医学とか専門性の高いものはその分野の知識も当然必要になってくると思うし そうするとプログラミングの専門家AIってなんだ? ほんとにプログラム作れるのか?という疑問が湧いてくる
ハチミツさんはどんなプログラムでも作れるよ 時間さえあれば
ところで、「結局C++とRustってどっちが良いの?」でも質問したんだけど、 X(旧 twitter)で、C++ というキーワードが検索できないんだけど、 俺の環境だけなのか、一般的に他の人の環境でもそうなって いるのかどっち?
unsigned intをkeyとするstd::mapである値以上ある値以下のkeyの要素を全て削除したいんだけどどうしたらいいかな?
>>722 記号を含むワードは検索できない。
投稿する側が配慮して #cpp や #cplusplus といったタグをつける習慣はあるけどそれほど浸透してないので網羅的に探す方法はないと思う。
普通のワードでも検索はなんかおかしいし。
おすすめが賢いようなのでフォローやお気に入りを積極的にしていくと快適に情報を集められるかもしれない。
昔はおすすめ機能に「いらんことするな」という意見が多かったけど思ったより良くできてるね。
最近Rustに押されてるのは検索性の悪さと無関係じゃないと思う
Go とか BASIC とか Scheme なんかも日常的な語彙すぎて検索性は悪いが、検索自体が出来ないってことはないから組み合わせるワード次第でなんとかなるもんな。 日本語の文章という制約を入れればそれなりに絞れるし。
皆さん、アドバイス大感謝します。しかし、Javaはある程度分かるんですが、C++はなかなか手古摺ります。
そもそもtwitterを検索に使おうって言う発想が貧困アタオカ
通常のwebより、SNSのほうが新鮮でおいしいって若者は思ったりするらしいんだが それなら5chもいいぞ、名無しでいけるだけあって、愚問こいちゃっても後腐れは少ない
>>729 そうやって解決策を示さずに初心者を排除していると老害と言われるよ。
自分が初心者だった頃を思い出せば 新参者に優しくなれるだろ?
初心者だった頃は、好き放題にぶっ叩かれてたな 同じようにするまいとは思うものの、他人を制止するのは(ry
初心者だったころはそもそもSNSもインターネッツもなくパソコン通信の黎明期で 周囲には俺以外C言語でプログラムしようという人間もいなかったから気楽だった
十年くらいC++触ってなくて、最近また触る機会があったんだが なんだこの[]()ってのは…ラムダ式なんて初めて見たよ
そういう古参さんは、頭に+つけるってのを聞くとちょっと喜ぶと思うw
すっぽすっぽ先生がC with Classesを作ってから最初の規格C++98まで19年 C++98からC++11まで13年 そしてC++11から今14年
十年くらい前に最新の書式を導入する情報もリスクを被る勇気も無いわな
>>741 ラムダ式の前に + を付けると関数ポインタに型変換できるという小ネタの話だと思う。
>>745 実際にはラムダ式 (クロージャ型) に対しての特別な機能があるわけじゃなくて、単項 + にクロージャオブジェクトを渡そうとするとオーバーロード解決ルールの途中で適用可能な暗黙の変換が適用された結果としてそうなる
停止性問題を一般のケースについて解く機械的手続きで有限時間で必ずおわるもの(アルゴリズム)は存在しないが 人間は納期までにプログラムえおデバッグできる……できる……たぶん……
出来なかったら誰かがどういう形かで責任を取る。 それが社会ってもんだ。
有限時間内に終わる機械的計算手続きとして存在するかという観点で考えたとき デバックの不可能なプログラムは存在しないという例の命題は偽な可能性、 もっともこの正確な引用は「バグのないプログラムは存在しないがデバックの不可能なプログラムもまた存在しない」であって全体として矛盾した主張であることは前から指摘されてあるが
訂正orz、 誤: 有限時間内に終わる機械的計算手続きとして存在するかという観点で考えたとき 正: 任意のプログラムのデバッグと言う手続きが有限時間内に終わる機械的計算手続きとして存在するかという観点で考えたとき
>>746 それちょっとだけ解説きぼん ぶっちゃけなんとなくで使ってて気持ち悪かった
オーバーロード解決のルールは大雑把には
・候補の中で実引数と完璧に型が一致するものがあればそれが選ばれる。
・完璧な一致がないが暗黙の型変換を適用したら一致するという候補があればそれが選ばれる。
ということになってる。
実際には変換の中にも優先順位がごちゃごちゃあってかなり複雑なんだけど……。
で、組み込みの単項 + が受け取りうる型は何かというと算術型、スコープなし列挙型、またはポインタ型の三つ。
https://timsong-cpp.github.io/cppwp/n3337/expr.unary#op-7 キャプチャなしのクロージャ型は関数ポインタへの変換関数を持っている。 つまり暗黙の型変換が可能。
https://timsong-cpp.github.io/cppwp/n3337/expr.prim.lambda#6 クロージャからポインタへ暗黙の型変換をすれば単項 + に一致するからそれが選ばれる。
そういうメカニズムだと私は理解してるんだけど間違いがあったら誰か指摘してね。
単項 + の話題がウケたみたいなのでオマケで * の話もしようかな。 単項 * にクロージャを渡した場合は関数の参照になる。 つまり *[](){} としたら型は void(&)() ってことね。 式中に参照が現れたら参照が指す先の型に変換されて、関数指示子が現れたら関数ポインタに変換されるので多くの状況では最終的に関数ポインタになっちゃうんだけど。
要するに副作用って事か 環境によってとかオプティマイズ如何で違った動きになる事は無いのかなぁ
昔、ARM系の環境で配列とポインタがまるっきり違う扱いになって困ったって事があったんだよなぁ
>>756 これは言語仕様の話なので言語仕様に沿わないことがあるなら単にコンパイラのバグってだけだ。
「関数の配列」なんてものが存在しないC++で、関数ポインタに合法的な加減算することなんてないはずなのに、その仲間である単項+が効いちゃうのは気持ち悪くはある
関数ポインタをインクリメントしたら次の関数になるとかだったら便利よね
>>760 私もそう思う。
いつからこうなのか探ってみたら1984年のリファレンスマニュアルではそもそも単項 + は存在せず、
https://web.archive.org/web/20171002220954/http ://www.eah-jena.de/~kleine/history/languages/Stroustrup-CplusplusReferenceManual.pdf
1989年には単項 + が現れていてポインタも受け取れるようになってる。
https://www.softwarepreservation.org/projects/c_plus_plus/cfront/release_2.0/doc/ProductReferenceManual.pdf この間にどんな議論があったのかよくわからん。
C の規格では今でも単項 + は算術型しか許してないし、それが自然だよな。
>>760-762 各要素のサイズが一定じゃないから無理なんやろな
>>755 またまた勉強になったお!
ありがとうございます!!
関数のアドレスなら呼び出して スタックに無理矢理アク(以下略)
そういうむちゃくちゃが簡単にできるのがC/C++ そんなことしながら、チップを覚えるんだよなあ 自分、次はMIPS覚えないと
どっかのタイミングでbpがスタックギリギリ飛ばすんじゃなくて コンパイラが128bytesくらい飛ばす仕様になった気がするんだけど あれは0埋めで(ホントはバグがあるのに)奇跡的にバグ回避するテクニックなのか 他に理由あるんか
>>770 128 ビット (16 バイト) じゃない?
SIMD とかの都合で 16 バイトアラインが必要な環境が出てきたからという事情だと聞いたことある。
質問なのですがstd::unique_ptr<T>とかstd::shared_ptr<T>みたいなSTLで定義済みの テンプレートクラスをfriendにすることは合法? 用途はシングルトンパティーンのオブジェクトのプログラム終了時の自動解放
>>772 T のデストラクタが private なのを std::unique_ptr<T> からのアクセスは許すってこと?
特に問題ないよ。
ところでテンプレートクラスじゃなくてクラステンプレートな!
>>773 ㌧クス、
>T のデストラクタが private なのを std::unique_ptr<T> からのアクセスは許すってこと?
>特に問題ないよ。
それがTのコンストラクタがprivateなパティーンなのです!
friendにしないとビルドが通らないかった(VS2022、VS2015)。
多分moveとかの最にstd::unique_ptr<T>がTのコンストラクタにアクセスするのだと思う。
>ところでテンプレートクラスじゃなくてクラステンプレートな! なるほど……orz コード例: class Foo { friend std::unique_ptr<Foo>; static std::unique_ptr<Foo> m_pObj; private: static Foo* createInstance() { if (m_pObj == NULL) { m_pObj = std::unique_ptr<Foo>(new Foo()); } return m_pObj.get()j; // ↑ std::make_unique<Foo>()したらビルドエラー(使うには多分std::make_unique<Foo>()もfriendが要る // スレッドセーフ化は省略 } // ... };
>>775 new Foo() を Foo のメンバ関数の中でやる分には自分自身の中でやることなので friend 宣言は不要。
std::make_unique<Foo>() をすると std::make_unique の中で Foo のコンストラクタを呼ぼうとするから std::make_unique<Foo> をフレンド宣言する必要がある。
>>776 >new Foo() を Foo のメンバ関数の中でやる分には自分自身の中でやることなので friend 宣言は不要。
と思うじゃん?
↓現実
>friendにしないとビルドが通らないかった(VS2022、VS2015)。(
>>774 エラーメッセージは熟読していませんぬが、
多分クラステンプレートの実体化がクラスのメソッド全部についてまとめて行われる的なことが起きて、
Tのコンストラクタにアクセスするstd::unique_ptr<T>のメンバ関数(moveコンストラクタとか)が引っかかるのだと予想
>>777 私は Visual Stuio 2022 (MSVC 17) にコンパイルさせてエラーが出ないことを確認した上で書いてる。
手元に Visual Studio を入れていないのでオンラインコンパイラだけど。
コードを呼び出す側なども補うとたぶんこんなのだよね? 私が問題の理解を間違えている箇所はある?
#include <memory>
class Foo {
private:
static std::unique_ptr<Foo> m_pObj;
Foo(void) = default; // デフォルトコンストラクタはプライベート
public:
static Foo* createInstance() {
if (m_pObj == NULL) {
m_pObj = std::unique_ptr<Foo>(new Foo);
}
return m_pObj.get();
}
};
std::unique_ptr<Foo> Foo::m_pObj;
int main(void) {
auto bar = Foo::createInstance();
}
>>777 エラーメッセージは読まんといかんよ
分からんときは今ならLLMに読ませると良い
>>778 >>779
お騒がせしましたサーセン;;;orz ビルドが通らないというのは私めの勘違いだった模様。
コードはそれで良いです。
そのコード(最小サンプル)、および最小サンプルにする前のコード×VS2015でもfriend宣言部分をコメントアウトしてビルドが通った 。n_
フレンド宣言friend std::unique_ptr<Foo>; を付けるに至った履歴が無いので推測ですだが
デストラクタがprivateのままだったタイミングがあったのかも……
(m_pObjが生ポインタのタイプのSingletonはデストラクタがprivateでもビルドが通る(デストラクタを呼ぶ人が居ないため)
→この状態でm_pObjをstd::unique_ptr<Foo>に変更してビルドエラー、アクセス許可が無いとコンパイラに言われて慌ててfriend追加、だった可能性、
繰り返しになるが熟読した方がいいぞ 無視していいメッセージかそうでないかも区別できるようになるから
元の話題からはずれる余談だけれど、静的記憶域期間を持つブロックスコープの変数は最初に通過したときに初期化されるルールがある。 (条件によるので常にではない。)
https://timsong-cpp.github.io/cppwp/n3337/stmt.dcl#4 なのでシングルトンパターンはこう単純化して書くことも出来る。
#include <memory>
class Foo {
Foo() = default;
public:
static Foo* createInstance() {
static std::unique_ptr<Foo> m_pObj = std::unique_ptr<Foo>(new Foo);
return m_pObj.get();
}
};
int main(void) {
auto bar = Foo::createInstance();
}
それunique_ptrにする意味ある? shared_ptrなら意味わかるけど
>>784 サンプルコードでは省略したけんども、Double-checked lockingの実験をしたかったノデス!
■ Double-Checked Locking is Fixed In C++11
https://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/ つなみに関数内staticオブジェクト初期化(初回実行時)のスレッド安全性がどうーなっているのかは
よく知りま栓(よって採用には消極的
>>785 Singletonなので誰からもshareされないし……
この場合むしろshared_ptrの方が牛刀な可能性もあるし……
なぜなら、std::shared_ptrの参照カウンタはその利用特性上
異なるスレッドから非同期にインクリメント/デクリメントされることを想定せざるおえず、
スレッド安全性担保がそこそこ重い同期オブジェクトで一方unique_ptrの所有権移動は非同期に行われることはなさげ
すまんこTeamsのノリで途中送信すたorz 誤: スレッド安全性担保がそこそこ重い同期オブジェクトで一方unique_ptrの所有権移動は非同期に行われることはなさげ 正: スレッド安全性担保がそこそこ重い同期オブジェクトで行われている危険性がある。一方unique_ptrの所有権移動は非同期に行われることはなさげなので多分軽量
だいたいstd::unique_ptrとstd::shard_ptrでは前者が1個のポインタと同じサイズなのに後者は2個分ある(ヒープにとられた参照カウンタへのポインタを持つため sizeof(shared_ptr)=16 sizeof(unique_ptr)=8 というのもあり、std::unique_ptr<T>で済むところをstd::shared_ptr<T>推しするのはいかがなものか……
>>789 shared_ptrを使えと言ってるのでなくunique_ptrの意味が特にないと言ってる
別に使ってもいいけどお前それをわかってんの?ってこと?
ついでに言っておけばshared_ptrを使う場合ってのは参照カウントがゼロになったらシングルトンを破棄するみたいな凝った実装する場合に使う
unique_ptrじゃなくてナマポ使えって言ってんの?どこでdeleteする気なの?
>>791 static Fooでいいだろってことだよ
自分で気づけなかったな
>>792 マルチスレッドで問題あるんじゃなかったっけ?
資料どこにあるか忘れたけど。
>>795 もし解決されてないならunique_ptrでも問題出るでしょ
Makefileについて教えてください。 ベースディレクトリにMakefileがあり、サブディレクトリは以下の構造としたいです ・src\内にhello.c func1.c func2.cが、include\内にfuncs.hがある ・*.oはobj\内に作る ・最終成果物は.\sample.exeとして作る ソースファイル、ヘッダファイルの増減時にSRCS、INCSを修正すれば済むようにと、 以下のようなMakefileを作っているのですが、makeすると *** No rule to make target 'obj/hello.o', needed by 'c_sample.exe'. Stop. となってしまいます ソースはsrc、オブジェクトはobjディレクトリとしている場合のサフィックスルールが正しくないので src/hello.cからobj/hello.oを作るルールを表現できていない、と個人的に思っているのですが、 どのようにすれば動作するか教えてください SRCDIR = ./src OBJDIR = ./obj INCDIR = ./include SRCS = hello.c funcs1.c funcs2.c OBJS = $(SRCS:%.c=%.o) INCS = funcs.h PROGRAM = c_sample.exe CC = gcc CFLAGS+= -g -Wall -I$(INCDIR) .SUFFIXES: .c .o all: $(PROGRAM) $(PROGRAM): $(OBJDIR)/$(OBJS) $(INCDIR)/$(INCS) $(CC) $(CFLAGS) -o $(PROGRAM) $^ .c.o: $(CC) $(CFLAGS) -c $(SRCDIR)/$<
すいません、タブが崩れました 下の方ですが、全角スペースで記載してますが $(PROGRAM): $(OBJDIR)/$(OBJS) $(INCDIR)/$(INCS) $(CC) $(CFLAGS) -o $(PROGRAM) $^ .c.o: $(CC) $(CFLAGS) -c $(SRCDIR)/$< こうです 申し訳ありませんでした
OpenCVについての質問です。VS2022を使用し、includeやopencv_world4100d.libの設定が終わり、検証のためにMatを宣言してimread、imshowのみを書いて検証しようとしたのですが、dllの設定がうまくいってなかったのかコンソールにdllのloadがfailedと大量に出力されます。OpenCVの入れ方を教えてほしいです…まだC++初心者で5チャンの投稿も初心者なので何か変だったらすみません…
>>798 .o: $(CC) $(CFLAGS) -c $(SRCDIR)/$< >>799 環境変数 >>799 exeと同じディレクトリにloadがfailedと言われるdll置いてみたら?
Makefileを作る時の$<と$?と$^の使い分けを教えて下さい 特に$<が何のためにあるのか分かりません。これだと2番目以降の材料が無視されてしまって動かない場合があるんじゃないかと心配になります。あと、makeは常に新しい材料のみコンパイルするという事は、すべてのケースで$?で良いのではと思ってしまいます。超初歩的な質問だと思いますがよろしくお願いします
C言語だとオブジェクトファイルの依存ファイルは,cファイルとそのcファイルが使うhファイルだけどコンパイルするのはあくまでcファイルだけ だから依存関係の1つ目にcファイルを,2個目以降にhファイルを書いておけば$<でコンパイルできる とかかな
>>797 基本的にサフィックスルールは何十年も前からobsolete扱いなのでやめた方が良い
ところでこの場合の makefile の話は GNU Make を前提にするということでええんか?
皆さんいろいろと情報をどうもです 結局、以下のようなものと落ち着いてます ちなみに使ってる環境のmakeはGNU Make 4.4で、GNU Makeの機能を多用してます 「$(OBJDIR)%.o: $(SRCDIR)%.c」と書ける理由は、pattern rulesという機能なのですかね ここをforeachとかで書こうとしてましたが、これでいけると聞き、書いてみたら動いたのでもうそのままです 以外に汎用性が出そうだと感じてますが、改良点があればまたご意見ほしいです PROGRAM = c_sample.exe SRCDIR = ./src/ OBJDIR = ./obj/ INCDIR = ./include/ SRCS = $(wildcard ${SRCDIR}*.c) OBJS = $(addprefix $(OBJDIR), $(notdir $(patsubst %.c, %.o, ${SRCS}))) INCS = $(wildcard ${INCDIR}*.h) CC = gcc CFLAGS += -g -Wall -I$(INCDIR) all: $(PROGRAM) $(PROGRAM): $(OBJS) $(CC) $(CFLAGS) -o $(PROGRAM) $^ $(OBJDIR)%.o: $(SRCDIR)%.c $(INCS) Makefile $(CC) $(CFLAGS) -c $< -o $(patsubst $(SRCDIR)%, $(OBJDIR)%, $@)
>>803 >>804 ありがとうございます
助かりました
汎用するのならautotoolsを使った方が良いのでは?
拡張子に exe がついてるということはウィンドウズを想定してるんじゃないの? cygwin とか msys2 とかだと autotools を入れるのは簡単だけどそうじゃないならめんどいかも。
>>807 分かったからもう消えろ
ここはCのスレではないしmakeのスレでもない
>>812 過疎ってきてるし
C++とmakeは連動すること多いから
話題はあってもいいんじゃねーかと
書き込んでみるテスト
>>815 あってもいいけどコンパイラの使い方までかな
makeは誘導した方が良いと思う
質問なのですが基底クラスでpublicとした仮想関数の可視性を派生クラスでprivateに狭めることができるのですが なんでこんな仕様なの? これは逆に言うと派生クラスでprivateとした一般メソッドに対し、 たまたま同じシグネチャの仮想関数を基底クラスで定義されたら基底クラス経由でprivateとしたメソッドを外部から呼び出せ てしまいカプセル化の危機……! そういう仕様になっているメリットとは一体……
前者は仮想関数を派生クラス経由で呼べないように出来る というか派生のコンストラクタをprivateにして、friend指定したcreatorクラス経由でしか生成出来ないようにするとかそういうのに便利 あと後者は、試してないけど派生の同シグネチャの関数は基底経由で呼べないと思うよ、vtblに登録されてないから
継承に関しては早すぎる最適化の問題もあるから、そのまま使うんじゃなくてアダプタに切り離した方がいいと思う。 Boostあたりにアダプタ用のライブラリないかしらん。
>>818 コードで言えばこういう状況かな?
https://wandbox.org/permlink/gEndnLHWa7qEvNRP 基底にある仮想関数と同じシグネチャならオーバーライドするという規則は単純に言語設計の失敗。
だからこそ override 指定子が導入された。
override 指定子ではオーバーライドのつもりでオーバーライドになっていないときを検出できても
オーバーライドではないつもりでオーバーライドになってしまうことは検出できないのだが……
互換性を壊す変更を入れるわけにもいかずそのままズルズルと今まで失敗を引きずってきたという歴史的経緯。
ああそっか、シグネチャ同じなら強制的にオーバーライドになるんだっけスマン
意図せずオーバーライドになってしまうことがあるのは失敗だが、 意図して private でオーバーライドする分には「そういうインターフェイス」なのだからカプセル化の破綻ではないよ。
リスコフの置換原則を破るからあんまり良くはないと思うけどな 基底クラスとして振る舞わせる気がないならprivate継承すべきだ
>>821 なるほど……
virtualが省略可能なのが諸悪の根源かとオモタがそっちか……
>>823 通常はBaseクラス→派生クラス、の順で設計するから「そういうインターフェイス」と考えてだいたい良いのかもしれませんけども
派生クラスまで設計した後にBaseクラスにメソッドを追加して、それがたまたま派生クラス独自に定義したprivateメソッドと
同じシグネチャになってしまった場合、Baseクラス経由で派生クラスのprivateメソッドを意図せず呼べてしまうという
現象が再燃する……
んまーBaseクラスにメソッドを追加しようとする時点で変更の影響範囲を派生クラスまで広げて調査すべき というのは正論やがコンパイラで検出可能な不都合のチェックのを人にやらせるのはイマイチ……
純粋仮装関数でも無ければ影響無いだろ だいいち使わない関数なら配慮する必要も無い
たとえば GCC なら -Wsuggest-override を付けておけば override 指定子なしでオーバーライドしているときを警告する。
https://wandbox.org/permlink/h6PGzqrDAAkAVeJO だけどこのオプションは -Wall にも -Wextra にも含まれてないから個別に指定しなきゃならなくて、普段は有効になってないのが普通かも。
前から思ってたけど -Wall と銘打ってるのに All じゃないとはこれいかに
前から思ってたけど -Wall と銘打ってるのに All じゃないとはこれいかに
コンストラクタ呼び出しで()の時にinitializer_listを呼んでしまったときの警告と 逆に{}の時にinitializer_list以外を呼んでしまったときの警告がほしい
override指定子って初めて知ったけども-Wallで警告出るのは俺はやだな 警告が大量に出るソースばかりと思うし 警告出すほどにoverride指定子を付けるべきなのかちょっと疑問
overrideなんて飾りです privateも飾りです
#define class struct #define private public #define protected public すれば大体はすり抜けられる
>>837 `private` などは用途が限定的なキーワードだからそういうことも出来るけど `class` はちょっと問題があるな。
template<class T> class foo {};
みたいなのが破綻する。
C++ の言語仕様的分類では構造体というものはないのだが、 C との関係の都合で微妙な形で struct キーワードは残されてしまった。 これも歴史的経緯による変なところ。
むしろキーワードとしてのclassがいらなかった 型は全部struct、構文の曖昧さを除くためのプレースホルダは全部typenameで良かった
protectedは使った方が良いけどprivateは使いたくなるシーンがほとんど無い
rustだってどうせ20年もすれば後からあーすればよかったこーすればよかった言ってるよ
Rust はエディションごとに互換性が維持され、逆に言えばエディションをまたぐと互換性を損なっても良いというルール。 そして異なるエディションがひとつのプロジェクトに混在できる。 古いエディションから新しいエディションへの移行はかなり自動化されている。 最初から互換性を捨てることがありうる体制なので歴史的事情をいつまでも引きずることはない……と思うのだがこの体制でうまくいくかはやってみないとわからんね。 二十年くらいすれば結果が見えてくるだろう。
開発ツールごと遺跡になって発掘される毎に解析されるんだよ
似たような仕組みは歴史上何度も再発明されて全て爆死してるし 今の所うまく行ってるように見えてるのは、まだ大して使われてない証拠でしかないっておじさんは思っちゃうよ
現在公開されている世界最速grepツールであるripgrepがRustで組んであるってのがすごい
>>848 C や C++ でやってやれないことはないと思うが使えるプログラムがあるのにフルスクラッチで書きなおそうと思うことがそもそもあまり無いからね。
新しい言語が登場するという形で整理する機会が生じるのは健全な進歩だと思う。
rustで一部の高速なシステムコールが追加されたらそれを使えばC++だろうが何だろうが関係なくなる でもどうせマルチスレッドのsimd使いなんだろうからシステム全体に過負荷になるからめんどくさい
それってOS付属のランタイムをrustで書いたらって事?
glibcのシステムコールラッパーみたいなものがRustにもあればってことなのかそれともsyscall命令で飛ぶカーネルのコードがRustで書かれてればってことなのか
分からんね
>>850 は最近システムコールって言葉を知ったのかもしれない
なんか頭悪そうな人間がたくさん噛みついてきてるけど生産性ゼロだなとしか… 何が言いたいんだよ お前らが単純にシステムコールを知らなかっただけだろう? OSに対してサービスの要求するのがシステムコールだ OSよって呼び方が違う
Rustって今こんなレベル低い人間も流れ込んでるのか そのうちJava化する運命だな
>>856 そのシステムコールを提供するのはOS側であって「rustで一部の高速なシステムコールが追加されたら」ってのが意味不明だって話だぜ?
システムコールはOSが提供するのは当たり前 それがRustの特性に合わせた高速化が行われていても使う側はなんでもよいと言う話がなんでわからないのか馬鹿なのかなと
>>862 「rustで一部の高速なシステムコールが追加されたら」について説明を
お前らrust "に" 一部の高速なシステムコールが~ と書いてあると勘違いしたんだろ 馬鹿すぎる システムコールが追加されるのはOSだろ 馬鹿馬鹿しい
つまり
>>848 で書かれているツールの高速性は「Rustの言語仕様や機能に依存した話ではなくOS提供のシステムコールによるものだ」と言いたいのか
ふぅ~ん
馬鹿発見 851 名前:デフォルトの名無しさん (ワッチョイ 4694-PSZj)[sage] 投稿日:2025/04/11(金) 08:37:04.65 ID:5PthuDCs0 [1/2] ↑何これ?w
なんだよRust界隈のお客さんじゃなくていつもの大天才様くんかよ おもんな
誰と勘違いしてるんだよ
普段はこのスレに書いてない
>>46 が自分だ
ああ,自分の誤った主張を説明しようとするとボロが見えるから自分に反論してくる人にレッテル貼って誤魔化してるのか
>>850 何を言っているのか全然わからん。
Rust開発者の主張は
「C/C++並に速くC/C++より安全」
だから、
「rustで一部の高速なシステムコールが追加されたらそれを使えばC++だろうが何だろうが関係なくなる」
というのが高速の話ならそりゃそうだろとしか。
Rustが違うと言っているのはそこじゃなくて、
「ビルド通ればダングリングポインタとかオーバーフローとか無いから安全だよ(safe rust なら)」
ということかと。
すぐさまサブ回線使いだすとか言う辺り、自分でもサブ回線使ってそうだよね 「rustで一部の高速なシステムコールが追加されたら」についての説明が出来ない時点でね
>>877 すぐ上のジジイは理解できてると言うのに…
いやいやw 未だに > 「rustで一部の高速なシステムコールが追加されたら」についての説明が出来ない時点でね と言ってる時点で認知症だろ
ChatGPTにさっきのメッセージ食わせてみた 回答 たしかに、Rustで高速なシステムコールが追加されて、それを直接叩けるようになれば、言語による違いはある程度意味を失いますよね。 C++でもRustでも、結局はそのシステムコールにアクセスできるかどうかでパフォーマンスの上限が決まる。 ただおっしゃる通り、高速化しようとしてマルチスレッド+SIMDをガチで使い始めると、リソースの使い方が雑になりがちで、 他プロセスにまで影響出たりするのが悩ましいところ。 特に、CPUキャッシュやメモリ帯域を食い尽くすと、システム全体が重くなって「なんかPC遅い…」ってなるやつですね。
これぐらいの意味が取れないってどういうことなんだお前らは?
cmakeでbuildするC++プロジェクトのバイナリを配布したいんだが この場合生成されたbinディレクトリを抜き出せばいいんでしょうか? こういうことは初めてでよくわかりません
ChatGPTを使うにも知識と知恵がいるんだよ バカは質問の仕方が下手 --- 「Rustでシステムコールを追加する」という表現は 文脈によっては誤解を招きやすく、通常の意味では少し不適切 です 1. Rustで書かれたOSの中に、新たなシステムコールを実装する → 例:Rust製OS(例:Redox OSなど)にsyscallを加える。 → この場合は正しい文脈。 2. Rustでカーネルモジュールを書いてシステムコールを追加する → 実現可能だがLinuxでは一般的ではなく、安全性に注意が必要。 3. RustでOSとやりとりするAPIを自作して、それを便宜的に「システムコール」と呼んだ → 厳密には誤用。OSレベルの syscall とは異なる。
>>885 自分では意味が取れなかったんだろ?ただの馬鹿自慢だろ?
ほんとこいつ頭悪いw どうバカにされたかも理解できない
>>887 それは自分だろw
そこに書いてある内容の真偽すら判定できないんだろw
>>886 馬鹿な私に教えてください
>>885 の1~3のどの意味だったんですか?
ミネオ大先生! 随分とカジュアルな言葉遣いになられたんですね
>>850 は
>>876 で反論してやったんだからちゃんと反応しろよ。
「自分850はRustのことをよく知らないのに引き合いに出した間抜けでした」
というだけの話なのに、いつまでうんこみたいなレス重ねるんだよ。
天才様くんは次に「俺様の天才的レスが理解できない白痴ばかりだな」と言い出す 相手するだけ無駄
つまり、OSをrustで書き換えたらって話かなぁ?
こっちこい
結局C++とRustってどっちが良いの? 9traits
http://2chb.net/r/tech/1701997063/ こっちもみてるから、このスレが伸びたのかとおもうたわw
24H2の売りはrustで書き換えたってとこだろ グダグダだけど
Rustは生メモリを扱えなくしてスマートポインタしか使えないので安全だって聞いたけど
単純化すると「高速なAPIを呼ぶようにすればどんな言語でも高速になる」ってことだろ? そりゃそうだろとしか思えんよな 話の肝は、「その言語で高速に組んだこと」だと思うのに あれだろ、一番速い車の話しているときに「どんな車でも速い車に載せれば早くなれる」って言っているようなものだよな 知らんけど
ハンドラを高速にしたって秒間何千回とか頻繁に呼んでるのでも無きゃ全体の処理速度は体感出来ないだろうに
>>901 でも850は大半をシステムコールに頼ってる感じで言ってる気がするんだよな
そうでなきゃメインプログラム(呼び出し元の意)が足を引っ張るから、全体のスループットは下がるってわかるはずだし
なんなら、データを渡せば全部やってくれて結果を受けとるだけ、ぐらいに思ってる気がしないでもない
>>872 漏れは
>>850 以降の流れはノーコメント
ひょっとしたらRustで書かれたRedoxはメチャクチャ速いのかもしれん……
>>904 面白いことかけなかったら、だまっとけ
俺はかけない、だまっとく
書くならC++ かあちゃん愛してる
>>906 >>850 を書いた香具師と思われたら恥ずかしいし……
>>850 書いたやつは知ったかぶりだけど
無理に話を広げると
>>863 に書いてるrustの特性に合わせた高速化ってありえると思う?
カーネルはメモリ空間別なんだし特にできることないよね?
Cよりは「うまく」かけるけど、C++ほど「凝らずに」書けるのは、いいことのはず Linusが、C++はボロクソ言ってNGしたが、Rustにはゴーサイン出したのは、そういうことだと思ってる (念のために・後学のためにいっとくが、LinusはC++について、ユーザランドでは好きにしたらいいとも言ったはず)
最初に書いたことは一切特別なことは書いてない 小学生でも流すような内容で当たり前の当たり前 それをアホが勘違いして騒いでいる
Linusが昔触ったC++コンパイラの出来が最悪でキレ散らかした 要するにC++の仕様が悪いわけではなくて当時のg++の出来の悪さに嫌気をさしてC++を触らなくなった どっちにしろバカに危ういコードを書かせないようにするセーフティ機構を導入したところでバカがコーディングしている時点で22H2も史上最悪の大型アプデで終わってるワケなんだがな
まちげーた ×22H2 〇24H2 どっちにしろセンスのないやつに触らせたら終わる罠
C++は継承があるからコードが追い辛いとかそんな理由だろう cだと関数はその点簡潔に挙動が追いやすい
>>909 抽象化モデルが非効率だったと何年もたってから発覚したときにはそのモデルに依存しきっていて全体の書き直ししか修正しようがないということをリーナスは書いている。
プログラムを凝らずに書けることが良いというよりは、凝ったプログラムが柔軟性がない (修正しにくい) ことを問題視してるように見える。
実行効率はやってみないとわからん場合もあるし事情が変わる場合もあるから、ある時点で設計として真っ当であってもずっとそうだとは限らんのだな。
一度しか呼ばれないような関数は書かない (関数としてくくり出さない) とかいう方針の有名なプロジェクトがあったような気がするんだが、なんだったかわかる人はいる? 細部の処理の追いやすさとしてはそのほうが見通しがよいという論で、なるほどそういう考え方もあるんだなーと面白く思った記憶がある。
>>910 解説頼むわ
rustじゃないとできない並列化って何?
>>916 有名なというと、デビット・カトラーのNTカーネル開発ではなかったか
逆に、「関数は30行以内」だったかなルールが採用されており、
普通に描いたら40行とか行ってしまう関数を、25行ずつの呼び出し元関数と呼び出し先関数に
書き換えられることが頻繁にあった、というので有名だったのはFileMakerだったかな
Rust見て羨ましいと思ったのはスタックフレーム重視の言語設計かね。 効率化の観点からは入れ子構造・スタック構造が優れているんだから、スタックを崩す例外とかgotoは廃止してほしい。 あとスタックにある自動変数は関数呼び出しが乱れない限り存在が保証されるんだから、自動変数の参照しか受け付けない仮変数も欲しいところ。スマートポインタの参照は効率的だし、もっと安全に使えるようにしてほしい。
例外はもう実行が続けられないんだからスタックが壊れても問題ない それよりも、単なるエラーを例外として実装したコードが多いのが問題 std::optional など使え
>>921 ヒエッツ……、、、例外とスタックの関係について誤解が見受けられる……
例外発生時はスタックをアンワインドしてくれられるので(構築済みの)自動オブジェクトは解放される
もっとも救われるのはそれだけなので無神経なコーディングをしているとリソースリークがほとんど避けられないが
今後はよく反省し「スタック」を狩野英孝のホスト物まねの口調で「スタック~」と音読するようにしなさい
ライブラリ設計者なら一部のエラーを例外のスローとしたくなる気持ちあるある…… こんなん明らかに使う側(呼び出し元)のバグじゃねーの?!というケースまで律儀にエラー値をreturnする設計にすると かえって全員が不幸に……
ライブラリ設計ではなくて特定のアプリケーション内のアプリケーションロジックということなら 呼び出し元のバグはassert()なりで引っ掛けて十分テストするとか検出次第abort()してしまうという安直解決手はつかえまつがね……
「C++のクソなとこを反面教師にしますた!」を標榜してる言語もだいたい例外は持ってるんだよなあ
一つの関数にずらずらそのまんま一続きの手続きを書いてる 関数の入り口でif判定の群れでその次はwhileの囲まれた深いfor 中にも数段階階層のあるif これが非常にわかりにくい 出てもif並んでて、次でまたforループとか 意味でわけようとしてないけど、上に書かれたような一度しか呼ばれない関数は書かないという方針なのかもしれない 読むのめんどくさい
case文とラムダ式だらけの長いコードなら見た事あるわw
そういうのは仕方ないけど 関数で何らかのvectorを入力値として受け取ってまずそれの検証をしてループで何らかの処理やら分析をして特徴をリストアップ その後それを基にまた解析して最後に出力用に整形して直接printf ここまでが一関数で縦に並んでる 自分ならすぐ下請け関数作る GUIなどのコンポーネントも同じでDrawLineが並んでるとかなり残念な気持ちになる 速度重視なのだろうか 自分ならDrawFrameとか対象別に関数に分けてるけど
>>915 その理由だとRustもアウトか
南無南無
ラダー図や状態遷移図などの形で設計してからコードに落とし込むような場合は愚直にダラダラと書いたほうが良いということもある。 元の設計図と一対一に対応するから。 理解するために読む必要があるならそのときに見るのはコードではなく設計図だから見通しの悪さは問題にならない。 一見してコードがクソなように見えても工程全体を見ないと妥当性はわからない。 わからないけど大体の場合にはクソなのが現実ではあるだろうけどさ。
if文のネストは2段まで case文内は3行まで 1行は80文字以内 とかコーディングルールがあるはず
いい悪いじゃなくて本当に縦に長い 見づらい 2画面上のwhileループ前なんて見たくない
書いたステップ数で会社での評定が決まるのだから短く簡潔に書くのは大損 徹底的にだらだら冗長に書いて行数を増やすべき 自分を大事に!自分を第一に!
大昔や一部の組み込みみたいなスタックや関数呼び出しのコストが重い世界だと 余分な関数書くな全部main()に納めろみたいな文化もある
基本はdon't repeat yourselfかね。 繰り返しで無いのなら縦長のブロックも許容できる。
コンテキストの量にもよるよな 高速化の結果複雑なコンテキストになること多いけど、そうなると関数分けが難しくなる
極端にリソースが制限されているマイコンの場合はそもそも C や C++ が適した選択肢なのかどうかという疑問がある。 どうせインラインアセンブラまみれになるのだし、いっそマクロアセンブラのほうが見通しが良い気がするよ。
【脳科学】「政治行動の激しさ」に関連する脳回路の存在が研究で判明 [すらいむ★]
http://2chb.net/r/scienceplus/1744637408/ 上記のリンクをたどったリンク先の本文とコメントを読まれると・・・
余裕ありますか・・・
大々的にインターネット上にばらまかれました!
>>925-926 C++26で事前条件事後条件が入るっしょ、他の言語ほど凝ったものではなく単なるassertの別記法ではあるけど
バグなんだから検出次第即落として問題ないし
contractsのこと言ってるのなら単なるassertの別記法ではないぞい
リソースの後始末はデストラクタでやる (スマートポインタの利用を含む) ように設計するのが基本ではあるが……。 どうしてもそうできない事情があるなら後始末が必要な場所で例外を一旦キャッチすればいい。 例外が投げられるのは例外が投げられるような状況に対処させるためだ。 対処が必要な箇所でキャッチするというシンプルな話だろ。
MCPって面白そうだけどもC++のSDKってないんだな ラッパーとかないんかな?
MCPは単なるJSON-RPCだから仕様書とスキーマをAIに突っ込めばすぐできるでしょ MCPサーバーなんてどうせAI丸投げで実装させるのが基本だし、 速度も完全にIOとLLMがボトルネックだから、わざわざC++で実装しようなどという奴はいないのだろう
reasonというソフトのrack extentionを作りたいです。
javaの鉄則、では、goto文は使うな!と書いてましたが、皆さんどうっすか?
>>953 防災設備みたいなものだ。
使わないで済むほうが良いけど必要なときに避けようとすれば被害が大きくなる。
だけど goto は使わないで済むときに使ってしまうと更に被害が出る。
なので自分の判断に自信がないなら教条的に goto を避けたほうが全体としては比較的にマシなんだよ。
そもそも状況が理想的でないことも多いのだから理想通りにプログラムを構成できなくても仕方がない。
もうぐちゃぐちゃになってるものでもどうにかしなきゃならないときはあるだろ。
>>953 プログラミングにおいて再帰は最も重要な構造であり、C++もスタックフレームやASTなど再帰的な構造を暗黙の了解として成り立っている。
しかしgotoはこの再帰構造を容易く破壊してプログラムに混沌をもたらす。よってgotoは使ってはならない。
>>951 レス有難うございます
Oat++なるウェブフレームワークにoatpp-mcpなるライブラリがあるようです
まずはOat++から遊んでます
gotoが駄目ならlongjmpを使えば良いじゃない by マリー
setjmp/longjmpをANSIに詰め込んでるの💩だよね
アドバイスありがとうございます。駿台電子のネットワークの先生が昔、あらゆるプログラミング言語の中で一番、処理が早いのはC++だと言っていたので、頑張ります。
いまだにgoto論とかw いかに効率的にAIに作らせるかの時代だぞ 誤差レベルの最適化なんかやってる場合かよ
C++使いはジジィが多いからAIどころかIDEすら拒絶してるもんな 70年代からずっとgoto論だのインデント文字数だのvi vs emacs論争をたぶん絶滅するまで続けてるよ
>>961 そのあたりは要件定義とかユースケースとかの話だから、問題領域が違うよ。
しかし>961もそうだけど、AIの使い方の話をしているやつからPM知識の匂いがしないのはなんでかね。
AI利用法とかPMで長年研究してきた問題と重複する部分が多いのに。
まずそのgotoの話し始めたコテがどう見ても知的に問題がありそうな感じなのに そいつの話題に乗って語り始めちゃったところで、まともな結論にたどり着けるはずもなく…
まあ、クラス関数テーブル参照する分C++の方が遅いかなw
vtableのことかよ 最近のはプリフェッチ改善されてきているからな
>>968 メンバ関数は必ずvtableを参照するものではない(非仮想のメンバ関数)
参照しなければCと変わらん
Cでvtable相当のものを用意してそれを介して関数呼べば
仮想メンバ関数呼ぶのと変わらん
rack extention作りますが、グラニュラーとstutterとフーリエ変換付けたら、デスマーチ状態になりそうだなあ。
この場合に何を指してクラス関数という言葉を使ったか (そしてそれが速度的ペナルティに繋がると思ったか) は当人にしかわからんが、私なりに推測すると Java Python Ruby などで言うところのクラスメソッドから間違った類推をして得られた概念ではないかと思う。 これらの言語は「クラスはオブジェクトである」というパラダイムの世界で、抽象メソッドでもインスタンスメソッドでもない場合でも動的なディスパッチを必要とする場合がある。 もちろん C++ ではそうではなく、仮想関数を除けばコンパイル後には関数を指す唯一無二のアドレスが確定していて C の関数と比べて速度的不利はないし、仮想関数のようなことを C でやろうとすれば間接参照なり分岐なりのコストはどうせ必要なので仮想関数を C++ の速度的不利というのは無理筋だ。 ただ、充分な理解なく不必要に速度的不利な機能を使ってしまうことが (C よりは) 高いだろうという意味では C++ が不利と言えなくもないかもね。
vectorは境界チェックするから遅くてゴミでCの配列には必要ないから最強だって暴れてた超天才Cグラマ様おったなあ
境界チェックはしてるんだけど、最適化の過程で霧散する… …いまは、どこの言語もそのくらいはできるからね
オライリーで、head first C++が洋書で無いかなあ。
そりゃ、あなたたちは、プログラマーというサラリーマンなんだから、僕はバカですよ。。。とほほ。。。
fstream iostream は糞ですね判ります
C++に触れるものは、遅かれ早かれ、duck test ってものを解する バカのように振舞うな
なんでも基礎的な内容をしっかりと勉強しておけば後で役に立つから頑張ればよい ジジイになる前に少しでも覚えろ
大昔はmemsetが最適化で消されて気が付かないで徹夜してデスク蹴ったりマウス投げたりしてたんだぞ 関数のアドレスすら存在しない超高速処理で速度的には超有利 流石C++
…あ。
>>980 踏んでたわ
わっちょい自分は苦手で、やったことないんだわ
けっきょく、
>>1 の、!extend* を、何行貼ったら、
>>1 のようになるの
2行みえてるけど、3行貼ったらいいんだよな
昔と出力コードが変わったなと思うのはコプロ周りの処理がSSE前提になった事かなぁ
みなさんはstd::filesystem::path使ってますか?それともただの文字列操作してますか
>>961 breakもcontinueもgotoの一種なのだから仕方が無い 行先がスコープの始まりか終わりに限定される、というのが良心的なだけで 実行フローをぐちゃぐちゃにできうる能力のはgotoとほとんど変わらないし、、、 for (i=0; i < 100; i++) { if (i == a) { continue; } if (i == b) { break; } if (i == c) { continue; } // i== aとi==cをまとめるとしたら、if (i == a && i != b && i == c) { continue; }としないとバグ if (i == d) { break; } } また例外はスローする関数と条件を把握していない限り、 いつ炸裂するかわからないステルスgoto文がコード中にばらまかれているのとだいたい同じ…… 従って構造化プログラミングで議論に結論がデタと考えるのは早計で、goto問題は永遠に古くて新しい問題…… 大量のコードが不可分にもつれあった状態を作れるgotoと 連接・分岐・反復という構造を崩さないcontinue/breakの 違いがわからないようならどうしようもない。
そんなに構造化が嫌なら最初から機械語で書けばいい gotoしかないから楽しいかもよ 私は嫌です
いや普通の機械語・アセンブラでも、いまどきキレイに書くからw AIがコード生成しだしたらもうしらん あいつら疲れ知らずの限界なしだから
ダイクストラが言う構造化プログラミングはモジュールとか抽象データ型とかも含む広範で抽象的な概念として説明されている。 連接・分岐・反復で構成しようという話はそれより前に発表されたものだが、この時代は構造化もクソもないプログラムがまかり通っていたという前提がある。 まずはその三要素を基礎に据えて構成したらわかりやすくね? という提案 (というか感想?) に過ぎず、それで全て事足りるみたいな主張ではない。 (理論上は連接・分岐・反復で全て表現可能であるという証明はされている。) 構造化プログラミングの考え方のキモは構造は人間の認知の中にあるということ。 人間が思考しているときの構造を書き表すためにどんな言語機能 (またはデザインパターン) があればよいの? ってのが構造化プログラミングの議論なんだよ。 書いた人が思ってる構造が表現されているなら構造化プログラミングだし、構造化プログラミングのために用意された機能を使っていても構造が表れていなければ構造化プログラミングではない。 まあついでに言えば書き表されたものについて (コンパイラも人間も) 検証しやすいことも大事だ。 機械的に goto を除去したらむしろ構造が失われるという例をクヌースが出したりもしていて、結局のところはどんな機能も正しく使えば正しいし、悪い使い方をすれば駄目になるというシンプルな話。 そんなわけで break が構造化を崩すか崩さないかは使い方による。 ただ、常識的に考えて break は goto より構造を破綻させにくいだろうってだけ。
ダイクストラがじゃなくてもうちょい場を学ぼう 便所でいきなり大声で演説垂れ始める人がいたらみんな引くもんなんだよw
このスレッドは1000を超えました。 新しいスレッドを立ててください。 life time: 545日 2時間 41分 30秒
5ちゃんねるの運営はUPLIFT会員の皆さまに支えられています。
運営にご協力お願いいたします。
───────────────────
《UPLIFT会員の主な特典》
★ 5ちゃんねる専用ブラウザからの広告除去
★ 5ちゃんねるの過去ログを取得
★ 書き込み規制の緩和
───────────────────
会員登録には個人情報は一切必要ありません。
4 USD/mon. から匿名でご購入いただけます。
▼ UPLIFT会員登録はこちら ▼
https://uplift.5ch.net/ ▼ UPLIFTログインはこちら ▼
https://uplift.5ch.net/login
read.cgi ver 07.7.23 2024/12/25 Walang Kapalit ★ | Donguri System Team 5ちゃんねる
lud20250621120959caこのスレへの固定リンク: http://5chb.net/r/tech/1698705458/ ヒント: 5chスレのurlに http ://xxxx.5chb .net/xxxx のようにb を入れるだけでここでスレ保存、閲覧できます。 TOPへ TOPへ
全掲示板一覧 この掲示板へ 人気スレ |
Youtube 動画
>50
>100
>200
>300
>500
>1000枚
新着画像 ↓「C++相談室 part165 ->画像>3枚 」 を見た人も見ています:・C++相談室 part159 ・C++相談室 part158 ・C++相談室 part135 ・C++相談室 part141 ・C++相談室 part140 ・C++相談室 part146 ・C++相談室 part143 ・C++相談室 part157 ・C++相談室 part133 ・C++相談室 part149 ・C++相談室 part134 ・C++相談室 part131 ・C++相談室 part145 ・C++相談室 part154 ・C++相談室 part155 ・C++相談室 part156 ・C++相談室 part130 ・C++相談室 part124 ・C++相談室 part136 ・C++相談室 part137 ・C++相談室 part132 ・C++相談室 part117 ・C++相談室 part166 ・C++相談室 part150 ・C++相談室 part161 ・C++相談室 part152 ・C++相談室 part163 ・C++相談室 part126 ・C++相談室 part153 ・C++相談室 part148 ・C++相談室 part151 ・C++相談室 part164 ・C++相談室 part142 ・C++相談室 part144 ・C++相談室 part138 ・C++Builder相談室 Part21 ・アパートマンション経営なんでも相談室【158号室】 ・【皇室】眞子内親王殿下がお気持ち表明「結婚に向けて家族とも相談しながら進んでまいりたい」★17 [記憶たどり。★] ・アパートマンション経営なんでも相談室【143号室】 [無断転載禁止] ・C♯相談室 Part20 ・C#, C♯, C#相談室 Part98 ・◆◇◆ママ友相談室◆◇◆★2 ・[ワッチョイ]船乗りなんでも相談室・12 ・シーバス何でも相談室21 ・鍼灸マッサージ質問相談室パート15 ・[ワッチョイ]船乗りなんでも相談室・11 [無断転載禁止] ・★ギコ猫旅団の『のほほんPC相談室』 ・エイブル相談室 ・KDDIお客様相談室 ・PHP相談室 1 ・不登校相談室7 ・【ノーワッチョイ】船乗りなんでも相談室 26【内航船】 ・全国男電話相談室 ・夏休みVIP相談室 ・八百長お悩み相談室 ・不登校相談室8 ・【ハァテレビも無エ】ageteoff茸 埋め立て荒らし はんなり相談室 MANGO板分室[無断転載禁止] ・相談室で女子生徒にキスをしたり下半身を触ったりした教諭など6人を懲戒処分 兵庫県教委 ・NIPお悩み相談室 ・Uber Eats、配達員の不適切行為を報告できる「相談室」設置 ユーザー以外も通報OK [峠★] ・おっさん人生相談室 ・船乗りなんでも相談室・13 ・ハゲミン相談室 ・ほのぼの相談室 ・不登校相談室5
02:42:36 up 65 days, 3:41, 0 users, load average: 9.58, 9.52, 9.68
in 0.024327993392944 sec
@0.024327993392944@0b7 on 062115