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
185デフォルトの名無しさん
2020/06/03(水) 14:24:00.16ID:UHE1JPNz >>181
何がたまたまの結果だよ
C++規格票とドラフトは巻末に索引があって
検索でヒットしすぎるときは末尾を見に行けば
そこは索引の中である可能性が大きいというのを
思いつくことができんのかおまえさんの頭では
だから見つけられなくて聞いてきたというなら合点だ
何がたまたまの結果だよ
C++規格票とドラフトは巻末に索引があって
検索でヒットしすぎるときは末尾を見に行けば
そこは索引の中である可能性が大きいというのを
思いつくことができんのかおまえさんの頭では
だから見つけられなくて聞いてきたというなら合点だ
186デフォルトの名無しさん
2020/06/03(水) 14:27:27.09ID:UHE1JPNz >>178
世の中すべての::operator newの内容を確認してからでないと答えられない質問だ
もっと言うなら将来にわたってタイムマシンで確認してくる必要があるから
調査の工数が発散しちまう
どういう意味かわかるな?
世の中すべての::operator newの内容を確認してからでないと答えられない質問だ
もっと言うなら将来にわたってタイムマシンで確認してくる必要があるから
調査の工数が発散しちまう
どういう意味かわかるな?
187デフォルトの名無しさん
2020/06/03(水) 15:04:54.04ID:TdRUmxlv https://qiita.com/SaitoAtsushi/items/8da8ae7f6b84b1d806e4
int main(){
double a = 1.5;
std::string b = "Hello World";
struct foo{};
xyz(a, b, foo());
}
↑のfoo()は一時オブジェクトの作成ですね?
int main(){
double a = 1.5;
std::string b = "Hello World";
struct foo{};
xyz(a, b, foo());
}
↑のfoo()は一時オブジェクトの作成ですね?
188デフォルトの名無しさん
2020/06/03(水) 15:11:30.37ID:DAHZjgl3 >>185
他人の茶々入れに何言ってんだよw
他人の茶々入れに何言ってんだよw
189デフォルトの名無しさん
2020/06/03(水) 15:12:28.27ID:DAHZjgl3 >>186
やはりこんな奴かwww
やはりこんな奴かwww
190デフォルトの名無しさん
2020/06/03(水) 15:35:53.72ID:TdRUmxlv めちゃくちゃ難しいです。#100の部分は恐らく「部分特殊化」というものだと思うのですが、
自分がネットで調べた簡単な部分特殊化とはちょっと違っているようです。
https://ja.wikipedia.org/wiki/SFINAE
// どのようなテンプレート引数であってもvoidになる
template <typename... Ts> using void_t = void;
template <typename T, typename = void>
struct has_typedef_foobar : std::false_type {};
// #100
template <typename T>
struct has_typedef_foobar<T, void_t<typename T::foobar>> : std::true_type {}; // T::foobarが存在すれば、こちらが有効になる
struct foo {
using foobar = float;
};
int main() {
std::cout << std::boolalpha;
std::cout << has_typedef_foobar<int>::value << std::endl;
std::cout << has_typedef_foobar<foo>::value << std::endl;
}
自分がネットで調べた簡単な部分特殊化とはちょっと違っているようです。
https://ja.wikipedia.org/wiki/SFINAE
// どのようなテンプレート引数であってもvoidになる
template <typename... Ts> using void_t = void;
template <typename T, typename = void>
struct has_typedef_foobar : std::false_type {};
// #100
template <typename T>
struct has_typedef_foobar<T, void_t<typename T::foobar>> : std::true_type {}; // T::foobarが存在すれば、こちらが有効になる
struct foo {
using foobar = float;
};
int main() {
std::cout << std::boolalpha;
std::cout << has_typedef_foobar<int>::value << std::endl;
std::cout << has_typedef_foobar<foo>::value << std::endl;
}
192デフォルトの名無しさん
2020/06/03(水) 15:42:50.44ID:UHE1JPNz >>188
他人かどうかは関係ねえぜ
俺が生活の知恵と言ったことを
たまたまの結果と言ったのはおまえさんに他ならない
必然的に思いつくまでの思考過程を示されて
自分の浅はかさを誤魔化すのに他人がどうのと
再び浅はかな言い訳で恥の上塗りするのは
やめたほうがいいんじゃないかな
他人かどうかは関係ねえぜ
俺が生活の知恵と言ったことを
たまたまの結果と言ったのはおまえさんに他ならない
必然的に思いつくまでの思考過程を示されて
自分の浅はかさを誤魔化すのに他人がどうのと
再び浅はかな言い訳で恥の上塗りするのは
やめたほうがいいんじゃないかな
193デフォルトの名無しさん
2020/06/03(水) 15:44:00.45ID:TdRUmxlv >>190
部分特殊化とは、
template <typename T1, typename T2>
class A {・・・}; //#1
として、「primary class template」を定義後、もし、
template <typename T>
class A<T, void>{・・・}; //#2
と書いた場合、
A<int,int> なら、#1が、A<int>なら#2が適用されるということでしょうか?
ならば、A<int,void>はどうなるんでしょう??
部分特殊化とは、
template <typename T1, typename T2>
class A {・・・}; //#1
として、「primary class template」を定義後、もし、
template <typename T>
class A<T, void>{・・・}; //#2
と書いた場合、
A<int,int> なら、#1が、A<int>なら#2が適用されるということでしょうか?
ならば、A<int,void>はどうなるんでしょう??
194デフォルトの名無しさん
2020/06/03(水) 15:46:30.08ID:DAHZjgl3 >>192
やはりこういうやつかwww
やはりこういうやつかwww
195デフォルトの名無しさん
2020/06/03(水) 15:47:08.09ID:UHE1JPNz #2
つーか、そんくらいやってみろよ
つーか、そんくらいやってみろよ
196デフォルトの名無しさん
2020/06/03(水) 15:47:50.07ID:UHE1JPNz >>194
やーい、同じことしか言わなくなってやんのw
やーい、同じことしか言わなくなってやんのw
197デフォルトの名無しさん
2020/06/03(水) 15:49:26.08ID:DAHZjgl3 必ずしも索引があるとは限らないのにあることを一般論化してドヤ顔するのと
ヒープ解放するかどうかはすべてを尽くして調べられないからわからたないとドヤ顔してる奴が
同じ人物だってのが困るわぁwwww
ヒープ解放するかどうかはすべてを尽くして調べられないからわからたないとドヤ顔してる奴が
同じ人物だってのが困るわぁwwww
198デフォルトの名無しさん
2020/06/03(水) 15:49:47.87ID:DAHZjgl3199デフォルトの名無しさん
2020/06/03(水) 15:52:20.19ID:TdRUmxlv >>193 >>195
2017年のDraftのPDFには、以下のようにあり、部分特殊化をinstance化する際には、A<int>ではなく、A<int,int*>
と書く例があります:
Partial specialization declarations themselves are not found by name lookup. Rather, when the primary
template name is used, any previously-declared partial specializations of the primary template are also
considered. One consequence is that a using-declaration which refers to a class template does not restrict the
set of partial specializations which may be found through the using-declaration. [Example:
namespace N {
template<class T1, class T2> class A { }; // primary template
}
using N::A; // refers to the primary template
namespace N {
template<class T> class A<T, T*> { }; // partial specialization
}
A<int,int*> a; // uses the partial specialization, which is found through the using-declaration
// which refers to the primary template
—end example ]
2017年のDraftのPDFには、以下のようにあり、部分特殊化をinstance化する際には、A<int>ではなく、A<int,int*>
と書く例があります:
Partial specialization declarations themselves are not found by name lookup. Rather, when the primary
template name is used, any previously-declared partial specializations of the primary template are also
considered. One consequence is that a using-declaration which refers to a class template does not restrict the
set of partial specializations which may be found through the using-declaration. [Example:
namespace N {
template<class T1, class T2> class A { }; // primary template
}
using N::A; // refers to the primary template
namespace N {
template<class T> class A<T, T*> { }; // partial specialization
}
A<int,int*> a; // uses the partial specialization, which is found through the using-declaration
// which refers to the primary template
—end example ]
200デフォルトの名無しさん
2020/06/03(水) 16:02:27.31ID:UHE1JPNz201はちみつ餃子 ◆8X2XSCHEME
2020/06/03(水) 16:06:58.23ID:3vvIkHpN >>193
ほんとに >>195 の言う通りだわ。
やってみてから思った通りにならないのはなんでだろうっていうならまだしも
「どうなるんでしょうか」なんてやってみりゃわかることだろ。
まあ C++ には未定義とか処理系定義とかもあるから
実際の挙動を以て言語仕様を理解しようとするのは危険でもあるんだが……。
特殊化ってのはまさに「特殊な場合」を定義するもんだよ。
その場合には A<T1, T2> のテンプレートの特殊な場合として A<T, void> の場合を定義してることになる。
特殊な場合である A<T, void> は特殊でない場合の A<T1, T2> と同じ形式である必要がある。
>>199
基本的な理念が理解できていないのに仕様を読んでも理解できねーよ。
(まあたまには仕様からとっかかる超人もいないことはないが。)
お前は Rust スレでも見当はずれの根拠をコピペしては意味不明なことを言ってるが、
普通に入門書を読んでくれ。
ほんとに >>195 の言う通りだわ。
やってみてから思った通りにならないのはなんでだろうっていうならまだしも
「どうなるんでしょうか」なんてやってみりゃわかることだろ。
まあ C++ には未定義とか処理系定義とかもあるから
実際の挙動を以て言語仕様を理解しようとするのは危険でもあるんだが……。
特殊化ってのはまさに「特殊な場合」を定義するもんだよ。
その場合には A<T1, T2> のテンプレートの特殊な場合として A<T, void> の場合を定義してることになる。
特殊な場合である A<T, void> は特殊でない場合の A<T1, T2> と同じ形式である必要がある。
>>199
基本的な理念が理解できていないのに仕様を読んでも理解できねーよ。
(まあたまには仕様からとっかかる超人もいないことはないが。)
お前は Rust スレでも見当はずれの根拠をコピペしては意味不明なことを言ってるが、
普通に入門書を読んでくれ。
202デフォルトの名無しさん
2020/06/03(水) 16:19:58.53ID:H6kZ1pQy イキイキしてんなwww
203デフォルトの名無しさん
2020/06/03(水) 16:24:47.80ID:DAHZjgl3 >>200
予想通りで乙w
予想通りで乙w
204デフォルトの名無しさん
2020/06/03(水) 16:25:39.34ID:TdRUmxlv >>201
結局、答えられないんですね。
結局、答えられないんですね。
205デフォルトの名無しさん
2020/06/03(水) 16:29:44.75ID:gQ0mUfsI そこで煽ってどうするw
206デフォルトの名無しさん
2020/06/03(水) 16:50:20.37ID:UHE1JPNz 質問しといて無礼な口の利き方をするやつにはお仕置きだ
一切何も教えない
一切何も教えない
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 ならダイアログ使えるから、通知するだけなら簡単だね。
■ このスレッドは過去ログ倉庫に格納されています
ニュース
- 【おこめ券】鈴木農相 米価維持の意図「一切ない」 [ぐれ★]
- 【警視庁】走行中の電車で女性に露出した下半身押しつけたか 無職の男(46)逮捕「チャンスがあればいつでもやる」 [nita★]
- バリ島で男子生徒ら集団万引きか、防犯カメラ映像が拡散 京都の大谷中学・高校が「窃盗行為」謝罪★6 [七波羅探題★]
- 気象庁「最悪のケースでは311のような地震」青森で震度6強地震「北海道・三陸沖後発地震注意情報」…北海道から千葉の182市町村が対象 [♪♪♪★]
- 【苺ましまろ】立民衆院議員、人気漫画の水着少女画像を「醜悪」タイ人少女の性搾取事件と関連付け…党内で反発 [少考さん★]
- 中国軍機レーダー照射、トランプ氏沈黙突く 試される日本外交 ★5 [蚤の市★]
- 【実況】博衣こよりのえちえちチーズケーキを仕込み(雑談あり)🧪
- 【速報】1ポンド210円で日英GDP逆転(残り1.5円)...世界6位の経済規模に転落 [237216734]
- 【高市悲報】中国軍「公海で空母の発着訓練するって事前通告したのになんで自衛隊機は急接近してきたんだ…?」中国軍困惑★2 [931948549]
- 30過ぎた大人おじさんが大学生(昔)のままのファッションをする「おじさんキッズコーデ」、炎上して問題視される。 [153490809]
- 高市政権「かけてもつながらない。機能していない」防衛当局間のホットライン機能せず [834922174]
- 現役ドラフト発表WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
