20/05/14 11:53:25.59 ZPCfyTux.net
C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
IDE (VC++など)などの使い方の質問はその開発環境のスレにお願いします。
前スレ
C++相談室 part150
スレリンク(tech板)
このスレもよろしくね。
【初心者歓迎】C/C++室 Ver.105【環境依存OK】
スレリンク(tech板)
■長いソースを貼るときはここへ。■
URLリンク(codepad.org)
URLリンク(ideone.com)
[C++ FAQ]
URLリンク(isocpp.org)
URLリンク(www.bohyoh.com) (日本語)
テンプレここまで
2:デフォルトの名無しさん
20/05/14 12:14:02.15 tvxDWcUo.net
>>1
O2
3:デフォルトの名無しさん
20/05/14 15:59:11 Qhhsb9+b.net
スレリンク(tech板:1000番)
> 1000 名前:デフォルトの名無しさん[sage] 投稿日:2020/05/14(木) 15:51:59.69 ID:X1Z5LMNW [4/4]
> ん?
> >未だにC++03にしがみついているわけがない
> >>993で17使ってると言ってたようだが
>
> てかもうちょい生産的な話出来んのか
> 仕事でも趣味でも都合の良いコンパイラ使えばいいだけの話
> 構造化束縛をマクロとテンプレートで実現するとかなら面白い話題なんだけどな(面白いだけで実用性があるとは言ってない
なんだ、17で俺スゲーやってんのおまえじゃん
俺は仕事で17は当たり前という立場
おまえは仕事には危なくて使えないという立場
俺に教えを請うて突っぱねられたのがおまえ
あとはわかるな?
4:デフォルトの名無しさん
20/05/14 16:04:10 X1Z5LMNW.net
>>3
>なんだ、17で俺スゲーやってんのおまえじゃん
>おまえは仕事には危なくて使えないという立場
?
俺の話じゃないんだが・・
いいから消えろよ荒らしは
5:デフォルトの名無しさん
20/05/14 16:04:50 QxbT6fEj.net
ホスト環境は17、組み込みは03で良いのでは?
6:デフォルトの名無しさん
20/05/14 16:06:44 Qhhsb9+b.net
>>5
その「組み込み」ってのは、まさかH8とかか?
ARM用のコンパイラがどうなっているか知ってるか?
7:デフォルトの名無しさん
20/05/14 16:07:42 Qhhsb9+b.net
>>4
逃げたければ消えるのはおまえだ
ほら行けよ、追わねえでやるから
8:デフォルトの名無しさん
20/05/14 16:44:48.92 7nN34odP.net
extern "C" 以下が、宣言になるなのか、定義になるのかについて、以下のページには、
extern "C" { int i; } と書くと、i は、「定義」される。
宣言で済ましたい場合には、
extern "C" { extern int i; }としなくてはならない。しかし、中括弧で囲まずに、
extern "C" int i;
と書いた場合には、i は「宣言」だけされる、とあります。
さらに、これは変数の場合で、関数の場合には、戻り値 関数名(仮引数列) の後に関数定義部の{・・・}
があるかどうかで宣言か定義かが変わるだけのようです。といいますか、関数の場合は、関数定義部
がなければ、「定義」しようがないのでそれは当然かもしれませんが(結構複雑です。)。
これらの動作について、cppreference などで述べられているページがあれば、
教えていただければ幸いです。
URLリンク(stackoverflow.com)
Note that extern "C" { int i; } is a definition.
This may not be what you intended, next to the non-definition of void g(char);.
To make it a non-definition, you would need extern "C" { extern int i; }.
On the other hand, the one-declaration syntax without braces does make the declaration a non-definition: extern "C" int i; is the same as extern "C" { extern int i; }
9:デフォルトの名無しさん
20/05/14 17:19:49 7nN34odP.net
>>8
【関連事項】
[winnt.h の中]
#ifdef __cplusplus
#define EXTERN_C extern "C"
#else
#define EXTERN_C extern
#endif
[urlmon.h の中]
EXTERN_C const IID CLSID_CdlProtocol; // (100)
[考察]
(100)は、EXTERN_C のマクロ展開後
*pure C では、
extern const IID CLSID_CdlProtocol; // (101)
*C++ では、
extern "C" const IID CLSID_CdlProtocol; // (102)
となります。
(101)は明らかに(「定義」ではなく)「宣言」なので、モード間のバランスから考えて、
(102)も宣言でなくてはなりません。一方、
#ifdef __cplusplus
extern "C" {
#endif
int aaa;
#ifdef __cplusplus
}
#endif
と書いた場合、aaa は、どちらのモードでも「(変数)定義」であり、単なる「宣言」ではありません。
これは、(102)が「宣言」であることと、ある種の矛盾を生じているようですが、これが現状の
正しい解釈のようです。しかし、この事が cppreference のどこに書いてあるのかが分かりません。
10:デフォルトの名無しさん
20/05/14 17:25:47 xR/PZA9p.net
1回しか使われていない場合
2回以上使われている場合
「宣言」とは別に定義がリンクされている場合
11:デフォルトの名無しさん
20/05/14 17:33:00 7nN34odP.net
>>10
そういうことは理解しているつもりです。
extern ではなく、extern "C" の動作が、直後にブロックがあるかないかや、
変数か関数かによって、不思議な変化を見せることに興味があります。
12:デフォルトの名無しさん
20/05/14 17:38:36 Qhhsb9+b.net
int aaa; //definition in C++, tentative in C
int aaa; //invalid in C++, valid in C
13:デフォルトの名無しさん
20/05/14 17:48:01 nTyJBG5I.net
クラスで定義された型を言語構文でバラして対応付けると言う非対称な気持ち悪さと
const, 非constを混在して受けられない不便さとがあるな
構造化バインディング
まーtuple限定ではなく構造体を対応付けられるから非対称ってわけでもないか
14:デフォルトの名無しさん
20/05/14 17:51:54 nTyJBG5I.net
>>8
extern "C" {}
はブレース内をCリンケージで処理するつって話
extern "C" int a;
はCリンケージのextern文
15:デフォルトの名無しさん
20/05/14 18:15:11 7nN34odP.net
>>14
stackoverflow以外に、公式サイトでそれが書かれている場所を教えていただければ幸いです。
16:デフォルトの名無しさん
20/05/14 18:18:32.65 jF4/VTtK.net
cppreferenceは仕様書じゃないから書いてなくても不思議じゃないと思うけど。
仕様書見たら?ドラフト版はネットに転がってる
17:デフォルトの名無しさん
20/05/14 18:25:58.94 7nN34odP.net
>>16
その公式アドレスを教えていただければ幸いです。
18:デフォルトの名無しさん
20/05/14 18:27:40.05 nTyJBG5I.net
>>15
cppreference.comに書かれてるぞ
19:デフォルトの名無しさん
20/05/14 18:28:39.75 nTyJBG5I.net
externの説明のnotesのところにな
20:デフォルトの名無しさん
20/05/14 18:32:35.87 jF4/VTtK.net
>>17
ggrks
URLリンク(www.open-std.org)
あとcppreferenceはある意味ファンサイトみたいなものなので、何らかの標準化組織の公式サイトというわけじゃないよ
21:デフォルトの名無しさん
20/05/14 18:42:47.93 nTyJBG5I.net
つーか、cppreferenceに書いてあるのに見落としてよそのサイト教えろとか馬鹿丸出しで笑える
22:デフォルトの名無しさん
20/05/14 18:45:51.63 QxbT6fEj.net
バカにバカというのはバカ差別で違法だからね。
23:デフォルトの名無しさん
20/05/14 20:34:45.27 Qhhsb9+b.net
情報量ゼロのゴミレスでドヤ顔する自覚なきクズ大杉
20はggrksと言いながらちゃんとリンク貼ってる
24:デフォルトの名無しさん
20/05/14 20:40:53.93 xR/PZA9p.net
>>22
URLリンク(www.youtube.com)
25:デフォルトの名無しさん
20/05/14 20:46:17.52 QxbT6fEj.net
>>24
「私たちは抗議活動のための支援団体、人道支援団体ではない」
反日団体だから慰安婦なんか知ったことじゃないって事だろ?
筋通ってると思うが。
26:デフォルトの名無しさん
20/05/14 20:48:02.32 QxbT6fEj.net
そういえば、チョンにチョンというのはチョン差別で違法だけど、日本人に日本人というのは別に問題ないね。
フランス人にフランス人というのも問題ないし、中国人に中国人というのも問題ない。
何が違うんだろ。
27:デフォルトの名無しさん
20/05/14 20:51:04 QxbT6fEj.net
チョンというのがダメなのかと思ったけど。
朝鮮人に朝鮮人というのも朝鮮人差別だから違法だよね。
ますますわからん。
28:デフォルトの名無しさん
20/05/15 18:22:21 hNzctM0s.net
以下の混乱を、どう解決すべきか分かる人いますか?
・無名の共用体: 問題は特に有りません。
・無名の構造体: 入れ子の構造体(nested class)の「型定義」と区別が付かない気がします。
以下はその説明です :
class CPerson { // (1)
struct _TAaa { // (2)
・・・
}; // (3)
};
と書いた場合、(3) の部分にメンバ名が書かれていません。
しかし、これでは以下のどちらかなのか区別できない気がするのです。
a. CPerson の中に「無名ではあるが実態のあるメンバ」として「メンバ変数」を定義するつもり。
b. 単に、CPerson の class scope の中に _TAaa というタグ名を持つ構造体を「型定義」するつもり。
MSは、a の方針で、この形式 (2)~(3) を、「anonymous structure」と定義しているらしいです。
しかし、C++ には、b の解釈の「nested class」という言葉も存在しています。
29:デフォルトの名無しさん
20/05/15 18:32:30 OzObLB6i.net
>>28
自分でコンパイルしてどうなるか試したんだよな?
30:デフォルトの名無しさん
20/05/15 18:39:41 7pqJGfJd.net
2に名前つけている時点で無名じゃない
31:デフォルトの名無しさん
20/05/15 18:44:03 hNzctM0s.net
>>30
なるほど。
32:デフォルトの名無しさん
20/05/16 16:37:49 nLCzlpLv.net
std::bitset を std::unordered_map か std::map のキーとして使用したいのですが、
どうすればよろしいのでしょうか?
33:デフォルトの名無しさん
20/05/16 16:40:58 hM/FmoW0.net
>>32 やってみて、何か問題あったの?
34:デフォルトの名無しさん
20/05/16 16:46:28 tFvEvqcA.net
std::unordered_map<std::bitset<42>, int> um;
um[std::bitset<42>("0011")] = 9999;
std::cout << um[std::bitset<42>("0011")] ;
普通に動いたぞ
何に困ってるんだ?
35:デフォルトの名無しさん
20/05/16 16:50:35 nLCzlpLv.net
>>33
>>34
下のコードで書いてもエラーが出てしまってどうすればよいかがわからないんです。
#include <map>
#include <unordered_map>
#include <bitset>
int main()
{
std::map<std::bitset<100>, int> a;
std::bitset<100> n;
n.set( 1 );
a.insert( std::make_pair( n, 100 ) ); // ここでエラーが出てしまいます。
return 0;
}
36:デフォルトの名無しさん
20/05/16 16:59:00 hM/FmoW0.net
>>35 エラーメッセージも貼って、エラーメッセージのわからないところも書いてくれるといいな。
37:デフォルトの名無しさん
20/05/16 17:07:47 nLCzlpLv.net
>>36
error C2676: 二項演算子 '<': 'const _Ty' は、この演算子または定義済の演算子に適切な型への変換の定義を行いません。(新しい動作; ヘルプを参照)
with
[
_Ty=std::bitset<100>
]
message : クラス テンプレート メンバー関数 'bool std::less<std::bitset<100>>::operator ()(const _Ty &,const _Ty &) const' のコンパイル中
with
[
_Ty=std::bitset<100>
]
message : コンパイル対象の関数 テンプレート インスタンス化 'bool std::less<std::bitset<100>>::operator ()(const _Ty &,const _Ty &) const' のリファレンスを確認してください
with
[
_Ty=std::bitset<100>
]
message : コンパイル対象の クラス テンプレート インスタンス化 'std::less<std::bitset<100>>' のリファレンスを確認してください
message : コンパイルされている変数テンプレート 'const bool is_empty_v<std::less<std::bitset<100> > >' のリファレンスをご参照ください
message : コンパイル対象の クラス テンプレート インスタンス化 'std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>' のリファレンスを確認してください
with
[
_Kty=std::bitset<100>,
_Ty=int,
_Pr=std::less<std::bitset<100>>,
_Alloc=std::allocator<std::pair<const std::bitset<100>,int>>
]
message : コンパイル対象の クラス テンプレート インスタンス化 'std::map<std::bitset<100>,int,std::less<std::bitset<100>>,std::allocator<std::pair<const std::bitset<100>,int>>>' のリファレンスを確認してください
38:デフォルトの名無しさん
20/05/16 17:07:54 tFvEvqcA.net
わかった、std::mapだとダメなんだな
bitsetがoperator<持ってないからだ
これ定義すればmapでも通ると思うよ
template<>
struct std::less<std::bitset<100>>
{
bool operator()(const std::bitset<100>& lhs, const std::bitset<100>& rhs) const{ return lhs.to_ulong() < rhs.to_ulong();}
};
39:デフォルトの名無しさん
20/05/16 17:08:13 nLCzlpLv.net
といったメッセージが出ております。
40:デフォルトの名無しさん
20/05/16 17:09:26 is04b0b3.net
>>35
a.insert( std::make_pair< FOO , BAR >( n, 100 ) );
41:デフォルトの名無しさん
20/05/16 17:09:55 tFvEvqcA.net
まあどうしてもmapにしたい理由がなけりゃおとなしくunordered_mapにした方がいいと思うけど
stdのテンプレートをstdのクラスで特殊化するのは本来は反則だし、unordered_mapの方がだいたい効率いいし
42:デフォルトの名無しさん
20/05/16 17:16:42.14 uXmamJPc.net
普通に考えたらこれだろ。
std::make_pair( n, 100 )
43:デフォルトの名無しさん
20/05/16 17:36:40.03 nLCzlpLv.net
皆さん。情報ありがとうございます。
>>38
試してみた所ビットを33個立てるとstd::overflow が出てしまうようです。
おそらく関数の仕様的な問題だと思うのですが……
>>40
a.insert( std::make_pair<std::bitset<MAX>, int>( n, 100 ) );
とやってみた所エラーが出てしまいました。
この辺の指定はコンパイラが勝手に行ってくれると思っていたのですが、
指定しなければならないのでしょうか?
>>41
std::unordered_map を利用するとうまくいきました。
ありがとうございます。
>>42
すみません。
>>40と同じ理由なのでしょうか?
44:デフォルトの名無しさん
20/05/16 17:50:14 qkv5Lv3o.net
bitset の値同士で < での比較ができないから map でエラーってことか。
unordered_map なら == で比較できれば使える、と。
45:デフォルトの名無しさん
20/05/16 18:00:40 tFvEvqcA.net
ああ>>38だとulongにして比較してるからオーバーフローしちゃうな
真面目にビット比較するように関数書けば通ると思う
遅そうだしなおさらunordered_mapの方が良くなるけど
46:デフォルトの名無しさん
20/05/17 14:06:29 7W3ntFmq.net
ラムダ式にテンプレートの型指定ってできないんですかね?
auto f = []<class T>(T) {};
auto f2 = []<class T>() {};
f(1);
f2<int>();
fは引数にその型のパラメータがあるので大丈夫なんですけど、
f2だとコンパイルが通らないです...
47:デフォルトの名無しさん
20/05/17 14:12:23 ykqeUojC.net
ダミーの引数渡して
decltypeするとかすればいいんじゃね
48:デフォルトの名無しさん
20/05/17 14:33:24 AX8hrxuQ.net
>>46
呼び出してるのはあくまでオーバーロードされた関数呼び出し演算子なので、こうする
f2.operator()<int>();
URLリンク(wandbox.org)
49:デフォルトの名無しさん
20/05/17 14:41:04 7W3ntFmq.net
>>48
なるほど!ありがとうございます!!
50:デフォルトの名無しさん
20/05/18 09:15:27 XEI7YtdQ.net
なるほど
戻り値で判断するのも知りたい
51:デフォルトの名無しさん
20/05/18 10:30:31 VVfIWrZc.net
>>46
auto仮引数ではあかんの?
auto f = [](auto arg) { cout << typeid(arg).name() << endl; };
f(1); //int
f(1.5); //double
52:デフォルトの名無しさん
20/05/18 19:43:09 NOr8CY4q.net
以下のコードを実行すると 'あ' がアルファベットと判定されてしまうのですが、なぜかわかりますか?
Visual C++ 2019でもg++ 7.5.0でも結果は一緒でした(値は違いますが)。
std::locale loc("");
std::locale::global(loc);
std::wcout << std::isalpha(L'あ') << std::endl;
std::wcout << iswalpha(L'あ') << std::endl;
53:デフォルトの名無しさん
20/05/18 20:28:29.14 SqFV2JvV.net
あはアルファベットだからだろう
54:デフォルトの名無しさん
20/05/18 20:49:09 vxC60pVH.net
というより、その判定結果だからこそあはアルファベットなんだよ
isalphaがtrueを返すものを現在のロケールにおけるアルファベットと呼ぶと言う方が正しいか
55:デフォルトの名無しさん
20/05/18 20:53:28 ah40zw28.net
いや、isalphaがtrueになる文字は各localeで決まっている
isalphaはそれを垂れ流しているだけ
56:デフォルトの名無しさん
20/05/18 21:32:06.39 cgM2dsGJ.net
is_ascii_alpha()のほうが良く使う。
57:デフォルトの名無しさん
20/05/18 22:16:41 NOr8CY4q.net
ありがとうございます
普段は「日本語のアルファベット」とはあまり使わないけれど、
設定されている言語で表現するための文字のことをアルファベットと呼んでいると理解しておきます。
58:デフォルトの名無しさん
20/05/19 03:42:01 dHzzm0xI.net
そもそも英語では普通にひらがなとカタカナを指して"Japanese alphabet"と呼ぶ
59:デフォルトの名無しさん
20/05/19 10:55:08 h69Ba80R.net
アルファベットはアラビア語が語源?
60:デフォルトの名無しさん
20/05/19 10:56:23 h69Ba80R.net
あと正確に言うなら日本語のアルファベットは
いろは
61:デフォルトの名無しさん
20/05/19 12:21:31 kOq4o5Tk.net
アルファベット=表音文字と言いたいの?
62:デフォルトの名無しさん
20/05/19 13:16:28.27 kUNy0nAn.net
stlを考えた人は馬鹿だからな。
63:デフォルトの名無しさん
20/05/19 13:40:15 kUNy0nAn.net
isalpha()が2バイト文字環境でいままで使われてきた経緯も知らずに勝手に仕様を変えてしまう馬鹿な人々。
min,maxも伝統的なマクロの存在を知らずに衝突させてしまう馬鹿。
さらに馬鹿なのはSTL作者達なのにコンパイラ処理系作者のせいにしてしまう愚かな烏合の衆たち。
64:デフォルトの名無しさん
20/05/19 13:44:38 JQlWutmQ.net
isalphaは昔のcでもlocale依存だろ
65:デフォルトの名無しさん
20/05/19 14:25:44.49 O4jzhFRD.net
STLは、なぜあの時代に、ここまで抽象化できたのか?彼らは宇宙から来たのではないか?などと考えてしまうが。
66:デフォルトの名無しさん
20/05/19 14:27:12.72 O4jzhFRD.net
Windows.hのmin、maxは困りものだよな。
67:デフォルトの名無しさん
20/05/19 14:51:53.51 oq2DQSv9.net
マクロでminmax書いているほうがどう考えてもバカだよな
68:デフォルトの名無しさん
20/05/19 14:54:10.83 oq2DQSv9.net
win32の設計とかあーバカコードだなコレってのがちらほら
69:デフォルトの名無しさん
20/05/19 16:31:48 kOq4o5Tk.net
>>67
御意
70:デフォルトの名無しさん
20/05/19 17:47:23 HCP/tGTo.net
人類がBOOST_PREVENT_MACRO_SUBSTITUTIONから解放される日は遠い
71:デフォルトの名無しさん
20/05/19 18:01:48 0UAmioLe.net
STLの方が馬鹿。
今までのものを知らないで独自のものを書くのは簡単。
勉強もせずに独自の日記を書くようなことだから。
72:デフォルトの名無しさん
20/05/19 18:23:54 8HY/3oGP.net
なぜ会社を100社以上バックレたのか?働きたくない男の末路!
URLリンク(www.youtube.com)
【遅刻早退ドタキャン癖】の絶望的な解説。社会人失格の烙印。
URLリンク(www.youtube.com)
【悲報】あがり症は完治しない!緊張対策よりも開き直り!
URLリンク(www.youtube.com)
結婚式への参加は『社会の底辺』には地獄!非モテ手当を寄こせ!
URLリンク(www.youtube.com)
親戚の『葬式』ドタキャンで激怒された!冠婚葬祭パワハラが酷い!
URLリンク(www.youtube.com)
リボ払い借金500万円の一日!敗者復活ルーティーン
URLリンク(www.youtube.com)
73:
20/05/19 18:33:01.90 SLJ7GP9K.net
>>59
ちがいます、フェニキア文字由来ですよ
アラビア語はセム語族の中でも後発後進国
74:デフォルトの名無しさん
20/05/19 19:02:02.51 VP2fOBMJ.net
>>72
スレチ グロ
75:デフォルトの名無しさん
20/05/20 06:07:41 8m9cjgNh.net
関数(始点,終点)に馴染めないバカのあぶり出しだったな
関数(始点,個数)に固執してたやつらがSTLで吠え面かかされたw
76:デフォルトの名無しさん
20/05/20 14:27:55 9xAqQrOe.net
URLリンク(ideone.com)
ミラーラビン素数判定法を聞いて作ってるんだけど、決定性に確定させるにはここからどうしたらいいですか?
77:デフォルトの名無しさん
20/05/20 14:30:18 9xAqQrOe.net
URLリンク(ideone.com)
無しだとちゃんと出るっぽいです。ということを見せておきます。
78:デフォルトの名無しさん
20/05/21 09:22:26.84 r7XP4kDE.net
>>65
ソ連で生魚にあたって、入院中に病院の天井みてたら思いついたらしいぜ
79:デフォルトの名無しさん
20/05/21 11:21:03.35 K4ggzWEW.net
寄生虫より有毒魚かもな
フグみたいな命取りなやつじゃなくバラムツくらいなら腹壊す程度で済む
80:デフォルトの名無しさん
20/05/21 20:23:36 U7f5mioC.net
>>75がどれに対するレスなのか分からんが
みんな単にスルーしてんだろうなこれは
81:デフォルトの名無しさん
20/05/22 07:52:07 QdrkGYuD.net
バカって素直だな
ちゃんと返事しやがるw
82:デフォルトの名無しさん
20/05/22 13:00:00 c/ouk/Jn.net
dtmみたいな楽器を作る場合、音は何らかのライブラリを使うんでしょうか?1から作れるんですか?
83:デフォルトの名無しさん
20/05/22 14:03:10 lsrfRepl.net
は?
オリジナルは普通にサンプルしたものだろ
84:デフォルトの名無しさん
20/05/22 14:03:38 lsrfRepl.net
つまり現実の楽器の音
85:デフォルトの名無しさん
20/05/22 14:08:19 c/ouk/Jn.net
>>83
シンセとかもサンプルしてるんですか?
86:デフォルトの名無しさん
20/05/22 14:39:41.09 TUWJypw2.net
>>85
いかにもデジタル的な音は昔はFM音源だった。
あと、ランダムノイズ的なものも利用。
今は、楽器を物理シミュレーションしている場合がある。
87:デフォルトの名無しさん
20/05/22 14:47:32.08 Vl9NL0Mz.net
オートチューン使うと自分の声が楽器みたいになります。
88:デフォルトの名無しさん
20/05/22 17:31:59 Sp8oG6pc.net
あるクラスのvectorに対し、個々のクラスのメンバのvectorを返すのってラムダ式でサクッと書けると思うのですが、どうやればいいですか?
struct A { int i; };
vector<A> v(10);
auto v_i = ~ラムダ式~ // サイズ10のvector<int>が返る
こんな感じです
89:デフォルトの名無しさん
20/05/22 17:34:51 O4ltSfT0.net
なにいってるのかワカランゴ
90:デフォルトの名無しさん
20/05/22 17:40:03.05 Wrt3y1wd.net
[&]{
std::vector<int> ret(v.size());
std::transform(v.begin(),v.end(),ret.begin(),[](A d){return d.i;});
return ret;
}
91:デフォルトの名無しさん
20/05/22 17:42:50.71 Wrt3y1wd.net
[](A){...}
のところは&A::iでもいいかな
92:デフォルトの名無しさん
20/05/22 17:44:13.14 Czx4JK5B.net
>>88
URLリンク(ideone.com)
93:デフォルトの名無しさん
20/05/22 17:59:27 Sp8oG6pc.net
なるほど、std::transformを使うのですね
Pythonみたいにサクッとできたらよかったのですが、ちょっとイメージと違いました
ラムダ式に変な期待、というか勘違いしてました
素直にrange for文で個々にemplace_backするほうが短いし分かりやすいので、今回はそうします
ありがとうございました
94:デフォルトの名無しさん
20/05/22 18:03:14 Wrt3y1wd.net
pythonだと[d.i for d in v]って所か?
lambdaじゃないけど
95:デフォルトの名無しさん
20/05/22 18:08:11 UA0IlUzi.net
内包表記だな
96:デフォルトの名無しさん
20/05/22 19:08:51 TUWJypw2.net
>>90
そういうSTLのbegin,end表記見てると pure Cのqsortの書き方を思い出してしまう。
危険なので毎回良く仕様書を確認してから慎重に使わないといけないという。
97:はちみつ餃子
20/05/23 00:02:55.12 jzsRlJtI.net
range を使えば楽だろうと思ったんだけど view からコンテナに変換する関数は C++20 には入らなかったの?
Range-v3 にある to みたいなやつ。
URLリンク(ericniebler.github.io)
98:デフォルトの名無しさん
20/05/23 20:12:53 Ze0+o2k4.net
>>87
diva danceみたいに?
99:デフォルトの名無しさん
20/05/27 17:21:37 UmTuuMOr.net
gdbのプロンプトでsqrtとかabsみたいな数学の関数使えないんだけど使えるようにする方法ある?
100:デフォルトの名無しさん
20/05/27 17:25:22 CVgHI0+a.net
さぁ
101:デフォルトの名無しさん
20/05/27 17:52:37.65 y56ZMEX8.net
毎回生成したくない大きめな作業用配列とかって結局どこに持っとくのが良いの?
メンバ変数として?
グローバル変数として?
102:デフォルトの名無しさん
20/05/27 18:36:53.07 IG528ewY.net
そんなことで悩むレベルなら毎回生成しろ
たぶんそんなことでは全く遅くはならん
103:デフォルトの名無しさん
20/05/27 19:02:42 8V/LyVfK.net
なるべく使う奴にしか見えないスコープに閉じ込めるんだよ
bool1個だろうと10GBの配列だろうと一緒
基本を守るだけだ
104:デフォルトの名無しさん
20/05/27 19:50:08 9+VJvnQZ.net
>>99
$ gdb some_program
(gdb) break main
(gdb) run
(gdb) print ((double(*)(double))sqrt)(2.0)
って感じで使えないかな。
たぶん some_program は何らか libm の関数を取り込んでないとダメだけど。
105:デフォルトの名無しさん
20/05/27 20:25:14 UmTuuMOr.net
>>104
できました
そのキャストが必須な理由はまだ理解してませんが
106:デフォルトの名無しさん
20/05/27 20:35:36 8D/pm3yR.net
作業用の領域の扱いってたしかにいつも悩むんだが、
*) ループや関数の内側で毎回コンテナ (vector, set, queue, etc...) を宣言し、初期化し、使う
と
*) ループや関数の外側にコンテナを宣言しておき、ループや関数の内側で初期化し、使う
だと当然後者の方が低コストで、可読性を大きく損なわない限り後者の方が良いのだよな?
初期化の計算量のオーダーは両者とも同じだが、可変長コンテナのメモリアロケーションの回数を少なくするのが重要だと思って良いのだよな?
107:デフォルトの名無しさん
20/05/27 20:37:48 8D/pm3yR.net
もう一個質問
STLコンテナの初期化は空とのswapでやったりすると思うが、この場合コンテナが置かれたメモリの場所は変わらんよな?
つまり、余計なメモリアロケーションは起
108:こらんよな?
109:デフォルトの名無しさん
20/05/27 20:45:00 fWbzFAkP.net
なんかイラっときた
110:デフォルトの名無しさん
20/05/27 20:50:33 CVgHI0+a.net
なぜ同意を求める?
部下に相槌を打つようにいつも説得しているのか?
お願いします
教えてください
も言えんのか
111:デフォルトの名無しさん
20/05/27 21:47:27 HrRUxTGO.net
行単位でファイルを読み込んだあと、パースするような処理で巨大なテキストファイルを扱う場合だと、顕著に後者が速くなる
まあ一度プロファイラで確認してみればいいよ
112:はちみつ餃子
20/05/27 23:11:34.31 OEK6SyHu.net
>>106
場合による。
「可読性を大きく損なわない限り後者の方が良い」という理屈なら
「速度を大きく損なわない限り前者の方が良い」とも言えてしまうよ。
どちらが大事かなんて場合によるとしか言いようがない。
>>107
C++ の標準ライブラリにあるコンテナに関して言えば swap でアロケーションは発生しない。
アロケーションは発生しないけど std::array はちょっと特殊で要素の swap が発生するので
線形時間がかかることになっていることには注意。
113:デフォルトの名無しさん
20/05/27 23:13:55.80 CVgHI0+a.net
要素のswapってなんだ?
再配置だろ
114:はちみつ餃子
20/05/27 23:26:27.55 OEK6SyHu.net
>>112
再配置と言えば再配置ではあるけど、 >>107 の質問について
「コンテナが置かれたメモリの場所は変わらんよな?」に対しては「はい。 コンテナのメモリの場所は変わりません」だし
「余計なメモリアロケーションは起こらんよな?」に対しては「はい。 メモリアロケーションは発生しません」なので
正確に注意点を表現するなら「(格納場所の swap ではなく) 要素単位の swap ですよ」という表現になるでしょ。
115:デフォルトの名無しさん
20/05/27 23:50:44 HrRUxTGO.net
単にgetlineした文字列を
vectorに詰める場合、
getlineしたバッファをmove push_backしたり、shrink_to_fitしてmove
push_backするより、何もせずpush_backでコピーを詰め込んでバッファを使い回しってのが一番速くてメモリ効率もよく、コードもスッキリする
116:デフォルトの名無しさん
20/05/28 00:31:33.05 deInkrVp.net
そりゃそうだ
117:デフォルトの名無しさん
20/05/28 05:51:39.46 CImYg+b8.net
>>106
比べるようなものではない
毎回再初期化させる必要があるなら前者一択
ループを抜けた後で何かするなら後者一択
118:デフォルトの名無しさん
20/05/28 17:31:30 FcJ3hVy7.net
Promiseってなんでわざわざfutureを作ってあげなきゃいけないのです?
思想的な話なの?
119:デフォルトの名無しさん
20/05/28 20:27:31.11 MpYk07ZW.net
Nowなyoungにバカ受け
120:デフォルトの名無しさん
20/05/28 22:23:48 deInkrVp.net
約束ってのは将来果たすためのものだからだよ
121:デフォルトの名無しさん
20/05/29 08:16:47 eRAtimlp.net
このネーミングセンスには禿も苦笑してたな
122:デフォルトの名無しさん
20/05/29 10:12:51.28 pukUYLjc.net
ビャーネ御大と江添のどっちだよ!
123:デフォルトの名無しさん
20/05/31 08:42:17.14 iKoRaPmL.net
STLのsetで重複したノードの登録を除外する方法がわかりません
整列基準とするint key1,key2,key3の値にかかわらず、POINT positionが重複する値だったら除外したいのですが、意図した動作になりません
例えば(0,0),(0,1),(1,0),(1,1)の4パターンのみで同一パターンは除外されるようにしたいのに20パターン以上重複して登録されてしまいます
setについてご存知の方いらっしゃいましたらご教示願います
#include <set>
#include <time.h>
#include <windows.h>
using namespace std;
bool operator ==(const POINT& inA, const POINT& inB){ return (inA.x==inB.x)&&(inA.y==inB.y); }
124:デフォルトの名無しさん
20/05/31 08:42:47.02 iKoRaPmL.net
//setに入れる要素
class CNode
{
public:
POINT position;
int key1;
int key2;
int key3;
CNode()
{
position.x=rand()%2;
position.y=rand()%2;
key1=rand()%3;
key2=rand()%5;
key3=rand()%10;
}
//setに入れるCNodeポインタを整列する基準を定義
inline bool operator()(const CNode* a, const CNode* b) const
{
//positionの値が同じ要素はsetに登録しない
bool same = (a->position == b->position);
if( same ) return false;
//↑このあたりが怪しい? ここでfalseを返すと登録数が期待よりも多過ぎ、何も返さないと期待よりも少なくなる
//キーでの整列用
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;
}
};
125:デフォルトの名無しさん
20/05/31 08:43:16.96 iKoRaPmL.net
typedef set<CNode*, CNode> NODE_POINTER_SET;
int main()
{
srand((unsigned)time(NULL));
int NUM=100;
printf("setへの登録候補数:%d\n",NUM);
CNode* dammy[1];
NODE_POINTER_SET NodePointerSet(dammy, dammy+0, CNode());
CNode* node;
for(int i=0; i<NUM; i++)
{
node = new CNode();
printf("%x:(%d,%d)【%3d %3d %3d】をセットへ\n"
,node
,node->position.x, node->position.y
,node->key1, node->key2, node->key3 );
pair<NODE_POINTER_SET::iterator, bool> insert_result = NodePointerSet.insert(node); //setへ登録
if( false == insert_result.second ) delete node; //重複で登録できなかった場合は確保したメモリを破棄
}
printf("\nset内に登録された要素数:%d\n",NodePointerSet.size());
for(NODE_POINTER_SET::const_iterator it=NodePointerSet.begin(); it!=NodePointerSet.end(); )
{
printf("%x:(%d,%d)【%3d %3d %3d】をセットから\n"
,*it
,(*it)->position.x, (*it)->position.y
,(*it)->key1, (*it)->key2, (*it)->key3 );
delete (*it); //メモリの後始末
it=NodePointerSet.erase(it); //setから削除 itは次の要素を指す
}
}
126:蟻人間
20/05/31 08:47:50.96 KExNe49d.net
std::setの整列はlessでstd::unordered_setは整列せずでequalだったと思う。
たぶん近藤してる。
127:蟻人間
20/05/31 08:55:43.87 KExNe49d.net
スマポ使わずにdelete使うのは古いよ。
128:デフォルトの名無しさん
20/05/31 09:07:29.52 iKoRaPmL.net
>>125
すみません、もう少し詳しくお教え頂けないでしょうか
初心者で見よう見まねでやっているので…
整列はできているのですが、除外がうまく動かないかんじです
スマートポインタは、難しそうなので私にはまだ早いと思っています
(でも、そのうち取り組みたい)
129:蟻人間
20/05/31 09:13:01.00 KExNe49d.net
std::setとstd::unordered_setの規格票を参照。テンプレート引数の最初は値。その次の引数は比較になっている。比較だけど、その比較はequalかlessなのかが問題だ。
lessというのは、不等号で書くと<。
equalというのは、==という意味。
130:デフォルトの名無しさん
20/05/31 09:41:05 TtXgrlrn.net
>>127
最初は見よう見まねなのは仕方ないけど、関数の仕様を解説してるページを探して仕様を確認する癖をつけるといいぞ。
131:デフォルトの名無しさん
20/05/31 09:48:26 zTMn2qwy.net
まずstd::setについて調べると
URLリンク(cpprefjp.github.io)
Compareは狭義の弱順序において前ならtrueとある
狭義の弱順序のリンクをたどると
URLリンク(cpprefjp.github.io)
!comp(a, b) && !comp(b, a) として equiv(a, b) を定義する場合、
equiv(a, b) && equiv(b, c) は equiv(a, c) を意味する必要があると書いてある。
あなたの作った比較関数は、この条件を満たさない。
{{0,0},0
132:,0,0}=={{0,1},0,0,0}=={0,1},0,0,1}だが、{{0,0},0,0,0}!={0,1},0,0,1}となってしまう。
133:デフォルトの名無しさん
20/05/31 10:48:27.53 zTMn2qwy.net
もう少しざっくりとした説明。
setは、ソートした後に、等しい要素が隣同士に並ぶことを前提としている。
これにより、隣り合った要素とだけ重複判定することで効率化している。
しかし、問題の比較関数でソートしても、等しい要素が隣同士に並ぶとは限らない。
{{0,1},0,0,6}, {{0,3},0,0,4}, {{0,1},0,0,2}
のような要素列を、この比較関数でソートしても、順序は変わらない。
先頭と末尾が等しいはずなのに隣り合っていないため、重複判定が行われない。
134:デフォルトの名無しさん
20/05/31 11:51:01 iKoRaPmL.net
難しいですね…
つまり
//positionの値が同じ要素はsetに登録しない
bool same = (a->position == b->position);
if( same ) return false;
のところをどう書き直したら動くのでしょうか?
どうか教えて下さい
m(_ _)mこのとおり!
135:デフォルトの名無しさん
20/05/31 11:53:09 27DcnLkI.net
弱順序とか区分化とかあの説明だけで理解できたら天才だろ
だから群論・集合論の教科書を数冊読むとC++がスラスラと理解できるようになる
136:デフォルトの名無しさん
20/05/31 11:53:23 J1D5Z9UC.net
自分でやる気がない人に教える気にはならないなぁ。
137:デフォルトの名無しさん
20/05/31 12:02:25 6nfzU/vT.net
bool CNode::operator<(const CNode& rhs) const {
if (key1 != rhs.key1) { return (key1 < rhs.key1); }
else if (key2 != rhs.key2) { return (key2 < rhs.key2); }
else if (key3 != rhs.key3) { return (key3 < rhs.key3); }
else { return false; }
}
を実装したら最低限逝ける、
等値演算子「==」は、それがCNodeのメソッドまたはCNode&を引数にとる
関数定義がなされていなければ(!(a < b) && !(b < a))で遂行される
ただしそれでは効率が悪いので(「==」1回につきoperator<()が2回呼ばれるので)、
「==」も手動で実装したらモアベターではある
138:デフォルトの名無しさん
20/05/31 12:12:06 zTMn2qwy.net
>>132
そこだけ書き換えて修正するのは無理
あきらめて別の方法を考えることをお勧めする
139:デフォルトの名無しさん
20/05/31 12:25:20 HQ8vNkm/.net
そもそもCNodeにoperator<実装してないのになんでコンパイル通ってんのか謎
隠してるコードがあるなら全部出せ
140:デフォルトの名無しさん
20/05/31 12:45:05.74 J1D5Z9UC.net
>>137
> typedef set<CNode*, CNode> NODE_POINTER_SET;
141:蟻人間
20/05/31 12:51:20.01 KExNe49d.net
inline bool operator()(const CNode* a, const CNode* b) const
{
if(a->key1 < b->key1) return true;
if(a->key1 > b->key1) return false;
if(a->key2 < b->key2) return true;
if(a->key2 > b->key2) return false;
if(a->key3 < b->key3) return true;
if(a->key3 > b->key3) return false;
//ここまでヒント。
}
142:デフォルトの名無しさん
20/05/31 12:58:31.73 6nfzU/vT.net
>//positionの値が同じ要素はsetに登録しない
>bool same = (a->position == b->position);
>if( same ) return false;
仕様誤解してたサーセンgrz、、
143:デフォルトの名無しさん
20/05/31 13:17:45 iKoRaPmL.net
皆様ありがとうございます
>>135
なるほど、<が2回呼ばれるのですか(いろいろ試していて2回ずつカウントされているのを不思議に思ってました)
ご紹介頂いたコードを追加しましたが、rhsがポインタでないせいか効果がありませんでした
ポインタを、そのメンバ変数基準で整列させたいのですが、
bool operator<(const CNode* lhs, const CNode* rhs)const
で定義しようとするとコンパイルエラーC2804
binary 'operator <' に引数が多すぎます。
になってしまいます
==演算子も同様に駄目でした
<や==演算子オーバーロードでポインタを整列させる事は無理なのでしょうか?
>>140
の内容からすると、無理なのかな?
(自分で試してみて無理そうだと思ったので、仕方なく()オーバーロードで定義を書いていました)
>>139
ヒント見ても理解できないこの無能な鈍物めにお答えを賜りたく
どうかお願いします!
144:デフォルトの名無しさん
20/05/31 13:48:52.93 J1D5Z9UC.net
>>122
> 整列基準とするint key1,key2,key3の値にかかわらず、POINT positionが重複する値だったら除外したい
これ要求に間違いが無いなら、独立した比較基準(整列用と重複判定用)が2つあることになるので、
単一の比較関数(およびset)で解決しようとしてるのが間違いかな。
145:デフォルトの名無しさん
20/05/31 13:58:58.98 27DcnLkI.net
△ ヒント
○ これ以上は分かりませんでしたがMOTTAINAIので貼ります
146:デフォルトの名無しさん
20/05/31 14:31:43.92 iKoRaPmL.net
簡単に出来そうだと思っていた事が、結構な難問だったようですね…
自分の力では無理そうだという事がわかっただけでも収穫でした
皆様ありがとうございました
147:デフォルトの名無しさん
20/05/31 14:33:26.01 6nfzU/vT.net
回答を示す、
1. 「<」と「==」演算子をグローバルな関数として定義する版:
URLリンク(ideone.com)
2. 「<」と「==」演算子をクラスのメソッドとして定義する版:
URLリンク(ideone.com)
3. (参考)スマポ版
URLリンク(ideone.com)
元のコードはいきなりinsertしようとしているがinsertの動作はinsertしてから重複だったかどうか返すというものなので、
生ポインタ版である1と2では事前にfindしている
3は事前findが不要で本来のコードとなったが、動作は後優先(先にinsertしたaと、後からinsertしたbがsameの場合、aが削除され、bが残る。)
148:デフォルトの名無しさん
20/05/31 14:40:09.33 J1D5Z9UC.net
>>135
> 等値演算子「==」は、それがCNodeのメソッドまたはCNode&を引数にとる
> 関数定義がなされていなければ(!(a < b) && !(b < a))で遂行される
要出典
>>145
> insertの動作はinsertしてから重複だったかどうか返すというもの
要出典
149:デフォルトの名無しさん
20/05/31 15:24:55.05 6nfzU/vT.net
>>146
> > insertの動作はinsertしてから重複だったかどうか返すというもの
> 要出展
仕様誤解してたサーセンgrz、、
と言うわけで>>145のソースコードは以下の通り訂正汁、
1のソースコード ==> URLリンク(ideone.com)
2のソースコード ==> URLリンク(ideone.com)
3のソースコード ==> URLリンク(ideone.com)
(3は間違ったコメントを削除、およびアドレスの表示の誤りを訂正)
> > 等値演算子「==」は、それがCNodeのメソッドまたはCNode&を引数にとる
> > 関数定義がなされていなければ(!(a < b) && !(b < a))で遂行される
> 要出典
しらそん;;
テンプレートの定義とC++の言語仕様とかstd::rel_opsの存在意義とか想像したらワカル
150:デフォルトの名無しさん
20/05/31 15:28:53.38 xFqcIaF1.net
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へ登録
}
}
151:デフォルトの名無しさん
20/05/31 15:41:55 J1D5Z9UC.net
>>147
key1,key2,key3 で整列しないのは回答として不適ではないの?
等値演算子「==」の話はただの思い込みだったということでいいんかね。
152:デフォルトの名無しさん
20/05/31 16:08:01 HQ8vNkm/.net
setの重複排除条件をコントロールしたいだけなら
std::(unordered_)setのPredテンプレート引数で制御すればいいだけの話じゃないの?
からかって遊んでるだけ?
153:デフォルトの名無しさん
20/05/31 16:37:00 zTMn2qwy.net
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}
だけになってしまう。逆順でも同様の問題がある。
154:デフォルトの名無しさん
20/05/31 16:47:23 HQ8vNkm/.net
その隠し要件どこに書いてるの?もしそれが必要なら横着せずに全部持っておくしかないね
155:デフォルトの名無しさん
20/05/31 17:24:57 zTMn2qwy.net
書いてるところはない。すまん。
156:122
20/06/01 08:41:58 VTbJvOd1.net
すみません仕様間違えていました
>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さんもありがとうございます
157:デフォルトの名無しさん
20/06/01 08:53:47 idPskxLG.net
>>154
> return true;//ここをfalseではなくtrueに変更
明らかに違反してるじゃねーの?
URLリンク(cpprefjp.github.io)
> 「狭義 (strict) 」 は非反射関係 (irreflexive relation) (全ての x について !comp(x,x) である)の要求
158:デフォルトの名無しさん
20/06/01 09:14:14 VTbJvOd1.net
難しい事はわかりませんが、
動作検証が足りてないかんじでしょうか
もし駄目だったら、諦めて別の方法を考えようと思います
159:デフォルトの名無しさん
20/06/01 14:34:32 o7IiynR8.net
double *array1;
array1 = new double[count]();
と書いた場合の、[count] の後ろの () の意味は何でしょうか?
array1 = new double[count];
と書いた場合との違いは何でしょうか?
()の中に何か書くことは出来ますか?
160:はちみつ餃子 ◆8X2XSCHEME
20/06/01 15:11:25 0yVOdbpz.net
>>157
内容を初期化するかどうか。
普通のクラスでは括弧がなくてもデフォルトコンストラクタで初期化されるので
空の括弧があってもなくても意味はかわらないけど、
プリミティブな型などでは括弧無しのときは初期化しない。 (つまり内容は不定)
括弧があればゼロで初期化されることが保証される。
C++14 あたりからはこんな感じで初期化することもできるよ。
double *array1 = new double[]{1,2,3};
161:デフォルトの名無しさん
20/06/01 15:34:55.48 o7IiynR8.net
>>158
をー。有難う。
162:デフォルトの名無しさん
20/06/01 18:12:14.25 8BAaT/q7.net
昔はよく{0}って書いてたというか書けなかったな
163:デフォルトの名無しさん
20/06/01 18:13:08.51 8BAaT/q7.net
×書けなかったな
○しか書けなかった
164:デフォルトの名無しさん
20/06/02 10:09:36 d/ekt+66.net
ヘッダでvector要素の型を先行宣言で済ますことができるのc++20からだっけ?
165:デフォルトの名無しさん
20/06/02 11:21:52.93 7ZgjbGq0.net
Working Draft, Standard for Programming Language C++
Document Number: N4713, Date: 2017-11-27
というPDFを読んでいるんだけど、explicitキーワードの事について調べようとしても、
索引(index)には載ってないようだけど、どこに書いてる?
166:デフォルトの名無しさん
20/06/02 12:04:07 eZHppilZ.net
>>163
N4713だよね? P.1373の2行目は見た?
167:デフォルトの名無しさん
20/06/02 12:30:40.82 7ZgjbGq0.net
>>164
Indexのspecifier項目のサブ項目として書いてあったんですね。
でもこれだとexplicitが何なのかを知りたい人にとっては索引としての役割を果たさないです。
いわば国語辞典で知らない単語を調べるのに勝手にカテゴリー分けしてあるようなものです。
それでは辞典の意味をなしません。
168:はちみつ餃子
20/06/02 12:34:14.97 N0F889O8.net
>>165
PDF なのだから、ある項目について知りたければ検索すればいいよ。
この分量を印刷して読んでいるわけではないよね?
169:デフォルトの名無しさん
20/06/02 12:47:31 67GQ09ou.net
試しに検索かけたら1102件もヒットしたやんけ!餃子のバカバカ
170:デフォルトの名無しさん
20/06/02 13:55:05.15 7ZgjbGq0.net
AdobeRederは使いにくいので、SumatraPDF Reader を使って、まず、
左側のペーンに出てくる目次で index をクリックし、右側のペーンに
巻末の索引を出した後、右側のペーンの中で CTRL+Fを押して、
explicitを検索すると良いよう。
171:デフォルトの名無しさん
20/06/02 14:01:01.31 Ja+74ng6.net
素直にありがとうも言えないのか
これだからC++erは
172:デフォルトの名無しさん
20/06/02 14:11:59 7ZgjbGq0.net
>>169
ありがとう。
173:デフォルトの名無しさん
20/06/02 14:58:48 7ZgjbGq0.net
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と
識別されるのでしょうか。
174:デフォルトの名無しさん
20/06/02 15:00:52 7ZgjbGq0.net
ちなみに、
namespace-name:
identifier
namespace-alias
namespace-alias:
identifier
となっており、namespace-nameには、a::bb::cc のようなものは含まれないと思われます。
175:はちみつ餃子 ◆8X2XSCHEME
20/06/02 15:16:37 N0F889O8.net
>>167
索引だけ検索すればええんや。
176:デフォルトの名無しさん
20/06/02 16:38:50 7ZgjbGq0.net
>>171
の定義だと、
decltype(x)::decltype(y)::decltype(z)
のようなものは使えないということになるようです。
ひょっとすると、C++の仕様書的には、
ns1::ns2::ns3::変数名
も使えないのもかも知れませんがよく分かりません。
177:デフォルトの名無しさん
20/06/02 17:30:17.43 cu23LxCqi
C++初心者がオセロを作ろうと思います。
外部設計でクラス図を作ろうとし、
調べましたがクラスとして抽出する単位に困っています。
クラスにするものと理由、または抽出する方法を教えていただけませんか。
178:デフォルトの名無しさん
20/06/02 17:48:50.88 eZHppilZ.net
>>167
つーかよ、その1102件を末尾から順に見ていくとすぐなんだが
そういう生活の知恵はあんまりないのかい?
179:デフォルトの名無しさん
20/06/02 19:53:34.27 Ja+74ng6.net
よくわかんないけど
ツイッターで誹謗中傷してそう
180:デフォルトの名無しさん
20/06/03 10:50:24 TdRUmxlv.net
URLリンク(en.cppreference.com)
MyHash{}(obj)
std::hash<S>{}(obj)
の{}は、直接リスト初期化のもので、いったんMyHash型やstd::hash<S>型のテンポラリ・オブジェクトを作成してからoperator()関数をobjを実引数にして呼び出しているという理解でよろしいですか?
181:デフォルトの名無しさん
20/06/03 11:38:29 Nfbl5e81.net
newしたあとにdeleteしなくてもアプリケーションを終了すればメモリは解放されますか?
182:デフォルトの名無しさん
20/06/03 11:58:33 VI2pYiE8.net
OSによる
183:デフォルトの名無しさん
20/06/03 12:21:28.49 TdRUmxlv.net
>>179
Windows/Mac/Linuxではメモリー領域自体は絶対に解放される。
ただし、deleteが呼び出されるわけではないので、原則的にはデストラクタは呼び出されない。
184:デフォルトの名無しさん
20/06/03 12:24:39.32 DAHZjgl3.net
>>176
たまたまの結果を生活の知恵とかw
キーワードと通常言語が被らない日本語万歳だな
185:デフォルトの名無しさん
20/06/03 12:28:15 Nfbl5e81.net
>>180
>>181
ありがとうございます!
186:はちみつ餃子
20/06/03 13:34:40.56 3vvIkHpN.net
>>179
プロセスに割り当てられているメモリは現代の普通のデスクトップOS上でならプロセスの終了と共に解放されるのだけど、
オブジェクトは外部のリソースのハンドルを掴んでいることがあるから
それを正常に (デストラクタで) 後始末しないとリソースリークが起こる可能性はある。
POD 型のオブジェクトに限ってならば管理されてるリソースはメモリだけだから
delete しなくてもプロセス終了時におおよそ安全に解放されることは期待していいと思う。
言語仕様での保証はないので C++ スレ的に言えば「やめとけ」ってことになるけど。
187:デフォルトの名無しさん
20/06/03 13:47:15.12 gQ0mUfsI.net
メモリと断っている人に余計なこといわなくていいと思うけど
アプリの異常終了であっても解放されてほしいのだろうから
c++の終了処理に依存してもしゃない
188:デフォルトの名無しさん
20/06/03 14:24:00 UHE1JPNz.net
>>182
何がたまたまの結果だよ
C++規格票とドラフトは巻末に索引があって
検索でヒットしすぎるときは末尾を見に行けば
そこは索引の中である可能性が大きいというのを
思いつくことができんのかおまえさんの頭では
だから見つけられなくて聞いてきたというなら合点だ
189:デフォルトの名無しさん
20/06/03 14:27:27 UHE1JPNz.net
>>179
世の中すべての::operator newの内容を確認してからでないと答えられない質問だ
もっと言うなら将来にわたってタイムマシンで確認してくる必要があるから
調査の工数が発散しちまう
どういう意味かわかるな?
190:デフォルトの名無しさん
20/06/03 15:04:54 TdRUmxlv.net
URLリンク(qiita.com)
int main(){
double a = 1.5;
std::string b = "Hello World";
struct foo{};
xyz(a, b, foo());
}
↑のfoo()は一時オブジェクトの作成ですね?
191:デフォルトの名無しさん
20/06/03 15:11:30.37 DAHZjgl3.net
>>186
他人の茶々入れに何言ってんだよw
192:デフォルトの名無しさん
20/06/03 15:12:28.27 DAHZjgl3.net
>>187
やはりこんな奴かwww
193:デフォルトの名無しさん
20/06/03 15:35:53.72 TdRUmxlv.net
めちゃくちゃ難しいです。#100の部分は恐らく「部分特殊化」というものだと思うのですが、
自分がネットで調べた簡単な部分特殊化とはちょっと違っているようです。
URLリンク(ja.wikipedia.org)
// どのようなテンプレート引数であっても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;
}
194:はちみつ餃子 ◆8X2XSCHEME
20/06/03 15:40:53 3vvIkHpN.net
>>188
そういうのはコメントで質問すれば?
195:デフォルトの名無しさん
20/06/03 15:42:50.44 UHE1JPNz.net
>>189
他人かどうかは関係ねえぜ
俺が生活の知恵と言ったことを
たまたまの結果と言ったのはおまえさんに他ならない
必然的に思いつくまでの思考過程を示されて
自分の浅はかさを誤魔化すのに他人がどうのと
再び浅はかな言い訳で恥の上塗りするのは
やめたほうがいいんじゃないかな
196:デフォルトの名無しさん
20/06/03 15:44:00.45 TdRUmxlv.net
>>191
部分特殊化とは、
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>はどうなるんでしょう??
197:デフォルトの名無しさん
20/06/03 15:46:30.08 DAHZjgl3.net
>>193
やはりこういうやつかwww
198:デフォルトの名無しさん
20/06/03 15:47:08.09 UHE1JPNz.net
#2
つーか、そんくらいやってみろよ
199:デフォルトの名無しさん
20/06/03 15:47:50 UHE1JPNz.net
>>195
やーい、同じことしか言わなくなってやんのw
200:デフォルトの名無しさん
20/06/03 15:49:26 DAHZjgl3.net
必ずしも索引があるとは限らないのにあることを一般論化してドヤ顔するのと
ヒープ解放するかどうかはすべてを尽くして調べられないからわからたないとドヤ顔してる奴が
同じ人物だってのが困るわぁwwww
201:デフォルトの名無しさん
20/06/03 15:49:47 DAHZjgl3.net
>>197
>>198
202:デフォルトの名無しさん
20/06/03 15:52:20 TdRUmxlv.net
>>194 >>196
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 ]
203:デフォルトの名無しさん
20/06/03 16:02:27 UHE1JPNz.net
>>198
C++規格票とドラフトと言ったはずだ
必ずしも索引があるとは限らないとぬかすなら
そうなっていないC++規格票とドラフトを例示しろ
事実無根の誹謗中傷はやめてもらおうか
204:はちみつ餃子 ◆8X2XSCHEME
20/06/03 16:06:58 3vvIkHpN.net
>>194
ほんとに >>196 の言う通りだわ。
やってみてから思った通りにならないのはなんでだろうっていうならまだしも
「どうなるんでしょうか」なんてやってみりゃわかることだろ。
まあ C++ には未定義とか処理系定義とかもあるから
実際の挙動を以て言語仕様を理解しようとするのは危険でもあるんだが……。
特殊化ってのはまさに「特殊な場合」を定義するもんだよ。
その場合には A<T1, T2> のテンプレートの特殊な場合として A<T, void> の場合を定義してることになる。
特殊な場合である A<T, void> は特殊でない場合の A<T1, T2> と同じ形式である必要がある。
>>200
基本的な理念が理解できていないのに仕様を読んでも理解できねーよ。
(まあたまには仕様からとっかかる超人もいないことはないが。)
お前は Rust スレでも見当はずれの根拠をコピペしては意味不明なことを言ってるが、
普通に入門書を読んでくれ。
205:デフォルトの名無しさん
20/06/03 16:19:58 H6kZ1pQy.net
イキイキしてんなwww
206:デフォルトの名無しさん
20/06/03 16:24:47 DAHZjgl3.net
>>201
予想通りで乙w
207:デフォルトの名無しさん
20/06/03 16:25:39.34 TdRUmxlv.net
>>202
結局、答えられないんですね。
208:デフォルトの名無しさん
20/06/03 16:29:44.75 gQ0mUfsI.net
そこで煽ってどうするw
209:デフォルトの名無しさん
20/06/03 16:50:20.37 UHE1JPNz.net
質問しといて無礼な口の利き方をするやつにはお仕置きだ
一切何も教えない
210:デフォルトの名無しさん
20/06/03 16:50:59.31 UHE1JPNz.net
>>204
ぐうの音も出ねえとは
おまえさんのことだな
211:デフォルトの名無しさん
20/06/03 17:02:24.74 TdRUmxlv.net
>>207
答えられないだけ。
212:デフォルトの名無しさん
20/06/03 17:03:53.52 DAHZjgl3.net
>>208
都合よくげんていつけたりなくしたりwwww
213:デフォルトの名無しさん
20/06/03 17:04:33.42 DAHZjgl3.net
>>207
なんでも上から目線
やはりこういうやつかwwww
214:晒しage
20/06/03 17:11:10.63 UHE1JPNz.net
181 返信:デフォルトの名無しさん[sage] 投稿日:2020/06/03(水) 12:24:39.32 ID:DAHZjgl3 [1/9]
>>176
たまたまの結果を生活の知恵とかw
キーワードと通常言語が被らない日本語万歳だな
215:sage
20/06/03 17:55:41 B/1kftuN.net
getCFile()ってよくわからないので教えてください。
コードに次のような部分がありました。 getFile()では置き換えられない?
/// \brief Get C-file.
/// \return Extracted stdio's @c FILE structure.
std::FILE * getCFile();
file_.getCFile()
216:デフォルトの名無しさん
20/06/03 18:46:53 TdRUmxlv.net
>>194
推定だけど、
A<T, void>
の場合、2番目の仮引数がvoid型になっているので、そこには実引数を
指定しないということになっているらしい。
その結果、A<1> みたいに1つだけの引数でtemplateをinstance化できる
様になっている気がする。
まだ仕様書で確認したわけではない。
217:デフォルトの名無しさん
20/06/03 18:53:53.18 HVfXpWIv.net
いや、省略した場合のデフォルトを指定しない限り、そんなことにはならない
template <typename T1,typename T2=void>
class A;
みたいにする
まあ、primaryの定義と同時にも書けるし、そっちが普通
218:はちみつ餃子
20/06/03 19:02:53.85 3vvIkHpN.net
>>205
俺が答えていることすら理解できてない模様。
219:デフォルトの名無しさん
20/06/03 19:07:42.01 TdRUmxlv.net
[驚くべきパターンマッチング]
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);
}
220:デフォルトの名無しさん
20/06/03 19:08:51.14 TdRUmxlv.net
>>216
仮に心の中にあってもあなたは全く言語化して無いないので駄目。
221:デフォルトの名無しさん
20/06/03 19:10:26.76 TdRUmxlv.net
>>215 じゃあ、Wikipediaに載っていた>>191の例はどう説明すれば良い?
223:デフォルトの名無しさん
20/06/03 19:14:50.42 TdRUmxlv.net
>>219
そういえば仕様書に、templateをinstance化する際は、既に deducedされたパラメータは A<B>のBの中には書かないで良い例が書いてあった。
たとえば、
template <typename T1, typename T2>T1 f(T2 a);
のような場合、
f<T1>(100);
みたいにすれば、T2はint型だと分かるので、f<T1,int>(100)と書かなくて良いというもの。
それかな?
224:デフォルトの名無しさん
20/06/03 19:17:57 TdRUmxlv.net
そうではなく、>>191 の場合は、primary template として、
template <typename T, typename = void>
struct has_typedef_foobar : std::false_type {};
と、第二パラメータにデフォルト引数が書いてあるからか。
225:デフォルトの名無しさん
20/06/03 19:20:51 HVfXpWIv.net
>>219
190ってまさにtypename=voidしている例じゃね
226:デフォルトの名無しさん
20/06/03 19:27:23 TdRUmxlv.net
>>222
>>221と入れ違いになった。
それで辻褄は合うけど、primary templage definition では、
template <typename T, typename = void>
で、部分特殊化する際には、
template <typename T>
としてあって、物凄い複雑だね。
227:デフォルトの名無しさん
20/06/03 19:48:21.19 XMrfvYH7.net
TdRUmxlvは自分の日記帳に書いてくんないかな
228:デフォルトの名無しさん
20/06/03 20:15:01.97 TdRUmxlv.net
失礼しました。
でも断っておくと、俺ははちみつに対してそんなに悪口は言ってない。
スレの流れで混乱していたようだが、言っていたのは別人だから悪しからず。
229:デフォルトの名無しさん
20/06/03 22:21:05.04 OT4MJN13.net
いちいちイラッとする書きっぷりはID:TdRUmxlvのコミュ力が絶望的に低くいだけなので許してあげてください
230:デフォルトの名無しさん
20/06/03 23:25:41 SSmphgFp.net
憂さ晴らしに靖国に落書きしそう
231:デフォルトの名無しさん
20/06/04 08:16:53 85VTz4/e.net
とっくにNG
232:デフォルトの名無しさん
20/06/04 13:15:35 pT22FhoL.net
int& r_i=7; // compile error
int&& rr_i=7; // OK
2行目は、どういう仕組みになってるんでしょう?
7という値がメモリー上にはどこにも存在して無い場合もあるはずで、
その場合でも右辺値参照を持てるものなのでしょうか?
たとえばコンパイラの中に7という値は持っていても、アセンブラレベルでは、
どのsectionの中にも7というデータが入れられて無い場合もあると思うのです。
それだと7の入っている場所のアドレスは存在しえません。
例え「"右辺値"参照」であってもはアドレスが必要のはずですが。
233:デフォルトの名無しさん
20/06/04 13:17:22 +U2drwkO.net
構ってはいけない
234:デフォルトの名無しさん
20/06/04 14:43:12.11 2rF1/e7a.net
>>229
言語規格的にはrr_iという名前を通じて7という値が取れれば何でもいい
コンパイラが具体的にどうするかはコンパイラの勝手
アドレスがどこかで必要なら一時オブジェクトを作るようにするし必要なければ作らなくてもいい
235:デフォルトの名無しさん
20/06/04 18:50:33 pT22FhoL.net
>>231
どうやら、7の入ったint型の隠れた変数を一時オブジェクトとして作成してから、
そのアドレスをrr_iに入れているそうです。
236:デフォルトの名無しさん
20/06/07 01:50:09 P1Z5Y5je.net
>>229
int& r_i=7; // compile error
確かにこれはダメ
int&& rr_i=7; // OK
int& rr_j = rr_i; // OK
これおかしくね?
237:デフォルトの名無しさん
20/06/07 01:57:43 loMZGJMS.net
&&嫌いだわ
238:デフォルトの名無しさん
20/06/07 03:20:06 NFGxwtnl.net
右辺値参照自身は左辺値定期
239:はちみつ餃子
20/06/07 09:08:16.75 fhJ4vSsJ.net
だから std::forward が要るんだよ。
240:デフォルトの名無しさん
20/06/07 11:40:26 uPPavgXr.net
昔のソースコードからの派生で開発する際、リソースの開放だけをデストラクタで行うように変えたいと考えています
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以降の作法として正しいでしょうか?
241:デフォルトの名無しさん
20/06/07 13:44:00.54 ocvuft6U.net
作法とか正しいとかより自分で考えた方がいいと思うけど
その場合あえて言えば、hFile渡すとこは
直接CreateFileの戻り値使って(hFileを宣言しない)、dummyの持つハンドル経由で使った方が
一貫性が取れていいかも
理想を言えば全部ラップした方がいいんだろうけど
242:デフォルトの名無しさん
20/06/07 13:55:18.98 HzkE9Nko.net
>>237
その方法は始めてみた。
でも、unique_ptrなどを使わなくても、普通にC++98レベルのclassだけを使っても、RAIIは書ける。
243:デフォルトの名無しさん
20/06/07 14:54:05 HzkE9Nko.net
>>239
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が解放される。
244:デフォルトの名無しさん
20/06/07 15:37:10.54 NFGxwtnl.net
ポインタ以外のリソースでRAIIやらせるためのstd::unique_resourceが提案されてるけど難航してる
リソースの種類や使い方でそれぞれ事情が違うから無理矢理一般化しても上手く行かないらしい
245:デフォルトの名無しさん
20/06/07 15:48:34.18 HzkE9Nko.net
>>240
補足すると、このコードだとCreateFile()した後、返されたハンドル値を No CheckでCMyXのコンストラクタに渡しているが、本当はその前にINVALID_HANDLE_VALUEかどうかをチェックしておく必要がある。
246:デフォルトの名無しさん
20/06/07 21:39:58 P1Z5Y5je.net
>>235
そこじゃなくて
int& r_i=7; // compile error
をエラーにする必要ある?ってこと
リテラルを右辺値参照できんならエラーにする必要ないじゃん
247:デフォルトの名無しさん
20/06/07 21:49:43 NFGxwtnl.net
それがエラーじゃなかったら右辺値参照は何のためにあるんだよ
248:デフォルトの名無しさん
20/06/07 21:56:24.65 P1Z5Y5je.net
>>244
別にリテラル受けるためにあるわけじゃないでしょ
別の言い方すると
int&& rr_i=7; // OK
わざわざ一時オブジェクトつくってこれOKにする理由って何なの?
249:デフォルトの名無しさん
20/06/07 22:22:50.71 uPPavgXr.net
>>238,239,241
ありがとうございます
>>240
はい、そうなんですけれど、こういったコードも省略したいということと、
頻繁に必要になるので標準ライブラリに入っていないかなって期待していたわけです
>>241
なるほどstd::unique_resourceっていうので検討中なんですね
これが標準に組み込まれるのを期待しておきます
250:デフォルトの名無しさん
20/06/07 23:16:58 +YSUT0gy.net
More Effective C++ の、
項目9 : リソースリークを防ぐためにデストラクタを使う
項目11 : デストラクタから発生した例外を抑える
デストラクタ中で、例外がキャッチされない場合、
terminate を呼ばれて、受け身も取れず、強制終了させられる
251:デフォルトの名無しさん
20/06/08 11:21:10.82 KlUsfYw8.net
>>246
CreateFile以外にも似たようなのが沢山あって、それを楽にRAIIにしたいって話?
ならすでにunique_resourceはあるらしいけど(experimentalだかどこかに
あるいはそれに近い実装も公開されてるので落としてくればいいかと
逆にCreateFileだけなら素直に自分でクラス書いた方が後々楽になると思う
252:はちみつ餃子 ◆8X2XSCHEME
20/06/08 12:33:58 KAmnJXdU.net
リソースの解放以外は生のハンドルが使いたいという前提だと、
「unique_resource で包まれたオブジェクトからハンドル使うたびに (get で) 取り出す」という操作が必要になる。
たぶん >>237 の書きようだとそういうことはしたくないんだろうし、
包む前のハンドル (が入った変数) をそのまま使うとなると折角の所有権管理が台無しだ。
unique_resource はリソースの所有権管理の仕組みであって、
デストラクタでリソース解放もするのは所有権管理に付随するものに過ぎない。
どちらかというと scope_exit の方がやりたいことに近そうな気がする。
けど、いずれにしても中途半端なんだよな。
現時点でリソースの解放 (CloseHandle) がちゃんとできているなら
それを unique_resource (なり scope_exit なり) に置き換える意味はあまりないんじゃなかろうか。
「CloseHandle の書き漏らし」ってのと「scope_exit の書き忘れ」
ってのは同程度に有り得ることで、そんなに良くならないと思うよ。
型としての HANDLE の実態は void* なので、
HANDLE を HANDLE として扱おうとする限り C++ の型システムの恩恵はあまり受けられない。
古いコードをなるべくいじらずに使いたいという理由はとてもよくわかるのだけれど、
半端な書き換えをするくらいなら抽象レイヤをきちんと構築した方が結局は楽だと思う。
253:デフォルトの名無しさん
20/06/08 15:51:51 blut5LG8.net
void * と型として区別出来ない?
型はともかくそもそも HANDLE は値の範囲が決まってたか
254:はちみつ餃子 ◆8X2XSCHEME
20/06/08 16:16:36 KAmnJXdU.net
かなり前から DECLARE_HANDLE マクロで HANDLE は固有の型として定義してた。
そこは私の認識間違いだ。 すまぬ。
>>250
void* という型として認識出来たところで何が出来るものでもないよねという意図だった。
255:デフォルトの名無しさん
20/06/08 23:54:23 3GgB/ZcK.net
>>240
しね~よ
void bar(CMyX& x, HANDLE h) {
// hを思わずclose
CloseHandle(h);
}
void foo() {
HANDLE hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
CMyX y(hFile);
bar(x, h);
// このあとしぬ
}
>>240のCMyXはハンドルをマジWrapしてるだけで全く使えない
しねよ
256:デフォルトの名無しさん
20/06/08 23:56:48 3GgB/ZcK.net
というわけでget()メソッドが無いのも大概だが
それより悪いのはCloseHandle()が失敗したときのことを何も考えていないことだ
ファイルのClose失敗はエラーハンドリング省略で済まされる問題ではない
デストラクタでCloseHandle()を一概に否定するものではないが、
デストラクタから例外を飛ばすわけにもいかないので、エラーの通知先オブジェクトへのポインタをCMyXは持つ必要がある
257:デフォルトの名無しさん
20/06/09 00:00:40 Ah9aU5+0.net
いきってツッコむほどのことかそれ
258:デフォルトの名無しさん
20/06/09 03:22:41.56 SETbyCsO.net
>>253
File Handle のような OS Object については、RAIIで処理するのは実は難しいんだよ。
だから、WindowのDestroyWindow()もデストラクタで処理する前に明示的に
CWnd::DestoryWindow()を自分で呼び出すほうが良かったりするんだから。
デストラクタだけを頼りにすると、main()やWinMain()関数の後の
クリーンアップ処理の中で CloseHandle()が呼び出されたりすることになるが、
それは結構微妙な話になる。
なぜかといえば、まず、OS自体がそもそも、プロセスが終了する時には
勝手にすべてのハンドルを閉じてくれる。ならば、CloseHandle()なんて明示的に
書く必要が無い、というそもそも論が出てくる。
それプラス、あなたが言ったように、CloseHandle()で失敗した場合にどうなるか
という話もあることはある。
そもそも、個人的には、ファイルを開いたら、なるべく速く Closeする方が良いと思っている
ので、RAIIでファイルハンドルを処理するのは余りぴんと来ない。
259:デフォルトの名無しさん
20/06/09 06:33:30.92 iLzxHGzP.net
アプリ全体の終了が前提になっているおかしな主張だな
260:デフォルトの名無しさん
20/06/09 06:54:05.72 unijwXHc.net
CloseHandleやfileのcloseで失敗する様な状況って、普通のアプリじゃ実質対処不能な致命的な状態だろ
素直に落ちるなりおかしな挙動になるなりすればいいのよ
261:デフォルトの名無しさん
20/06/09 07:55:59.54 n28tZ6EV.net
OSやハードが正常稼働時ならそこら辺の例外発生はないからね。
リソース解放忘れてデスクリプタやらのリソース使い果たしたり、ファイルの占有したままで他のアプリに迷惑かけたりするのを防止するのにRAII使うのは有用
262:デフォルトの名無しさん
20/06/09 08:00:35.85 JJE9ezaH.net
HANDLEってOS側からはそれが有効か無効か判断できるから、無効なハンドルを
間違って使ったりCloseHandleしてしまってもエラーを返すだけで致命的な状態には
なりにくい
263:865
20/06/09 09:27:54.99 cTF8gHLn.net
前提にしているのがどんなOSであろうと
C++的には環境依存な話だね
264:デフォルトの名無しさん
20/06/09 15:37:05.70 FUnSNOef.net
要素はintと任意オブジェ
int値を渡すと
論理和がゼロ以外の要素を
返すコンテナってないですか?
265:デフォルトの名無しさん
20/06/09 16:12:25.38 SETbyCsO.net
>>257
もし、CTRL+Sを処理するイベントハンドラの中で、単純に CloseHandle()を自分で呼び出して
失敗した場合であれば、保存に失敗した事をAfxMessageBox()で知らせた後、なんとか今までの
メモリ中のデータだけは壊さずに処理できればベスト。
しかし、他の何らかの例外が発生した時に、RAIIによって自動的に呼び出されたデストラクタの中で
CloseHandle()に失敗した場合には、対処が難しそう。
テストも難しいし、余りそういう状況は起きないので優先順位は低いが。
266:デフォルトの名無しさん
20/06/09 17:15:04.89 nNNGB7r+.net
>>261
std::pair<int, SomeObj> を格納するコンテナと
「int部分とある値とのビットORを結果とする述語」を
std::copy_if() に渡すような話かな。
「任意オブジェ」部分が要素ごとに異なる、だと難問な気がするけど。
267:デフォルトの名無しさん
20/06/09 17:30:16 n28tZ6EV.net
論理積ではなく?
268:デフォルトの名無しさん
20/06/09 17:42:20.88 nNNGB7r+.net
確かに論理和だと「つまらない」結果になりそうね。
普通の使い方なら論理積で抽出か。
排他的論理和は「もっと面白い」かも知れんけど。
269:デフォルトの名無しさん
20/06/09 22:35:23.41 FUnSNOef.net
>>263
それで組んでみます
ありがとうございました
あと実際は論理積です
270:デフォルトの名無しさん
20/06/10 05:39:12.94 67cF/bBY.net
>>257
「ログファイルなので書込みに失敗しても大勢に影響が無い」とか
「作業用ファイルfは書いた後必ず誰かがリードオープンするから書込みに失敗していたらそこでワカルから書込みのエラーチェックを省略する」
みたいな判断はアプリの設計としてはアリかもしれないが、CMyHandleみたいな汎用部品的に使われ得る低水準クラスではナシ
これをアリだと思う香具師はお気楽すぐる、
271:
20/06/10 05:44:30.52 OTs8rmHM.net
>>267
でも >>257 の CloseHandle() や fclose() が失敗したからといって、何か手が打てるのですか?
何もできないのでは?
もしかして黙って exit() するのですか?
272:デフォルトの名無しさん
20/06/10 07:23:10 itI4VuCe.net
てか、自動解放するクラス作っても手動解放する手段残しておけば、使う側で特別な処理は出来るんだよね
273:デフォルトの名無しさん
20/06/10 08:13:57 V+CQutVh.net
C++ではexitをD組にして欲しい
274:デフォルトの名無しさん
20/06/10 12:31:11 BPKUZfdj.net
>>268 通知は欲しいかな。
黙って動作が続くくよりは terminate() のほうがマシだとも思うし。汎用部品ならなおさら。
破棄失敗する可能性のあるリソースの RAII wrapper にはエラー通知できる
close() なりの破棄操作を別に用意しておけという話で済むと思う。
275:
20/06/10 21:10:53.11 OTs8rmHM.net
>>271
通知って簡単にいいますけれども、その例えば fclose() 失敗の通知をどこに送り、そして送った先では何をするのですか?
通知をもらって何か手を打てるのですか?
汎用部品/ライブラリの作法ですか
理解はできますが、しかし、何もできないのなら、あるいは何もできないことがわかっているのなら、特段の失着にはみえませんね…
276:デフォルトの名無しさん
20/06/10 21:56:31.91 yfneRFZn.net
大事なデータを保存したファイルのfclose()が失敗したらどうするかって?
場所変えて保存を試みるに決まってるだろ
それくらいしないプログラムは売り物にならないぞ
277:デフォルトの名無しさん
20/06/10 22:20:00 yQDU6thd.net
そもそも仕様で指定があるならそのように書くだけなんじゃ
278:デフォルトの名無しさん
20/06/11 00:27:51 flOLYJrB.net
>>272
たとえばコンソールアプリなら標準エラーに情報を出したうえで終了コードに反映して、
コマンドが失敗したのを見たユーザーが何をするか考えるっていうのはごく当たり前のことでしょ。
たとえばストレージ容量が足りないとして失敗したなら容量を確保して再実行すればいい。
fclose() の戻り値を捨ててるプログラムは現実としてたぶん多いんだけど、
そんなソフトがたとえばサーバー内でストレージ容量不足を数か月にわたって闇に葬り続け、
何かおかしいと気付いたサーバー管理者が自動スクリプトを緻密にトレースした結果、
保存されているはずの情報がもはやどこにも存在しないと気付いた時の怒り憎しみ悲しみを想像されたい。
少なくとも成功したと誤解しないのが重要。
279:デフォルトの名無しさん
20/06/11 06:18:34 m7gaY4Qp.net
そんな状況じゃopenも失敗してるだろうな
280:デフォルトの名無しさん
20/06/11 09:58:48.19 Th6rh/3U.net
>>275
実はそれがRAIIの限界なんだよ。
ちゃんと明示的に fclose() してその戻り値をチェックするのが一番安全。
例外安全性のためにRAIIを使うべきという人が居るけど、それで勝手に
デストラクタ内でfclose()して容量不足やディスクエラーで書き込み失敗した時には、
多くの場合、対処に困る。
でも、例外安全のためにはそうせざるを得ないかも知れない。
ということは、そもそも論になり、例外の throw、catch機構自体が安全に扱うのが
難しいという結論に至り、議論百出する。
281:デフォルトの名無しさん
20/06/11 10:29:20 flOLYJrB.net
>>277
それは飛躍しすぎかな。
破棄が失敗する可能性のあるリソースの RAII ラッパーが破棄操作も提供すれば済む話でしょ。
std::fstream の close() みたいに。
282:デフォルトの名無しさん
20/06/11 10:38:30.62 3eiGl155.net
上から目線なくせに脇が甘いな
283:はちみつ餃子
20/06/11 11:08:58.38 7wv0rqaB.net
デストラクタ内でエラーが発生する可能性があってそれに対処が必要なら
例外の送出とか言ってないでデストラクタ内で対処してしまえよ。
汎用的な部品にし難いのはしゃーないやろ。
実際に汎用的ではないんだから。
284:デフォルトの名無しさん
20/06/11 11:47:39.02 DcPEy/qZ.net
おまいら (f)printf() の戻り値もちゃんと毎回観てるか?
285:デフォルトの名無しさん
20/06/11 11:54:46.87 Th6rh/3U.net
>>280
そうじゃなくて、何らかの別の事情で例外が送出された時に、fclose()し忘れを
防ぐためにRAIIのテクニックを使う場合の話をしてる。
286:デフォルトの名無しさん
20/06/11 11:56:16.72 Th6rh/3U.net
>>278
fstreamであろうがなんであろうが、GUIアプリに置いて、デストラクタ内で失敗した
時にユーザーに失敗したことを知らせるのは結構難しいぞ。
287:デフォルトの名無しさん
20/06/11 12:17:49 3eiGl155.net
そんなに難しいか?
深刻な事態が疑われるならシステムモーダルダイアログなり何なりすることあるだろ
あくまでOSではなくアプリとして事後条件が保証できない場合はterminateを呼び出して
OSに事故としての扱いをさせるのが「難しい」のは思いつかないだけじゃねえだろな
プログラミング以外の仕事でも事故はまず報連相
1人で握りつぶそうとするのは学生気分が抜けてないやつのすることだ
288:デフォルトの名無しさん
20/06/11 12:19:04 flOLYJrB.net
>>283
そりゃ難しいだろうな。
通知が要るならデストラクタ内で失敗させないように破棄操作を提供すれば済むだろうという話をしたつもり。
それで済まないケースを想定してるなら、どんなのか教えて。
289:デフォルトの名無しさん
20/06/11 12:21:07 flOLYJrB.net
>>284 そっか GUI ならダイアログ使えるから、通知するだけなら簡単だね。
290:デフォルトの名無しさん
20/06/11 12:22:43 Th6rh/3U.net
>>285
>通知が要るならデストラクタ内で失敗させないように破棄操作を提供すれば済むだろうという話をしたつもり。
意味が分からないので、説明を。
291:デフォルトの名無しさん
20/06/11 12:29:07.29 Th6rh/3U.net
>>284
Exceptionをthrowした時の自動フォローアップとしてRAIIのデストラクタが呼び出される。
それが呼び出されるのは原則的にどこかでかは余り仮定できない。
ということは、非常に変なタイミングで fclose()に失敗することがある。
メッセージボックスを出すと、そこでイベントに対するメッセージループが形成されるので、
タイマーイベントのハンドラのOnTimer()などが起動してしまうこともある。
OnTimer()を、Exceptionがthrowされた状態で実行してよいかどうかは注意を要する事だ。
また、アプリの初期化処理の InitInstance()や終了処理のExitInstance()の中で、RAIIの
デストラクタが呼び出されてしまう場合もあるかも知れず、その中でメッセージボックスを
出すと思わぬ問題が生じるかもしれない。
生じないかも知れないが。
ただ、Exceptionがthrowされたということは何か異常が生じているということで、
それがたまたまファイルに関するものであったとしたら、二重三重に、ファイル関連で
エラーが生じてしまい、何か危険な状態に陥ってしまう可能性も有るかも知れない。
そういう微妙な配慮が必要となる。
292:デフォルトの名無しさん
20/06/11 12:33:42.17 Th6rh/3U.net
>>288
もっといえば、Exceptionのthrowはどこで起きるかは仮定しにくいものなので、
何らかのダイアログを出すための初期化処理の中で生じることも有るかも知れない。
そういう場合にたまたま、関数の呼びだし元へ どんどん Exception の Unwinding
が生じて、RAIIのデストラクタで fclose()が呼び出される可能性も有るかも知れない。
そうなって、さらに、その fclose()がエラー終了する場合がある。
ダイアログの生成に失敗したタイミングで、エラーメッセージの表示のために、
メッセージボックスのダイアログを出すことになれば、もしかしたらかなり危険な
バグを含むことになってしまうかも知れない。
293:デフォルトの名無しさん
20/06/11 12:49:26.16 flOLYJrB.net
>>287-289
ごめん、別の例外でスタック巻き戻し中の fclose() 失敗は無視でもいい想定だった。
元の例外が通知されればそれでいいだろうと。
破棄操作を提供すれば済むっていうのは、たとえば fstream について
正常フローから close() 呼び出せば fclose() の失敗は普通に処理できるっていう意味。
エラー発生後の後処理でのエラーについてはもはや例外処理機構とか RAII とか関係なく
エラー処理一般で難しさは変わらないのでは?
294:デフォルトの名無しさん
20/06/11 13:14:41.21 4Jo+eUkD.net
>>288
何を言い出すかと思ったらシングルスレッドを
気分だけマルチっぽく見せかけてるだけなやつの話か
295:デフォルトの名無しさん
20/06/11 17:56:16 +WuQ8P1K.net
そんなに大事なデータならverifyするだろ
296:デフォルトの名無しさん
20/06/13 16:05:30.52 ifM7/RIh.net
>>272
>知って簡単にいいますけれども、その例えば fclose() 失敗の通知をどこに送り、そして送った先では何をするのですか?
最終的にはユーザーに通知する
>通知をもらって何か手を打てるのですか?
ユーザーが通知に従い手を打てる
>>280
デストラクタ内での例外を送出したら即アプリが死ぬハズ
コアを吐いてくれたら通知にあたる情報が取り出せるかもしれないが美しくない
>>288
異常の内容をユーザーに通知することを目的とするなら
>エラーの通知先オブジェクトへのポインタをCMyXは持つ(>>253)
で事足りる
メッセージループは、通知先オブジェクトが1個だけもちさえすればユーザーへの通知の役目を果たせる
CMyXのようなケースは通知先オブジェクトを保持するオブジェクトからFactoryMethodパターンでインスタンス化
するのがいかにもOOP的で個人的には好み(CMyXのインスタンス化のときに通知先を確実に渡せる