C++相談室 part151

■ このスレッドは過去ログ倉庫に格納されています
2020/05/14(木) 11:53:25.59ID:ZPCfyTux
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/ (日本語)

テンプレここまで
2020/05/31(日) 15:28:53.38ID:xFqcIaF1
C++は美しい
bool operator <(const POINT& inA, const POINT& inB){
int rA2 = ( inA.x * inA.x + inA.y * inA.y );
int rB2 = ( inB.x * inB.x + inB.y * inB.y );
return ( ( rA2 < rB2 ) || ( ( rA2 == rB2 ) && ( inA.y < inB.y ) ) );
}

inline bool operator()(const CNode* a, const CNode* b) const{
if(a->key1 != b->key1) return a->key1 > b->key1;
if(a->key2 != b->key2) return a->key2 > b->key2;
if(a->key3 != b->key3) return a->key3 > b->key3;
return false;
}

NODE_POINTER_SET NodePointerSet2(dammy, dammy+0, CNode());
for(int i=0; i<NUM; i++){
node = new CNode();
pair<NODE_POINTER_SET::iterator, bool> insert_result = NodePointerSet2.insert(node); //setへ登録
if( false == insert_result.second ) delete node; //重複で登録できなかった場合は確保したメモリを破棄
}
std::map<POINT, CNode*> mp;
for(NODE_POINTER_SET::const_iterator it=NodePointerSet2.begin(); it!=NodePointerSet2.end(); it++ ){
if( !mp[(*it)->position] ){
mp[(*it)->position] = (*it);
pair<NODE_POINTER_SET::iterator, bool> insert_result = NodePointerSet.insert((*it)); //setへ登録
}
}
2020/05/31(日) 15:41:55.39ID:J1D5Z9UC
>>147
key1,key2,key3 で整列しないのは回答として不適ではないの?
等値演算子「==」の話はただの思い込みだったということでいいんかね。
2020/05/31(日) 16:08:01.03ID:HQ8vNkm/
setの重複排除条件をコントロールしたいだけなら
std::(unordered_)setのPredテンプレート引数で制御すればいいだけの話じゃないの?
からかって遊んでるだけ?
2020/05/31(日) 16:37:00.29ID:zTMn2qwy
positionによる重複削除だけでなく、key1〜3によるソートと重複削除も必要だから
単純に順番にやるだけだと、余計な要素まで消えてしまう。

{{0,0},0,0,0},{{0,0},0,0,1},{{0,1},0,0,0}
みたいなデータがあった場合、単純にpositionによる重複削除を先に実施してしまうと
{{0,0},0,0,0},{{0,1},0,0,0}
みたいになって、そこからkey1〜3によるソートと重複削除を行うと
{{0,0},0,0,0}
だけになってしまう。逆順でも同様の問題がある。
2020/05/31(日) 16:47:23.53ID:HQ8vNkm/
その隠し要件どこに書いてるの?もしそれが必要なら横着せずに全部持っておくしかないね
2020/05/31(日) 17:24:57.13ID:zTMn2qwy
書いてるところはない。すまん。
154122
垢版 |
2020/06/01(月) 08:41:58.41ID:VTbJvOd1
すみません仕様間違えていました
>positionによる重複削除だけでなく、key1〜3によるソートと重複削除も必要
ではなく
positionによる重複削除だけでなく、key1〜3によるソートも必要
で、key1〜3が全部同じでもpositionが異なれば重複削除はしないという仕様が正しかったです
なので
>>148さんが書いて下さったコードを追加して、
if(a->key1 != b->key1) return a->key1 > b->key1;
if(a->key2 != b->key2) return a->key2 > b->key2;
if(a->key3 != b->key3) return a->key3 > b->key3;
return true;//ここをfalseではなくtrueに変更
にしたら、期待どおりの動作をしました
148さん本当にありがとうございます!とても助かりました
147さんもありがとうございます
2020/06/01(月) 08:53:47.81ID:idPskxLG
>>154
> return true;//ここをfalseではなくtrueに変更

