C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
IDE (VC++など)などの使い方の質問はその開発環境のスレにお願いします。
前スレ
C++相談室 part150
https://mevius.5ch.net/test/read.cgi/tech/1584975873/
このスレもよろしくね。
【初心者歓迎】C/C++室 Ver.105【環境依存OK】
http://mevius.5ch.net/test/read.cgi/tech/1556142878/
■長いソースを貼るときはここへ。■
http://codepad.org/
https://ideone.com/
[C++ FAQ]
https://isocpp.org/wiki/faq/
http://www.bohyoh.com/CandCPP/FAQ/ (日本語)
テンプレここまで
C++相談室 part151
■ このスレッドは過去ログ倉庫に格納されています
2020/05/14(木) 11:53:25.59ID:ZPCfyTux
207デフォルトの名無しさん
2020/06/03(水) 16:50:59.31ID:UHE1JPNz208デフォルトの名無しさん
2020/06/03(水) 17:02:24.74ID:TdRUmxlv >>206
答えられないだけ。
答えられないだけ。
209デフォルトの名無しさん
2020/06/03(水) 17:03:53.52ID:DAHZjgl3 >>207
都合よくげんていつけたりなくしたりwwww
都合よくげんていつけたりなくしたりwwww
210デフォルトの名無しさん
2020/06/03(水) 17:04:33.42ID:DAHZjgl3211晒しage
2020/06/03(水) 17:11:10.63ID:UHE1JPNz 181 返信:デフォルトの名無しさん[sage] 投稿日:2020/06/03(水) 12:24:39.32 ID:DAHZjgl3 [1/9]
>>175
たまたまの結果を生活の知恵とかw
キーワードと通常言語が被らない日本語万歳だな
>>175
たまたまの結果を生活の知恵とかw
キーワードと通常言語が被らない日本語万歳だな
212sage
2020/06/03(水) 17:55:41.24ID:B/1kftuN getCFile()ってよくわからないので教えてください。
コードに次のような部分がありました。 getFile()では置き換えられない?
/// \brief Get C-file.
/// \return Extracted stdio's @c FILE structure.
std::FILE * getCFile();
file_.getCFile()
コードに次のような部分がありました。 getFile()では置き換えられない?
/// \brief Get C-file.
/// \return Extracted stdio's @c FILE structure.
std::FILE * getCFile();
file_.getCFile()
213デフォルトの名無しさん
2020/06/03(水) 18:46:53.95ID:TdRUmxlv >>193
推定だけど、
A<T, void>
の場合、2番目の仮引数がvoid型になっているので、そこには実引数を
指定しないということになっているらしい。
その結果、A<1> みたいに1つだけの引数でtemplateをinstance化できる
様になっている気がする。
まだ仕様書で確認したわけではない。
推定だけど、
A<T, void>
の場合、2番目の仮引数がvoid型になっているので、そこには実引数を
指定しないということになっているらしい。
その結果、A<1> みたいに1つだけの引数でtemplateをinstance化できる
様になっている気がする。
まだ仕様書で確認したわけではない。
214デフォルトの名無しさん
2020/06/03(水) 18:53:53.18ID:HVfXpWIv いや、省略した場合のデフォルトを指定しない限り、そんなことにはならない
template <typename T1,typename T2=void>
class A;
みたいにする
まあ、primaryの定義と同時にも書けるし、そっちが普通
template <typename T1,typename T2=void>
class A;
みたいにする
まあ、primaryの定義と同時にも書けるし、そっちが普通
216デフォルトの名無しさん
2020/06/03(水) 19:07:42.01ID:TdRUmxlv [驚くべきパターンマッチング]
MS製のSTLのforward()のソースを呼んでいて驚いた。
forward()の引数のremove_reference_t<_Ty>&& _Argの部分は、とても複雑なパターンマッチングをしているらしい。
_Tyがまだ決まって無い段階で、remove_reference<_Ty> というテンプレートclass を展開してtype メンバを調べ、それと実引数から右辺値参照部分を除いた部分を一致させるような複雑な処理をした結果、_Ty を逆算して決定しているらしい。
template <class _Ty>
struct remove_reference { // YA, #1, primary class template。"
using type = _Ty; // const も保存されているハズ。
using _Const_thru_ref_type = const _Ty;
};
・・・ remove_reference<> に対する部分特殊化があるが、省略 ・・・
template <class _Ty>
using remove_reference_t = typename remove_reference<_Ty>::type;
template <class _Ty>
_NODISCARD constexpr _Ty&& forward(remove_reference_t<_Ty>&& _Arg) noexcept { // forward an rvalue as an rvalue
static_assert(!is_lvalue_reference_v<_Ty>, "bad forward call");
return static_cast<_Ty&&>(_Arg);
}
MS製のSTLのforward()のソースを呼んでいて驚いた。
forward()の引数のremove_reference_t<_Ty>&& _Argの部分は、とても複雑なパターンマッチングをしているらしい。
_Tyがまだ決まって無い段階で、remove_reference<_Ty> というテンプレートclass を展開してtype メンバを調べ、それと実引数から右辺値参照部分を除いた部分を一致させるような複雑な処理をした結果、_Ty を逆算して決定しているらしい。
template <class _Ty>
struct remove_reference { // YA, #1, primary class template。"
using type = _Ty; // const も保存されているハズ。
using _Const_thru_ref_type = const _Ty;
};
・・・ remove_reference<> に対する部分特殊化があるが、省略 ・・・
template <class _Ty>
using remove_reference_t = typename remove_reference<_Ty>::type;
template <class _Ty>
_NODISCARD constexpr _Ty&& forward(remove_reference_t<_Ty>&& _Arg) noexcept { // forward an rvalue as an rvalue
static_assert(!is_lvalue_reference_v<_Ty>, "bad forward call");
return static_cast<_Ty&&>(_Arg);
}
217デフォルトの名無しさん
2020/06/03(水) 19:08:51.14ID:TdRUmxlv >>215
仮に心の中にあってもあなたは全く言語化して無いないので駄目。
仮に心の中にあってもあなたは全く言語化して無いないので駄目。
218デフォルトの名無しさん
2020/06/03(水) 19:10:26.76ID:TdRUmxlv219デフォルトの名無しさん
2020/06/03(水) 19:14:50.42ID:TdRUmxlv >>218
そういえば仕様書に、templateをinstance化する際は、既に deducedされたパラメータは A<B>のBの中には書かないで良い例が書いてあった。
たとえば、
template <typename T1, typename T2>T1 f(T2 a);
のような場合、
f<T1>(100);
みたいにすれば、T2はint型だと分かるので、f<T1,int>(100)と書かなくて良いというもの。
それかな?
そういえば仕様書に、templateをinstance化する際は、既に deducedされたパラメータは A<B>のBの中には書かないで良い例が書いてあった。
たとえば、
template <typename T1, typename T2>T1 f(T2 a);
のような場合、
f<T1>(100);
みたいにすれば、T2はint型だと分かるので、f<T1,int>(100)と書かなくて良いというもの。
それかな?
220デフォルトの名無しさん
2020/06/03(水) 19:17:57.22ID:TdRUmxlv そうではなく、>>190 の場合は、primary template として、
template <typename T, typename = void>
struct has_typedef_foobar : std::false_type {};
と、第二パラメータにデフォルト引数が書いてあるからか。
template <typename T, typename = void>
struct has_typedef_foobar : std::false_type {};
と、第二パラメータにデフォルト引数が書いてあるからか。
221デフォルトの名無しさん
2020/06/03(水) 19:20:51.92ID:HVfXpWIv >>218
190ってまさにtypename=voidしている例じゃね
190ってまさにtypename=voidしている例じゃね
222デフォルトの名無しさん
2020/06/03(水) 19:27:23.10ID:TdRUmxlv223デフォルトの名無しさん
2020/06/03(水) 19:48:21.19ID:XMrfvYH7 TdRUmxlvは自分の日記帳に書いてくんないかな
224デフォルトの名無しさん
2020/06/03(水) 20:15:01.97ID:TdRUmxlv 失礼しました。
でも断っておくと、俺ははちみつに対してそんなに悪口は言ってない。
スレの流れで混乱していたようだが、言っていたのは別人だから悪しからず。
でも断っておくと、俺ははちみつに対してそんなに悪口は言ってない。
スレの流れで混乱していたようだが、言っていたのは別人だから悪しからず。
225デフォルトの名無しさん
2020/06/03(水) 22:21:05.04ID:OT4MJN13 いちいちイラッとする書きっぷりはID:TdRUmxlvのコミュ力が絶望的に低くいだけなので許してあげてください
226デフォルトの名無しさん
2020/06/03(水) 23:25:41.73ID:SSmphgFp 憂さ晴らしに靖国に落書きしそう
227デフォルトの名無しさん
2020/06/04(木) 08:16:53.40ID:85VTz4/e とっくにNG
228デフォルトの名無しさん
2020/06/04(木) 13:15:35.94ID:pT22FhoL int& r_i=7; // compile error
int&& rr_i=7; // OK
2行目は、どういう仕組みになってるんでしょう?
7という値がメモリー上にはどこにも存在して無い場合もあるはずで、
その場合でも右辺値参照を持てるものなのでしょうか?
たとえばコンパイラの中に7という値は持っていても、アセンブラレベルでは、
どのsectionの中にも7というデータが入れられて無い場合もあると思うのです。
それだと7の入っている場所のアドレスは存在しえません。
例え「"右辺値"参照」であってもはアドレスが必要のはずですが。
int&& rr_i=7; // OK
2行目は、どういう仕組みになってるんでしょう?
7という値がメモリー上にはどこにも存在して無い場合もあるはずで、
その場合でも右辺値参照を持てるものなのでしょうか?
たとえばコンパイラの中に7という値は持っていても、アセンブラレベルでは、
どのsectionの中にも7というデータが入れられて無い場合もあると思うのです。
それだと7の入っている場所のアドレスは存在しえません。
例え「"右辺値"参照」であってもはアドレスが必要のはずですが。
229デフォルトの名無しさん
2020/06/04(木) 13:17:22.86ID:+U2drwkO 構ってはいけない
230デフォルトの名無しさん
2020/06/04(木) 14:43:12.11ID:2rF1/e7a >>228
言語規格的にはrr_iという名前を通じて7という値が取れれば何でもいい
コンパイラが具体的にどうするかはコンパイラの勝手
アドレスがどこかで必要なら一時オブジェクトを作るようにするし必要なければ作らなくてもいい
言語規格的にはrr_iという名前を通じて7という値が取れれば何でもいい
コンパイラが具体的にどうするかはコンパイラの勝手
アドレスがどこかで必要なら一時オブジェクトを作るようにするし必要なければ作らなくてもいい
231デフォルトの名無しさん
2020/06/04(木) 18:50:33.11ID:pT22FhoL232デフォルトの名無しさん
2020/06/07(日) 01:50:09.38ID:P1Z5Y5je233デフォルトの名無しさん
2020/06/07(日) 01:57:43.49ID:loMZGJMS &&嫌いだわ
234デフォルトの名無しさん
2020/06/07(日) 03:20:06.67ID:NFGxwtnl 右辺値参照自身は左辺値定期
235はちみつ餃子 ◆8X2XSCHEME
2020/06/07(日) 09:08:16.75ID:fhJ4vSsJ だから std::forward が要るんだよ。
236デフォルトの名無しさん
2020/06/07(日) 11:40:26.26ID:uPPavgXr 昔のソースコードからの派生で開発する際、リソースの開放だけをデストラクタで行うように変えたいと考えています
RAIIだけを行う標準的な実装って何かあったりしますか?
あるいは、自分で調べた限りでは例えば、
HANDLE hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
unique_ptr<void, decltype(&CloseHandle)> dummy(hFile, CloseHandle);
// 以降dummyは使わずに生のhFileに対して操作
のようにunique_ptrを使えばできそうに見えますが、C++11以降の作法として正しいでしょうか?
RAIIだけを行う標準的な実装って何かあったりしますか?
あるいは、自分で調べた限りでは例えば、
HANDLE hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
unique_ptr<void, decltype(&CloseHandle)> dummy(hFile, CloseHandle);
// 以降dummyは使わずに生のhFileに対して操作
のようにunique_ptrを使えばできそうに見えますが、C++11以降の作法として正しいでしょうか?
237デフォルトの名無しさん
2020/06/07(日) 13:44:00.54ID:ocvuft6U 作法とか正しいとかより自分で考えた方がいいと思うけど
その場合あえて言えば、hFile渡すとこは
直接CreateFileの戻り値使って(hFileを宣言しない)、dummyの持つハンドル経由で使った方が
一貫性が取れていいかも
理想を言えば全部ラップした方がいいんだろうけど
その場合あえて言えば、hFile渡すとこは
直接CreateFileの戻り値使って(hFileを宣言しない)、dummyの持つハンドル経由で使った方が
一貫性が取れていいかも
理想を言えば全部ラップした方がいいんだろうけど
238デフォルトの名無しさん
2020/06/07(日) 13:55:18.98ID:HzkE9Nko239デフォルトの名無しさん
2020/06/07(日) 14:54:05.65ID:HzkE9Nko >>238
RAIIというのは物凄く簡単に実装できて、細かいことを抜きにすれば以下の様にすれば完成する :
class CMyX {
protected:
HANDLE m_hFile;
public:
CMyX(HANDLE hFile) {m_hFile=hFile;}
~CMyX() {CloseHandle(m_hFile);}
}
HANDLE hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
CMyX myx(hFile); // これが初期化。後は勝手に hFileが解放される。
RAIIというのは物凄く簡単に実装できて、細かいことを抜きにすれば以下の様にすれば完成する :
class CMyX {
protected:
HANDLE m_hFile;
public:
CMyX(HANDLE hFile) {m_hFile=hFile;}
~CMyX() {CloseHandle(m_hFile);}
}
HANDLE hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
CMyX myx(hFile); // これが初期化。後は勝手に hFileが解放される。
240デフォルトの名無しさん
2020/06/07(日) 15:37:10.54ID:NFGxwtnl ポインタ以外のリソースでRAIIやらせるためのstd::unique_resourceが提案されてるけど難航してる
リソースの種類や使い方でそれぞれ事情が違うから無理矢理一般化しても上手く行かないらしい
リソースの種類や使い方でそれぞれ事情が違うから無理矢理一般化しても上手く行かないらしい
241デフォルトの名無しさん
2020/06/07(日) 15:48:34.18ID:HzkE9Nko >>239
補足すると、このコードだとCreateFile()した後、返されたハンドル値を No CheckでCMyXのコンストラクタに渡しているが、本当はその前にINVALID_HANDLE_VALUEかどうかをチェックしておく必要がある。
補足すると、このコードだとCreateFile()した後、返されたハンドル値を No CheckでCMyXのコンストラクタに渡しているが、本当はその前にINVALID_HANDLE_VALUEかどうかをチェックしておく必要がある。
242デフォルトの名無しさん
2020/06/07(日) 21:39:58.03ID:P1Z5Y5je243デフォルトの名無しさん
2020/06/07(日) 21:49:43.50ID:NFGxwtnl それがエラーじゃなかったら右辺値参照は何のためにあるんだよ
244デフォルトの名無しさん
2020/06/07(日) 21:56:24.65ID:P1Z5Y5je245デフォルトの名無しさん
2020/06/07(日) 22:22:50.71ID:uPPavgXr246デフォルトの名無しさん
2020/06/07(日) 23:16:58.32ID:+YSUT0gy More Effective C++ の、
項目9 : リソースリークを防ぐためにデストラクタを使う
項目11 : デストラクタから発生した例外を抑える
デストラクタ中で、例外がキャッチされない場合、
terminate を呼ばれて、受け身も取れず、強制終了させられる
項目9 : リソースリークを防ぐためにデストラクタを使う
項目11 : デストラクタから発生した例外を抑える
デストラクタ中で、例外がキャッチされない場合、
terminate を呼ばれて、受け身も取れず、強制終了させられる
247デフォルトの名無しさん
2020/06/08(月) 11:21:10.82ID:KlUsfYw8 >>245
CreateFile以外にも似たようなのが沢山あって、それを楽にRAIIにしたいって話?
ならすでにunique_resourceはあるらしいけど(experimentalだかどこかに
あるいはそれに近い実装も公開されてるので落としてくればいいかと
逆にCreateFileだけなら素直に自分でクラス書いた方が後々楽になると思う
CreateFile以外にも似たようなのが沢山あって、それを楽にRAIIにしたいって話?
ならすでにunique_resourceはあるらしいけど(experimentalだかどこかに
あるいはそれに近い実装も公開されてるので落としてくればいいかと
逆にCreateFileだけなら素直に自分でクラス書いた方が後々楽になると思う
248はちみつ餃子 ◆8X2XSCHEME
2020/06/08(月) 12:33:58.17ID:KAmnJXdU リソースの解放以外は生のハンドルが使いたいという前提だと、
「unique_resource で包まれたオブジェクトからハンドル使うたびに (get で) 取り出す」という操作が必要になる。
たぶん >>236 の書きようだとそういうことはしたくないんだろうし、
包む前のハンドル (が入った変数) をそのまま使うとなると折角の所有権管理が台無しだ。
unique_resource はリソースの所有権管理の仕組みであって、
デストラクタでリソース解放もするのは所有権管理に付随するものに過ぎない。
どちらかというと scope_exit の方がやりたいことに近そうな気がする。
けど、いずれにしても中途半端なんだよな。
現時点でリソースの解放 (CloseHandle) がちゃんとできているなら
それを unique_resource (なり scope_exit なり) に置き換える意味はあまりないんじゃなかろうか。
「CloseHandle の書き漏らし」ってのと「scope_exit の書き忘れ」
ってのは同程度に有り得ることで、そんなに良くならないと思うよ。
型としての HANDLE の実態は void* なので、
HANDLE を HANDLE として扱おうとする限り C++ の型システムの恩恵はあまり受けられない。
古いコードをなるべくいじらずに使いたいという理由はとてもよくわかるのだけれど、
半端な書き換えをするくらいなら抽象レイヤをきちんと構築した方が結局は楽だと思う。
「unique_resource で包まれたオブジェクトからハンドル使うたびに (get で) 取り出す」という操作が必要になる。
たぶん >>236 の書きようだとそういうことはしたくないんだろうし、
包む前のハンドル (が入った変数) をそのまま使うとなると折角の所有権管理が台無しだ。
unique_resource はリソースの所有権管理の仕組みであって、
デストラクタでリソース解放もするのは所有権管理に付随するものに過ぎない。
どちらかというと scope_exit の方がやりたいことに近そうな気がする。
けど、いずれにしても中途半端なんだよな。
現時点でリソースの解放 (CloseHandle) がちゃんとできているなら
それを unique_resource (なり scope_exit なり) に置き換える意味はあまりないんじゃなかろうか。
「CloseHandle の書き漏らし」ってのと「scope_exit の書き忘れ」
ってのは同程度に有り得ることで、そんなに良くならないと思うよ。
型としての HANDLE の実態は void* なので、
HANDLE を HANDLE として扱おうとする限り C++ の型システムの恩恵はあまり受けられない。
古いコードをなるべくいじらずに使いたいという理由はとてもよくわかるのだけれど、
半端な書き換えをするくらいなら抽象レイヤをきちんと構築した方が結局は楽だと思う。
249デフォルトの名無しさん
2020/06/08(月) 15:51:51.35ID:blut5LG8 void * と型として区別出来ない?
型はともかくそもそも HANDLE は値の範囲が決まってたか
型はともかくそもそも HANDLE は値の範囲が決まってたか
250はちみつ餃子 ◆8X2XSCHEME
2020/06/08(月) 16:16:36.67ID:KAmnJXdU かなり前から DECLARE_HANDLE マクロで HANDLE は固有の型として定義してた。
そこは私の認識間違いだ。 すまぬ。
>>249
void* という型として認識出来たところで何が出来るものでもないよねという意図だった。
そこは私の認識間違いだ。 すまぬ。
>>249
void* という型として認識出来たところで何が出来るものでもないよねという意図だった。
251デフォルトの名無しさん
2020/06/08(月) 23:54:23.01ID:3GgB/ZcK252デフォルトの名無しさん
2020/06/08(月) 23:56:48.34ID:3GgB/ZcK というわけでget()メソッドが無いのも大概だが
それより悪いのはCloseHandle()が失敗したときのことを何も考えていないことだ
ファイルのClose失敗はエラーハンドリング省略で済まされる問題ではない
デストラクタでCloseHandle()を一概に否定するものではないが、
デストラクタから例外を飛ばすわけにもいかないので、エラーの通知先オブジェクトへのポインタをCMyXは持つ必要がある
それより悪いのはCloseHandle()が失敗したときのことを何も考えていないことだ
ファイルのClose失敗はエラーハンドリング省略で済まされる問題ではない
デストラクタでCloseHandle()を一概に否定するものではないが、
デストラクタから例外を飛ばすわけにもいかないので、エラーの通知先オブジェクトへのポインタをCMyXは持つ必要がある
253デフォルトの名無しさん
2020/06/09(火) 00:00:40.22ID:Ah9aU5+0 いきってツッコむほどのことかそれ
254デフォルトの名無しさん
2020/06/09(火) 03:22:41.56ID:SETbyCsO >>252
File Handle のような OS Object については、RAIIで処理するのは実は難しいんだよ。
だから、WindowのDestroyWindow()もデストラクタで処理する前に明示的に
CWnd::DestoryWindow()を自分で呼び出すほうが良かったりするんだから。
デストラクタだけを頼りにすると、main()やWinMain()関数の後の
クリーンアップ処理の中で CloseHandle()が呼び出されたりすることになるが、
それは結構微妙な話になる。
なぜかといえば、まず、OS自体がそもそも、プロセスが終了する時には
勝手にすべてのハンドルを閉じてくれる。ならば、CloseHandle()なんて明示的に
書く必要が無い、というそもそも論が出てくる。
それプラス、あなたが言ったように、CloseHandle()で失敗した場合にどうなるか
という話もあることはある。
そもそも、個人的には、ファイルを開いたら、なるべく速く Closeする方が良いと思っている
ので、RAIIでファイルハンドルを処理するのは余りぴんと来ない。
File Handle のような OS Object については、RAIIで処理するのは実は難しいんだよ。
だから、WindowのDestroyWindow()もデストラクタで処理する前に明示的に
CWnd::DestoryWindow()を自分で呼び出すほうが良かったりするんだから。
デストラクタだけを頼りにすると、main()やWinMain()関数の後の
クリーンアップ処理の中で CloseHandle()が呼び出されたりすることになるが、
それは結構微妙な話になる。
なぜかといえば、まず、OS自体がそもそも、プロセスが終了する時には
勝手にすべてのハンドルを閉じてくれる。ならば、CloseHandle()なんて明示的に
書く必要が無い、というそもそも論が出てくる。
それプラス、あなたが言ったように、CloseHandle()で失敗した場合にどうなるか
という話もあることはある。
そもそも、個人的には、ファイルを開いたら、なるべく速く Closeする方が良いと思っている
ので、RAIIでファイルハンドルを処理するのは余りぴんと来ない。
255デフォルトの名無しさん
2020/06/09(火) 06:33:30.92ID:iLzxHGzP アプリ全体の終了が前提になっているおかしな主張だな
256デフォルトの名無しさん
2020/06/09(火) 06:54:05.72ID:unijwXHc CloseHandleやfileのcloseで失敗する様な状況って、普通のアプリじゃ実質対処不能な致命的な状態だろ
素直に落ちるなりおかしな挙動になるなりすればいいのよ
素直に落ちるなりおかしな挙動になるなりすればいいのよ
257デフォルトの名無しさん
2020/06/09(火) 07:55:59.54ID:n28tZ6EV OSやハードが正常稼働時ならそこら辺の例外発生はないからね。
リソース解放忘れてデスクリプタやらのリソース使い果たしたり、ファイルの占有したままで他のアプリに迷惑かけたりするのを防止するのにRAII使うのは有用
リソース解放忘れてデスクリプタやらのリソース使い果たしたり、ファイルの占有したままで他のアプリに迷惑かけたりするのを防止するのにRAII使うのは有用
258デフォルトの名無しさん
2020/06/09(火) 08:00:35.85ID:JJE9ezaH HANDLEってOS側からはそれが有効か無効か判断できるから、無効なハンドルを
間違って使ったりCloseHandleしてしまってもエラーを返すだけで致命的な状態には
なりにくい
間違って使ったりCloseHandleしてしまってもエラーを返すだけで致命的な状態には
なりにくい
259865
2020/06/09(火) 09:27:54.99ID:cTF8gHLn 前提にしているのがどんなOSであろうと
C++的には環境依存な話だね
C++的には環境依存な話だね
260デフォルトの名無しさん
2020/06/09(火) 15:37:05.70ID:FUnSNOef 要素はintと任意オブジェ
int値を渡すと
論理和がゼロ以外の要素を
返すコンテナってないですか?
int値を渡すと
論理和がゼロ以外の要素を
返すコンテナってないですか?
261デフォルトの名無しさん
2020/06/09(火) 16:12:25.38ID:SETbyCsO >>256
もし、CTRL+Sを処理するイベントハンドラの中で、単純に CloseHandle()を自分で呼び出して
失敗した場合であれば、保存に失敗した事をAfxMessageBox()で知らせた後、なんとか今までの
メモリ中のデータだけは壊さずに処理できればベスト。
しかし、他の何らかの例外が発生した時に、RAIIによって自動的に呼び出されたデストラクタの中で
CloseHandle()に失敗した場合には、対処が難しそう。
テストも難しいし、余りそういう状況は起きないので優先順位は低いが。
もし、CTRL+Sを処理するイベントハンドラの中で、単純に CloseHandle()を自分で呼び出して
失敗した場合であれば、保存に失敗した事をAfxMessageBox()で知らせた後、なんとか今までの
メモリ中のデータだけは壊さずに処理できればベスト。
しかし、他の何らかの例外が発生した時に、RAIIによって自動的に呼び出されたデストラクタの中で
CloseHandle()に失敗した場合には、対処が難しそう。
テストも難しいし、余りそういう状況は起きないので優先順位は低いが。
262デフォルトの名無しさん
2020/06/09(火) 17:15:04.89ID:nNNGB7r+ >>260
std::pair<int, SomeObj> を格納するコンテナと
「int部分とある値とのビットORを結果とする述語」を
std::copy_if() に渡すような話かな。
「任意オブジェ」部分が要素ごとに異なる、だと難問な気がするけど。
std::pair<int, SomeObj> を格納するコンテナと
「int部分とある値とのビットORを結果とする述語」を
std::copy_if() に渡すような話かな。
「任意オブジェ」部分が要素ごとに異なる、だと難問な気がするけど。
263デフォルトの名無しさん
2020/06/09(火) 17:30:16.71ID:n28tZ6EV 論理積ではなく?
264デフォルトの名無しさん
2020/06/09(火) 17:42:20.88ID:nNNGB7r+ 確かに論理和だと「つまらない」結果になりそうね。
普通の使い方なら論理積で抽出か。
排他的論理和は「もっと面白い」かも知れんけど。
普通の使い方なら論理積で抽出か。
排他的論理和は「もっと面白い」かも知れんけど。
265デフォルトの名無しさん
2020/06/09(火) 22:35:23.41ID:FUnSNOef266デフォルトの名無しさん
2020/06/10(水) 05:39:12.94ID:67cF/bBY >>256
「ログファイルなので書込みに失敗しても大勢に影響が無い」とか
「作業用ファイルfは書いた後必ず誰かがリードオープンするから書込みに失敗していたらそこでワカルから書込みのエラーチェックを省略する」
みたいな判断はアプリの設計としてはアリかもしれないが、CMyHandleみたいな汎用部品的に使われ得る低水準クラスではナシ
これをアリだと思う香具師はお気楽すぐる、
「ログファイルなので書込みに失敗しても大勢に影響が無い」とか
「作業用ファイルfは書いた後必ず誰かがリードオープンするから書込みに失敗していたらそこでワカルから書込みのエラーチェックを省略する」
みたいな判断はアプリの設計としてはアリかもしれないが、CMyHandleみたいな汎用部品的に使われ得る低水準クラスではナシ
これをアリだと思う香具師はお気楽すぐる、
268デフォルトの名無しさん
2020/06/10(水) 07:23:10.62ID:itI4VuCe てか、自動解放するクラス作っても手動解放する手段残しておけば、使う側で特別な処理は出来るんだよね
269デフォルトの名無しさん
2020/06/10(水) 08:13:57.83ID:V+CQutVh C++ではexitをD組にして欲しい
270デフォルトの名無しさん
2020/06/10(水) 12:31:11.80ID:BPKUZfdj >>267 通知は欲しいかな。
黙って動作が続くくよりは terminate() のほうがマシだとも思うし。汎用部品ならなおさら。
破棄失敗する可能性のあるリソースの RAII wrapper にはエラー通知できる
close() なりの破棄操作を別に用意しておけという話で済むと思う。
黙って動作が続くくよりは terminate() のほうがマシだとも思うし。汎用部品ならなおさら。
破棄失敗する可能性のあるリソースの RAII wrapper にはエラー通知できる
close() なりの破棄操作を別に用意しておけという話で済むと思う。
>>270
通知って簡単にいいますけれども、その例えば fclose() 失敗の通知をどこに送り、そして送った先では何をするのですか?
通知をもらって何か手を打てるのですか?
汎用部品/ライブラリの作法ですか
理解はできますが、しかし、何もできないのなら、あるいは何もできないことがわかっているのなら、特段の失着にはみえませんね…
通知って簡単にいいますけれども、その例えば fclose() 失敗の通知をどこに送り、そして送った先では何をするのですか?
通知をもらって何か手を打てるのですか?
汎用部品/ライブラリの作法ですか
理解はできますが、しかし、何もできないのなら、あるいは何もできないことがわかっているのなら、特段の失着にはみえませんね…
272デフォルトの名無しさん
2020/06/10(水) 21:56:31.91ID:yfneRFZn 大事なデータを保存したファイルのfclose()が失敗したらどうするかって?
場所変えて保存を試みるに決まってるだろ
それくらいしないプログラムは売り物にならないぞ
場所変えて保存を試みるに決まってるだろ
それくらいしないプログラムは売り物にならないぞ
273デフォルトの名無しさん
2020/06/10(水) 22:20:00.38ID:yQDU6thd そもそも仕様で指定があるならそのように書くだけなんじゃ
274デフォルトの名無しさん
2020/06/11(木) 00:27:51.81ID:flOLYJrB >>271
たとえばコンソールアプリなら標準エラーに情報を出したうえで終了コードに反映して、
コマンドが失敗したのを見たユーザーが何をするか考えるっていうのはごく当たり前のことでしょ。
たとえばストレージ容量が足りないとして失敗したなら容量を確保して再実行すればいい。
fclose() の戻り値を捨ててるプログラムは現実としてたぶん多いんだけど、
そんなソフトがたとえばサーバー内でストレージ容量不足を数か月にわたって闇に葬り続け、
何かおかしいと気付いたサーバー管理者が自動スクリプトを緻密にトレースした結果、
保存されているはずの情報がもはやどこにも存在しないと気付いた時の怒り憎しみ悲しみを想像されたい。
少なくとも成功したと誤解しないのが重要。
たとえばコンソールアプリなら標準エラーに情報を出したうえで終了コードに反映して、
コマンドが失敗したのを見たユーザーが何をするか考えるっていうのはごく当たり前のことでしょ。
たとえばストレージ容量が足りないとして失敗したなら容量を確保して再実行すればいい。
fclose() の戻り値を捨ててるプログラムは現実としてたぶん多いんだけど、
そんなソフトがたとえばサーバー内でストレージ容量不足を数か月にわたって闇に葬り続け、
何かおかしいと気付いたサーバー管理者が自動スクリプトを緻密にトレースした結果、
保存されているはずの情報がもはやどこにも存在しないと気付いた時の怒り憎しみ悲しみを想像されたい。
少なくとも成功したと誤解しないのが重要。
275デフォルトの名無しさん
2020/06/11(木) 06:18:34.85ID:m7gaY4Qp そんな状況じゃopenも失敗してるだろうな
276デフォルトの名無しさん
2020/06/11(木) 09:58:48.19ID:Th6rh/3U >>274
実はそれがRAIIの限界なんだよ。
ちゃんと明示的に fclose() してその戻り値をチェックするのが一番安全。
例外安全性のためにRAIIを使うべきという人が居るけど、それで勝手に
デストラクタ内でfclose()して容量不足やディスクエラーで書き込み失敗した時には、
多くの場合、対処に困る。
でも、例外安全のためにはそうせざるを得ないかも知れない。
ということは、そもそも論になり、例外の throw、catch機構自体が安全に扱うのが
難しいという結論に至り、議論百出する。
実はそれがRAIIの限界なんだよ。
ちゃんと明示的に fclose() してその戻り値をチェックするのが一番安全。
例外安全性のためにRAIIを使うべきという人が居るけど、それで勝手に
デストラクタ内でfclose()して容量不足やディスクエラーで書き込み失敗した時には、
多くの場合、対処に困る。
でも、例外安全のためにはそうせざるを得ないかも知れない。
ということは、そもそも論になり、例外の throw、catch機構自体が安全に扱うのが
難しいという結論に至り、議論百出する。
277デフォルトの名無しさん
2020/06/11(木) 10:29:20.16ID:flOLYJrB278デフォルトの名無しさん
2020/06/11(木) 10:38:30.62ID:3eiGl155 上から目線なくせに脇が甘いな
279はちみつ餃子 ◆8X2XSCHEME
2020/06/11(木) 11:08:58.38ID:7wv0rqaB デストラクタ内でエラーが発生する可能性があってそれに対処が必要なら
例外の送出とか言ってないでデストラクタ内で対処してしまえよ。
汎用的な部品にし難いのはしゃーないやろ。
実際に汎用的ではないんだから。
例外の送出とか言ってないでデストラクタ内で対処してしまえよ。
汎用的な部品にし難いのはしゃーないやろ。
実際に汎用的ではないんだから。
280デフォルトの名無しさん
2020/06/11(木) 11:47:39.02ID:DcPEy/qZ おまいら (f)printf() の戻り値もちゃんと毎回観てるか?
281デフォルトの名無しさん
2020/06/11(木) 11:54:46.87ID:Th6rh/3U282デフォルトの名無しさん
2020/06/11(木) 11:56:16.72ID:Th6rh/3U283デフォルトの名無しさん
2020/06/11(木) 12:17:49.27ID:3eiGl155 そんなに難しいか?
深刻な事態が疑われるならシステムモーダルダイアログなり何なりすることあるだろ
あくまでOSではなくアプリとして事後条件が保証できない場合はterminateを呼び出して
OSに事故としての扱いをさせるのが「難しい」のは思いつかないだけじゃねえだろな
プログラミング以外の仕事でも事故はまず報連相
1人で握りつぶそうとするのは学生気分が抜けてないやつのすることだ
深刻な事態が疑われるならシステムモーダルダイアログなり何なりすることあるだろ
あくまでOSではなくアプリとして事後条件が保証できない場合はterminateを呼び出して
OSに事故としての扱いをさせるのが「難しい」のは思いつかないだけじゃねえだろな
プログラミング以外の仕事でも事故はまず報連相
1人で握りつぶそうとするのは学生気分が抜けてないやつのすることだ
284デフォルトの名無しさん
2020/06/11(木) 12:19:04.03ID:flOLYJrB285デフォルトの名無しさん
2020/06/11(木) 12:21:07.06ID:flOLYJrB >>283 そっか GUI ならダイアログ使えるから、通知するだけなら簡単だね。
286デフォルトの名無しさん
2020/06/11(木) 12:22:43.78ID:Th6rh/3U287デフォルトの名無しさん
2020/06/11(木) 12:29:07.29ID:Th6rh/3U >>283
Exceptionをthrowした時の自動フォローアップとしてRAIIのデストラクタが呼び出される。
それが呼び出されるのは原則的にどこかでかは余り仮定できない。
ということは、非常に変なタイミングで fclose()に失敗することがある。
メッセージボックスを出すと、そこでイベントに対するメッセージループが形成されるので、
タイマーイベントのハンドラのOnTimer()などが起動してしまうこともある。
OnTimer()を、Exceptionがthrowされた状態で実行してよいかどうかは注意を要する事だ。
また、アプリの初期化処理の InitInstance()や終了処理のExitInstance()の中で、RAIIの
デストラクタが呼び出されてしまう場合もあるかも知れず、その中でメッセージボックスを
出すと思わぬ問題が生じるかもしれない。
生じないかも知れないが。
ただ、Exceptionがthrowされたということは何か異常が生じているということで、
それがたまたまファイルに関するものであったとしたら、二重三重に、ファイル関連で
エラーが生じてしまい、何か危険な状態に陥ってしまう可能性も有るかも知れない。
そういう微妙な配慮が必要となる。
Exceptionをthrowした時の自動フォローアップとしてRAIIのデストラクタが呼び出される。
それが呼び出されるのは原則的にどこかでかは余り仮定できない。
ということは、非常に変なタイミングで fclose()に失敗することがある。
メッセージボックスを出すと、そこでイベントに対するメッセージループが形成されるので、
タイマーイベントのハンドラのOnTimer()などが起動してしまうこともある。
OnTimer()を、Exceptionがthrowされた状態で実行してよいかどうかは注意を要する事だ。
また、アプリの初期化処理の InitInstance()や終了処理のExitInstance()の中で、RAIIの
デストラクタが呼び出されてしまう場合もあるかも知れず、その中でメッセージボックスを
出すと思わぬ問題が生じるかもしれない。
生じないかも知れないが。
ただ、Exceptionがthrowされたということは何か異常が生じているということで、
それがたまたまファイルに関するものであったとしたら、二重三重に、ファイル関連で
エラーが生じてしまい、何か危険な状態に陥ってしまう可能性も有るかも知れない。
そういう微妙な配慮が必要となる。
288デフォルトの名無しさん
2020/06/11(木) 12:33:42.17ID:Th6rh/3U >>287
もっといえば、Exceptionのthrowはどこで起きるかは仮定しにくいものなので、
何らかのダイアログを出すための初期化処理の中で生じることも有るかも知れない。
そういう場合にたまたま、関数の呼びだし元へ どんどん Exception の Unwinding
が生じて、RAIIのデストラクタで fclose()が呼び出される可能性も有るかも知れない。
そうなって、さらに、その fclose()がエラー終了する場合がある。
ダイアログの生成に失敗したタイミングで、エラーメッセージの表示のために、
メッセージボックスのダイアログを出すことになれば、もしかしたらかなり危険な
バグを含むことになってしまうかも知れない。
もっといえば、Exceptionのthrowはどこで起きるかは仮定しにくいものなので、
何らかのダイアログを出すための初期化処理の中で生じることも有るかも知れない。
そういう場合にたまたま、関数の呼びだし元へ どんどん Exception の Unwinding
が生じて、RAIIのデストラクタで fclose()が呼び出される可能性も有るかも知れない。
そうなって、さらに、その fclose()がエラー終了する場合がある。
ダイアログの生成に失敗したタイミングで、エラーメッセージの表示のために、
メッセージボックスのダイアログを出すことになれば、もしかしたらかなり危険な
バグを含むことになってしまうかも知れない。
289デフォルトの名無しさん
2020/06/11(木) 12:49:26.16ID:flOLYJrB >>286-288
ごめん、別の例外でスタック巻き戻し中の fclose() 失敗は無視でもいい想定だった。
元の例外が通知されればそれでいいだろうと。
破棄操作を提供すれば済むっていうのは、たとえば fstream について
正常フローから close() 呼び出せば fclose() の失敗は普通に処理できるっていう意味。
エラー発生後の後処理でのエラーについてはもはや例外処理機構とか RAII とか関係なく
エラー処理一般で難しさは変わらないのでは?
ごめん、別の例外でスタック巻き戻し中の fclose() 失敗は無視でもいい想定だった。
元の例外が通知されればそれでいいだろうと。
破棄操作を提供すれば済むっていうのは、たとえば fstream について
正常フローから close() 呼び出せば fclose() の失敗は普通に処理できるっていう意味。
エラー発生後の後処理でのエラーについてはもはや例外処理機構とか RAII とか関係なく
エラー処理一般で難しさは変わらないのでは?
290デフォルトの名無しさん
2020/06/11(木) 13:14:41.21ID:4Jo+eUkD291デフォルトの名無しさん
2020/06/11(木) 17:56:16.10ID:+WuQ8P1K そんなに大事なデータならverifyするだろ
292デフォルトの名無しさん
2020/06/13(土) 16:05:30.52ID:ifM7/RIh >>271
>知って簡単にいいますけれども、その例えば fclose() 失敗の通知をどこに送り、そして送った先では何をするのですか?
最終的にはユーザーに通知する
>通知をもらって何か手を打てるのですか?
ユーザーが通知に従い手を打てる
>>279
デストラクタ内での例外を送出したら即アプリが死ぬハズ
コアを吐いてくれたら通知にあたる情報が取り出せるかもしれないが美しくない
>>287
異常の内容をユーザーに通知することを目的とするなら
>エラーの通知先オブジェクトへのポインタをCMyXは持つ(>>252)
で事足りる
メッセージループは、通知先オブジェクトが1個だけもちさえすればユーザーへの通知の役目を果たせる
CMyXのようなケースは通知先オブジェクトを保持するオブジェクトからFactoryMethodパターンでインスタンス化
するのがいかにもOOP的で個人的には好み(CMyXのインスタンス化のときに通知先を確実に渡せる
>知って簡単にいいますけれども、その例えば fclose() 失敗の通知をどこに送り、そして送った先では何をするのですか?
最終的にはユーザーに通知する
>通知をもらって何か手を打てるのですか?
ユーザーが通知に従い手を打てる
>>279
デストラクタ内での例外を送出したら即アプリが死ぬハズ
コアを吐いてくれたら通知にあたる情報が取り出せるかもしれないが美しくない
>>287
異常の内容をユーザーに通知することを目的とするなら
>エラーの通知先オブジェクトへのポインタをCMyXは持つ(>>252)
で事足りる
メッセージループは、通知先オブジェクトが1個だけもちさえすればユーザーへの通知の役目を果たせる
CMyXのようなケースは通知先オブジェクトを保持するオブジェクトからFactoryMethodパターンでインスタンス化
するのがいかにもOOP的で個人的には好み(CMyXのインスタンス化のときに通知先を確実に渡せる
293はちみつ餃子 ◆8X2XSCHEME
2020/06/13(土) 16:59:34.64ID:1nypd8FJ >>292
私が書いた >>279 ではデストラクタ内で対処を完結させろ (例外を投げずに済ますために) と書いてあるつもりなんだが、お前にはそれが読み取れなかったか?
ちなみに、現在の C++ ではデストラクタ (と delete) はデフォルトで noexcept で修飾されているものと見なされる。
これは例外を外へ送出しないことを保障するんだが、内部で例外が発生しないとは保証されない。
もし発生した例外を内部でキャッチせずに外へ出ていこうとしたら std::terminate() が呼び出される。
(スタックの巻き戻しは起こらずに即死するかもしれない。)
陽に noexcept(false) を指定したらデストラクタから例外を送出することは可能。
ただし、スタックの巻き戻し中に起動される別のデストラクタから例外が送出されると死ぬ。
普通は色々なライブラリを組み合わせるから問題が出ないようにするには
一貫してデストラクタからは例外を投げないのが妥当な設計だと考えられているってだけ。
私が書いた >>279 ではデストラクタ内で対処を完結させろ (例外を投げずに済ますために) と書いてあるつもりなんだが、お前にはそれが読み取れなかったか?
ちなみに、現在の C++ ではデストラクタ (と delete) はデフォルトで noexcept で修飾されているものと見なされる。
これは例外を外へ送出しないことを保障するんだが、内部で例外が発生しないとは保証されない。
もし発生した例外を内部でキャッチせずに外へ出ていこうとしたら std::terminate() が呼び出される。
(スタックの巻き戻しは起こらずに即死するかもしれない。)
陽に noexcept(false) を指定したらデストラクタから例外を送出することは可能。
ただし、スタックの巻き戻し中に起動される別のデストラクタから例外が送出されると死ぬ。
普通は色々なライブラリを組み合わせるから問題が出ないようにするには
一貫してデストラクタからは例外を投げないのが妥当な設計だと考えられているってだけ。
294デフォルトの名無しさん
2020/06/13(土) 17:06:07.88ID:ifM7/RIh295デフォルトの名無しさん
2020/06/13(土) 20:11:16.15ID:K/U+GWpl 個人でc++使うことは少ないですか?
C#やelectronと比べて何倍手間がかかりますか?
2dのタイルマップエディタのようなものを作りたいのです、、、
https://www.mapeditor.org/
C#やelectronと比べて何倍手間がかかりますか?
2dのタイルマップエディタのようなものを作りたいのです、、、
https://www.mapeditor.org/
296デフォルトの名無しさん
2020/06/13(土) 20:19:12.06ID:lPN2rvMv 挫折するリスクも加味すると100倍くらいじゃないかな
297デフォルトの名無しさん
2020/06/13(土) 20:42:52.21ID:AVSH26bs >>295
個人の場合、実はC++は適している。
むしろ、大人数の場合、いろいろなレベルの人がいるので速度を落としてでも、
誰でも使えるような言語を使おうとする企業が多い。
ちゃんとしたものを作りたかったら、C++は最良の選択。
個人の場合、実はC++は適している。
むしろ、大人数の場合、いろいろなレベルの人がいるので速度を落としてでも、
誰でも使えるような言語を使おうとする企業が多い。
ちゃんとしたものを作りたかったら、C++は最良の選択。
298デフォルトの名無しさん
2020/06/13(土) 20:55:51.74ID:AVSH26bs ところで、全く関係ないけど、昔は、
標準変換(Standard Conversions)の1つに、
「Reference Conversions(参照変換)」
という項目があったのに、C++17では、Overload Resolution関連で
「Reference Binding(参照束縛)」
という項目だけになってしまった、という認識であってますかね?
もしかしたら古すぎて、もう分からないかな。
標準変換(Standard Conversions)の1つに、
「Reference Conversions(参照変換)」
という項目があったのに、C++17では、Overload Resolution関連で
「Reference Binding(参照束縛)」
という項目だけになってしまった、という認識であってますかね?
もしかしたら古すぎて、もう分からないかな。
299デフォルトの名無しさん
2020/06/13(土) 21:10:55.91ID:XHF92Eb6 c++がどうこういうこと自体無意味な気分。
OSとコンパイラのバージョン指定でもせん限り、特定の議論にもなりゃしない。
OSとコンパイラのバージョン指定でもせん限り、特定の議論にもなりゃしない。
300デフォルトの名無しさん
2020/06/13(土) 22:13:05.14ID:rMzKFBuy これから始めようと思うのですが
C++とC♯の大きな違いは何ですか
どっちから先の方が良いですか?
C++とC♯の大きな違いは何ですか
どっちから先の方が良いですか?
301デフォルトの名無しさん
2020/06/13(土) 23:19:47.34ID:B/JuT+NG 何作りたいかによるとしか言いようがない
302デフォルトの名無しさん
2020/06/13(土) 23:29:25.22ID:dAI/jSW6 あーじゃあ、C++には何が出来なかったせいで
後からC♯が作られたの?
後からC♯が作られたの?
303デフォルトの名無しさん
2020/06/14(日) 00:35:35.69ID:0sKu6MyV 違うよ
304デフォルトの名無しさん
2020/06/14(日) 00:45:05.04ID:lm4ZS132 んーでは、C++が劣っていてC♯が作られた理由は?
305デフォルトの名無しさん
2020/06/14(日) 00:55:29.50ID:7AEk3bXh インタープリ夛ー
306デフォルトの名無しさん
2020/06/14(日) 00:58:40.28ID:g+gmh/oa Javaの代わりが欲しかっただけであって優劣の問題はあまり関係がない
が結局Javaの領域には食い込めず、スクリプト言語の代わりになった
自由度を奪う代わりに楽に書けるみたいな
結局自由度が必要なのでC++から離れられないので余計書くのがつらい仕様になった
Win32APIのインクルードくらいSDKにまとめとけやPinヴォケって感じ
が結局Javaの領域には食い込めず、スクリプト言語の代わりになった
自由度を奪う代わりに楽に書けるみたいな
結局自由度が必要なのでC++から離れられないので余計書くのがつらい仕様になった
Win32APIのインクルードくらいSDKにまとめとけやPinヴォケって感じ
■ このスレッドは過去ログ倉庫に格納されています