明らかに違反してるじゃねーの?
https://cpprefjp.github.io/reference/algorithm.html#strict-weak-ordering
> 「狭義 (strict) 」 は非反射関係 (irreflexive relation) (全ての x について !comp(x,x) である)の要求
2020/06/01(月) 09:14:14.95ID:VTbJvOd1
難しい事はわかりませんが、
動作検証が足りてないかんじでしょうか
もし駄目だったら、諦めて別の方法を考えようと思います
2020/06/01(月) 14:34:32.60ID:o7IiynR8
double *array1;
array1 = new double[count]();
と書いた場合の、[count] の後ろの () の意味は何でしょうか?
array1 = new double[count];
と書いた場合との違いは何でしょうか?
()の中に何か書くことは出来ますか?
2020/06/01(月) 15:11:25.75ID:0yVOdbpz
>>157
内容を初期化するかどうか。
普通のクラスでは括弧がなくてもデフォルトコンストラクタで初期化されるので
空の括弧があってもなくても意味はかわらないけど、
プリミティブな型などでは括弧無しのときは初期化しない。 (つまり内容は不定)
括弧があればゼロで初期化されることが保証される。

C++14 あたりからはこんな感じで初期化することもできるよ。
double *array1 = new double[]{1,2,3};
2020/06/01(月) 15:34:55.48ID:o7IiynR8
>>158
をー。有難う。
2020/06/01(月) 18:12:14.25ID:8BAaT/q7
昔はよく{0}って書いてたというか書けなかったな
2020/06/01(月) 18:13:08.51ID:8BAaT/q7
×書けなかったな
○しか書けなかった
2020/06/02(火) 10:09:36.47ID:d/ekt+66
ヘッダでvector要素の型を先行宣言で済ますことができるのc++20からだっけ?
2020/06/02(火) 11:21:52.93ID:7ZgjbGq0
Working Draft, Standard for Programming Language C++
Document Number: N4713, Date: 2017-11-27
というPDFを読んでいるんだけど、explicitキーワードの事について調べようとしても、
索引(index)には載ってないようだけど、どこに書いてる?
2020/06/02(火) 12:04:07.50ID:eZHppilZ
>>163
N4713だよね? P.1373の2行目は見た?
2020/06/02(火) 12:30:40.82ID:7ZgjbGq0
>>164
Indexのspecifier項目のサブ項目として書いてあったんですね。
でもこれだとexplicitが何なのかを知りたい人にとっては索引としての役割を果たさないです。
いわば国語辞典で知らない単語を調べるのに勝手にカテゴリー分けしてあるようなものです。
それでは辞典の意味をなしません。
2020/06/02(火) 12:34:14.97ID:N0F889O8
>>165
PDF なのだから、ある項目について知りたければ検索すればいいよ。
この分量を印刷して読んでいるわけではないよね?
2020/06/02(火) 12:47:31.50ID:67GQ09ou
試しに検索かけたら1102件もヒットしたやんけ!餃子のバカバカ
2020/06/02(火) 13:55:05.15ID:7ZgjbGq0
AdobeRederは使いにくいので、SumatraPDF Reader を使って、まず、
左側のペーンに出てくる目次で index をクリックし、右側のペーンに
巻末の索引を出した後、右側のペーンの中で CTRL+Fを押して、
explicitを検索すると良いよう。
2020/06/02(火) 14:01:01.31ID:Ja+74ng6
素直にありがとうも言えないのか
これだからC++erは
2020/06/02(火) 14:11:59.21ID:7ZgjbGq0
>>169
ありがとう。
2020/06/02(火) 14:58:48.73ID:7ZgjbGq0
nested-name-specifier:
::
type-name ::
namespace-name ::
decltype-specifier ::
nested-name-specifier identifier ::
nested-name-specifier template opt simple-template-id ::

と有るのですが、このBNFだけで解釈するなら、ns1, ns2,ns3 という namespace が有った場合の
ns1::ns2::ns3::変数名
のような場合、
namespace-nameと認識されるのは ns1だけで、ns2,ns3は、identifierと
識別されるのでしょうか。
2020/06/02(火) 15:00:52.54ID:7ZgjbGq0
ちなみに、
namespace-name:
identifier
namespace-alias
namespace-alias:
identifier
となっており、namespace-nameには、a::bb::cc のようなものは含まれないと思われます。
2020/06/02(火) 15:16:37.04ID:N0F889O8
>>167
索引だけ検索すればええんや。
2020/06/02(火) 16:38:50.35ID:7ZgjbGq0
>>171
の定義だと、
decltype(x)::decltype(y)::decltype(z)
のようなものは使えないということになるようです。
ひょっとすると、C++の仕様書的には、
ns1::ns2::ns3::変数名
も使えないのもかも知れませんがよく分かりません。
2020/06/02(火) 17:48:50.88ID:eZHppilZ
>>167
つーかよ、その1102件を末尾から順に見ていくとすぐなんだが
そういう生活の知恵はあんまりないのかい?
2020/06/02(火) 19:53:34.27ID:Ja+74ng6
よくわかんないけど
ツイッターで誹謗中傷してそう
2020/06/03(水) 10:50:24.30ID:TdRUmxlv
https://en.cppreference.com/w/cpp/utility/hash
MyHash{}(obj)
std::hash<S>{}(obj)
の{}は、直接リスト初期化のもので、いったんMyHash型やstd::hash<S>型のテンポラリ・オブジェクトを作成してからoperator()関数をobjを実引数にして呼び出しているという理解でよろしいですか?
2020/06/03(水) 11:38:29.12ID:Nfbl5e81
newしたあとにdeleteしなくてもアプリケーションを終了すればメモリは解放されますか?
2020/06/03(水) 11:58:33.77ID:VI2pYiE8
OSによる
2020/06/03(水) 12:21:28.49ID:TdRUmxlv
>>178
Windows/Mac/Linuxではメモリー領域自体は絶対に解放される。
ただし、deleteが呼び出されるわけではないので、原則的にはデストラクタは呼び出されない。
2020/06/03(水) 12:24:39.32ID:DAHZjgl3
>>175
たまたまの結果を生活の知恵とかw
キーワードと通常言語が被らない日本語万歳だな
2020/06/03(水) 12:28:15.38ID:Nfbl5e81
>>179
>>180
ありがとうございます!
2020/06/03(水) 13:34:40.56ID:3vvIkHpN
>>178
プロセスに割り当てられているメモリは現代の普通のデスクトップOS上でならプロセスの終了と共に解放されるのだけど、
オブジェクトは外部のリソースのハンドルを掴んでいることがあるから
それを正常に (デストラクタで) 後始末しないとリソースリークが起こる可能性はある。

POD 型のオブジェクトに限ってならば管理されてるリソースはメモリだけだから
delete しなくてもプロセス終了時におおよそ安全に解放されることは期待していいと思う。

言語仕様での保証はないので C++ スレ的に言えば「やめとけ」ってことになるけど。
2020/06/03(水) 13:47:15.12ID:gQ0mUfsI
メモリと断っている人に余計なこといわなくていいと思うけど
アプリの異常終了であっても解放されてほしいのだろうから
c++の終了処理に依存してもしゃない
2020/06/03(水) 14:24:00.16ID:UHE1JPNz
>>181
何がたまたまの結果だよ
C++規格票とドラフトは巻末に索引があって
検索でヒットしすぎるときは末尾を見に行けば
そこは索引の中である可能性が大きいというのを
思いつくことができんのかおまえさんの頭では

だから見つけられなくて聞いてきたというなら合点だ
2020/06/03(水) 14:27:27.09ID:UHE1JPNz
>>178
世の中すべての::operator newの内容を確認してからでないと答えられない質問だ
もっと言うなら将来にわたってタイムマシンで確認してくる必要があるから
調査の工数が発散しちまう

どういう意味かわかるな?
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()は一時オブジェクトの作成ですね?
2020/06/03(水) 15:11:30.37ID:DAHZjgl3
>>185
他人の茶々入れに何言ってんだよw
2020/06/03(水) 15:12:28.27ID:DAHZjgl3
>>186
やはりこんな奴かwww
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;
}
2020/06/03(水) 15:40:53.00ID:3vvIkHpN
>>187
そういうのはコメントで質問すれば?
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>はどうなるんでしょう??
2020/06/03(水) 15:46:30.08ID:DAHZjgl3
>>192
やはりこういうやつかwww
2020/06/03(水) 15:47:08.09ID:UHE1JPNz
#2
つーか、そんくらいやってみろよ
2020/06/03(水) 15:47:50.07ID:UHE1JPNz
>>194
やーい、同じことしか言わなくなってやんのw
2020/06/03(水) 15:49:26.08ID:DAHZjgl3
必ずしも索引があるとは限らないのにあることを一般論化してドヤ顔するのと
ヒープ解放するかどうかはすべてを尽くして調べられないからわからたないとドヤ顔してる奴が
同じ人物だってのが困るわぁwwww
2020/06/03(水) 15:49:47.87ID:DAHZjgl3
>>196
>>197
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 ]
2020/06/03(水) 16:02:27.31ID:UHE1JPNz
>>197
C++規格票とドラフトと言ったはずだ
必ずしも索引があるとは限らないとぬかすなら
そうなっていないC++規格票とドラフトを例示しろ
事実無根の誹謗中傷はやめてもらおうか
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 スレでも見当はずれの根拠をコピペしては意味不明なことを言ってるが、
普通に入門書を読んでくれ。
2020/06/03(水) 16:19:58.53ID:H6kZ1pQy
イキイキしてんなwww
2020/06/03(水) 16:24:47.80ID:DAHZjgl3
>>200
予想通りで乙w
2020/06/03(水) 16:25:39.34ID:TdRUmxlv
>>201
結局、答えられないんですね。
2020/06/03(水) 16:29:44.75ID:gQ0mUfsI
そこで煽ってどうするw
2020/06/03(水) 16:50:20.37ID:UHE1JPNz
質問しといて無礼な口の利き方をするやつにはお仕置きだ
一切何も教えない
2020/06/03(水) 16:50:59.31ID:UHE1JPNz
>>203
ぐうの音も出ねえとは
おまえさんのことだな
2020/06/03(水) 17:02:24.74ID:TdRUmxlv
>>206
答えられないだけ。
2020/06/03(水) 17:03:53.52ID:DAHZjgl3
>>207
都合よくげんていつけたりなくしたりwwww
2020/06/03(水) 17:04:33.42ID:DAHZjgl3
>>206
なんでも上から目線
やはりこういうやつかwwww
211晒しage
垢版 |
2020/06/03(水) 17:11:10.63ID:UHE1JPNz
181 返信:デフォルトの名無しさん[sage] 投稿日:2020/06/03(水) 12:24:39.32 ID:DAHZjgl3 [1/9]
>>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()
2020/06/03(水) 18:46:53.95ID:TdRUmxlv
>>193
推定だけど、
A<T, void>
の場合、2番目の仮引数がvoid型になっているので、そこには実引数を
指定しないということになっているらしい。
その結果、A<1> みたいに1つだけの引数でtemplateをinstance化できる
様になっている気がする。
まだ仕様書で確認したわけではない。
2020/06/03(水) 18:53:53.18ID:HVfXpWIv
いや、省略した場合のデフォルトを指定しない限り、そんなことにはならない

template <typename T1,typename T2=void>
class A;

みたいにする
まあ、primaryの定義と同時にも書けるし、そっちが普通
2020/06/03(水) 19:02:53.85ID:3vvIkHpN
>>204
俺が答えていることすら理解できてない模様。
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);
}
2020/06/03(水) 19:08:51.14ID:TdRUmxlv
>>215
仮に心の中にあってもあなたは全く言語化して無いないので駄目。
2020/06/03(水) 19:10:26.76ID:TdRUmxlv
>>214
じゃあ、Wikipediaに載っていた>>190の例はどう説明すれば良い?
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)と書かなくて良いというもの。
それかな?
2020/06/03(水) 19:17:57.22ID:TdRUmxlv
そうではなく、>>190 の場合は、primary template として、
template <typename T, typename = void>
struct has_typedef_foobar : std::false_type {};
と、第二パラメータにデフォルト引数が書いてあるからか。
2020/06/03(水) 19:20:51.92ID:HVfXpWIv
>>218
190ってまさにtypename=voidしている例じゃね
2020/06/03(水) 19:27:23.10ID:TdRUmxlv
>>221
>>220と入れ違いになった。
それで辻褄は合うけど、primary templage definition では、
template <typename T, typename = void>
で、部分特殊化する際には、
template <typename T>
としてあって、物凄い複雑だね。
2020/06/03(水) 19:48:21.19ID:XMrfvYH7
TdRUmxlvは自分の日記帳に書いてくんないかな
2020/06/03(水) 20:15:01.97ID:TdRUmxlv
失礼しました。
でも断っておくと、俺ははちみつに対してそんなに悪口は言ってない。
スレの流れで混乱していたようだが、言っていたのは別人だから悪しからず。
2020/06/03(水) 22:21:05.04ID:OT4MJN13
いちいちイラッとする書きっぷりはID:TdRUmxlvのコミュ力が絶望的に低くいだけなので許してあげてください
2020/06/03(水) 23:25:41.73ID:SSmphgFp
憂さ晴らしに靖国に落書きしそう
2020/06/04(木) 08:16:53.40ID:85VTz4/e
とっくにNG
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の入っている場所のアドレスは存在しえません。
例え「"右辺値"参照」であってもはアドレスが必要のはずですが。
2020/06/04(木) 13:17:22.86ID:+U2drwkO
構ってはいけない
2020/06/04(木) 14:43:12.11ID:2rF1/e7a
>>228
言語規格的にはrr_iという名前を通じて7という値が取れれば何でもいい
コンパイラが具体的にどうするかはコンパイラの勝手
アドレスがどこかで必要なら一時オブジェクトを作るようにするし必要なければ作らなくてもいい
2020/06/04(木) 18:50:33.11ID:pT22FhoL
>>230
どうやら、7の入ったint型の隠れた変数を一時オブジェクトとして作成してから、
そのアドレスをrr_iに入れているそうです。
2020/06/07(日) 01:50:09.38ID:P1Z5Y5je
>>228

int& r_i=7; // compile error

確かにこれはダメ

int&& rr_i=7; // OK
int& rr_j = rr_i; // OK

これおかしくね?
2020/06/07(日) 01:57:43.49ID:loMZGJMS
&&嫌いだわ
2020/06/07(日) 03:20:06.67ID:NFGxwtnl
右辺値参照自身は左辺値定期
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以降の作法として正しいでしょうか?
2020/06/07(日) 13:44:00.54ID:ocvuft6U
作法とか正しいとかより自分で考えた方がいいと思うけど
その場合あえて言えば、hFile渡すとこは
直接CreateFileの戻り値使って(hFileを宣言しない)、dummyの持つハンドル経由で使った方が
一貫性が取れていいかも

理想を言えば全部ラップした方がいいんだろうけど
2020/06/07(日) 13:55:18.98ID:HzkE9Nko
>>236
その方法は始めてみた。
でも、unique_ptrなどを使わなくても、普通にC++98レベルのclassだけを使っても、RAIIは書ける。
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が解放される。
2020/06/07(日) 15:37:10.54ID:NFGxwtnl
ポインタ以外のリソースでRAIIやらせるためのstd::unique_resourceが提案されてるけど難航してる
リソースの種類や使い方でそれぞれ事情が違うから無理矢理一般化しても上手く行かないらしい
2020/06/07(日) 15:48:34.18ID:HzkE9Nko
>>239
補足すると、このコードだとCreateFile()した後、返されたハンドル値を No CheckでCMyXのコンストラクタに渡しているが、本当はその前にINVALID_HANDLE_VALUEかどうかをチェックしておく必要がある。
2020/06/07(日) 21:39:58.03ID:P1Z5Y5je
>>234
そこじゃなくて

int& r_i=7; // compile error

をエラーにする必要ある?ってこと
リテラルを右辺値参照できんならエラーにする必要ないじゃん
2020/06/07(日) 21:49:43.50ID:NFGxwtnl
それがエラーじゃなかったら右辺値参照は何のためにあるんだよ
2020/06/07(日) 21:56:24.65ID:P1Z5Y5je
>>243
別にリテラル受けるためにあるわけじゃないでしょ
別の言い方すると

int&& rr_i=7; // OK

わざわざ一時オブジェクトつくってこれOKにする理由って何なの?
245デフォルトの名無しさん
垢版 |
2020/06/07(日) 22:22:50.71ID:uPPavgXr
>>237,238,240
ありがとうございます
>>239
はい、そうなんですけれど、こういったコードも省略したいということと、
頻繁に必要になるので標準ライブラリに入っていないかなって期待していたわけです
>>240
なるほどstd::unique_resourceっていうので検討中なんですね
これが標準に組み込まれるのを期待しておきます
2020/06/07(日) 23:16:58.32ID:+YSUT0gy
More Effective C++ の、

項目9 : リソースリークを防ぐためにデストラクタを使う
項目11 : デストラクタから発生した例外を抑える

デストラクタ中で、例外がキャッチされない場合、
terminate を呼ばれて、受け身も取れず、強制終了させられる
2020/06/08(月) 11:21:10.82ID:KlUsfYw8
>>245
CreateFile以外にも似たようなのが沢山あって、それを楽にRAIIにしたいって話?
ならすでにunique_resourceはあるらしいけど(experimentalだかどこかに
あるいはそれに近い実装も公開されてるので落としてくればいいかと

逆にCreateFileだけなら素直に自分でクラス書いた方が後々楽になると思う
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

ニューススポーツなんでも実況