C++相談室 part145

■ このスレッドは過去ログ倉庫に格納されています
1デフォルトの名無しさん
垢版 |
2019/09/13(金) 17:13:24.60ID:/ygW08Jq
C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
IDE (VC++など)などの使い方の質問はその開発環境のスレにお願いします。

前スレ
C++相談室 part144
https://mevius.5ch.net/test/read.cgi/tech/1563769115/

このスレもよろしくね。
【初心者歓迎】C/C++室 Ver.105【環境依存OK】
https://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/ (日本語)

----- テンプレ ここまで -----
2019/10/24(木) 13:57:45.03ID:SfEmAS3k
林檎だってcheckマクロでBoostに大迷惑かけてるしお互い様
2019/10/24(木) 17:59:23.36ID:0EVcBOG9
>>582
そこは
ヘッダだけにな
と言ってやるところだろ
2019/10/24(木) 18:05:45.17ID:pgieaG2c
ヘッダ「嫌ならincludeするな」
2019/10/24(木) 19:57:40.06ID:WiWlXxwu
このスレはみんなWindows嫌いなのかな
2019/10/24(木) 20:17:56.94ID:TRYJth0S
んなわけない
2019/10/24(木) 21:28:21.53ID:hxYU3Lux
たしかmaxとかもマクロ定義されてたよね
初心者のころはどハマリして殺意がわいたわ
2019/10/24(木) 21:49:18.24ID:omM/Gkq5
いまはIDEが色変えてくれるからすぐわかるから別にいいけどね
2019/10/24(木) 23:20:19.58ID:M5uvwdA8
マクロがあればなんでもできる
2019/10/24(木) 23:40:29.47ID:PIyGP0m1
最近ちょいちょい思うことだが、ある言語のここがどうであーだこうだと議論する場合
テキストエディタでコーディング作業してる連中と IDE でコーディング作業してる連中では
わりと大きな認識の違いがあることが多い
2019/10/24(木) 23:44:34.75ID:8Fri6DgZ
windows.hのマクロ回りでトラブル起こしているのは、殆んどvisual studio使用者だと思うのだが
2019/10/25(金) 00:24:04.41ID:AZBzSxe6
認識の違いはコンパイラによるものであってコードエディタは関係ない。
2019/10/25(金) 00:39:26.61ID:ghRRxqDU
モジュールでマクロとか気にしなくて良くなる(なるといいなぁ...)
2019/10/25(金) 07:52:28.01ID:51G3P59H
コンパイラ変えてもマクロは変わらんでしょ
せいぜいエラーメッセージ変わるぐらいじゃ
2019/10/25(金) 09:14:30.39ID:AZBzSxe6
>>595
何言ってるのか意味がわかりにくいエラーメッセージを吐くのはコンパイラでしょ。
2019/10/25(金) 12:19:38.16ID:51G3P59H
マクロは影響範囲わからんからなんとも

vcでマクロがテンプレートに影響したらマジでわからん
clangはテンプレートのエラーメッセージわかりやすいとかみたな
2019/10/25(金) 12:45:17.61ID:yKAgzXLG
>>593
お前はまず日本語を正しく認識できるようになれよ…
>>591は連中(=人間)の認識の話な
599デフォルトの名無しさん
垢版 |
2019/10/25(金) 17:33:51.00ID:AZBzSxe6
初心者であればあるほど親切なエラーメッセージが必要なのだけど、VCのエラーメッセージはgccに比べて不親切な印象がある。
STL関連のエラーメッセージは、わかりにくい代表格。かたやgccはprintf系の書式ミスを指摘してくれるなど初心者に優しい。
600デフォルトの名無しさん
垢版 |
2019/10/25(金) 18:03:22.82ID:AZBzSxe6
C#が使いやすいと思っている人は、Visual Studioの入力補完に救われていることに気づいていない。
Visual Studioがなければヘッダーファイル相当のgrep検索もままならない不便な言語であると感じるだろう。
2019/10/25(金) 18:50:41.74ID:StYWqeWG
VS込みでいいじゃん
どうせC#なんて大半がWindows向けなんだしVS使える環境で開発してるでしょ

って変なこと言うと思ったらADSLか
2019/10/25(金) 19:00:26.80ID:r/2esNbS
referencesource.microsoft.comみたいなありがたいものがあるのに
2019/10/25(金) 19:58:41.60ID:q2iK2L4t
基本的には MSDN こそ C++ である。
2019/10/26(土) 00:56:44.62ID:7AoWPXY8
class A{};

namespace N
{
class B{
friend class A;
int i;
};

class A{
A(){b.i = 0;}
B b;
};
};

これをコンパイルできるようにするにはどうすればいいですか?

・クラスAを名前空間Nの下に書く
・名前空間NのクラスAを別の名前にする
・最初のクラスAを別の名前にする

これ以外でできますか?
2019/10/26(土) 00:59:53.57ID:SyjizfQh
全部消す
2019/10/26(土) 01:35:09.91ID:dcsgYCXg
>>604
「コンパイルできるようにする」
というだけであれば、何も修正しない元のままでもコンパイルできるはずだし、
最初の class A {} の行をコメントアウトする、消す。
Nの中のAを消す、namespace N {・・・} の部分を全部消す、
などなどいくらでも有りえる。
2019/10/26(土) 06:20:26.55ID:3CUGZWDU
BのfriendをN::AにしたいってことであればNとBの間にclass A;とAの宣言を入れる
これ以上のエスパーは無理
2019/10/26(土) 08:16:08.08ID:kGqH5EJJ
>>604
g++だと、現状のままでok
vs2019は、friend宣言の対象が::AになっていてC2248
::Aをコメントアウトするとok

正しいのはg++
N4713 6.4.1. Unqualified name lookup (7.4)
Note: When looking for a prior declaration of a class or function
introduced by a friend declaration, scopes outside of the innermost
enclosing namespace scope are not considered; see 10.3.1.2.
2019/10/26(土) 21:50:06.24ID:JNlbd3QN
投稿テスト

N3337 3.4.1 Unqualified name lookup
Note: When looking for a prior declaration of a class or function
introduced by a friend declaration, scopes outside of the innermost
enclosing namespace scope are not considered; see 7.3.1.2.
2019/10/26(土) 22:03:59.61ID:JNlbd3QN
vs2019で::Aをコメントアウトするとokの意味がわからんorz
2019/10/27(日) 08:17:56.25ID:/F19lavA
試してないが、理論上はこれでいけるはず :
namespace N
{
class A;
class B{
int i;
friend class A;
};

class A{
B b;
A(){b.i = 0;}
};
};
2019/10/27(日) 08:27:09.91ID:C3DsRDjK
N::Aを前方宣言するなら、宣言を名前空間Nの中に入れるかN::Aで宣言する必要があるってのはC++の規約通りじゃないのか?
>>608が意味わからん
2019/10/27(日) 09:08:16.09ID:M7FyKfzv
friend宣言は、当該宣言を含むクラスが属するスコープを対象とし
なおかつ、対象スコープに識別子を導入しない

class G
{
friend class A; //::A
};

namespace H
{
class I
{
friend class A; //H::A
};
}
2019/10/27(日) 12:21:23.69ID:C3DsRDjK
>>604はfriend宣言ではなく前方宣言の問題なんだが?
2019/10/27(日) 14:03:45.40ID:M7FyKfzv
いや前方宣言は関係ない
「もし」::Aがあったら、H::Aがあったら
と言っているだけのものだ
2019/10/27(日) 14:25:39.88ID:vcUKQgsd
>>614
前方参照をfriendがどう解釈するかの問題だろ
2019/10/27(日) 15:28:12.27ID:itfBjV2c
>>616なのは明白だが
>>604のコードのどこにコメントアウトすべき::Aがあるのかわからん…

ひょっとして、>>604が禁じていないのを良いことに、
最も外側のclass A{};を丸ごとコメントアウトしようとしている?
2019/10/27(日) 15:53:16.22ID:ho9vIROt
>>617
???
>>608はVisual Studio 2019(2017でも同じだったが)の話だと言うことは理解できてるか?
2019/10/27(日) 15:56:22.52ID:M7FyKfzv
>>617
そのとおりだが?

//class A{};

namespace N
{
class B{
friend class A;
int i;
};

class A{
A(){b.i = 0;}
B b;
};
};

friend宣言が識別子を導入したり
関係ないはずのグローバルに干渉するなど
vcはfriendにクセがある
2019/10/27(日) 16:07:13.81ID:6193c9It
規格的にはどうなるのが正しいの?
むしろ、もとの話がどうしたいのかに依る気がしないでもない
2019/10/27(日) 16:13:20.11ID:rrcAfXPk
>>620
規格の話は>>608じゃねーの?
コンパイルできるようにするにはg++にするかVisual Studioなら>>619みたいにするってことでしょ
それ以外なら環境を提示してねってことかと
2019/10/27(日) 16:22:22.30ID:itfBjV2c
>Visual Studioなら>>619みたいにするってことでしょ
https://festy.jp/wp-content/uploads/festy/2015/12/25/06/51/40/917/1448191295053.jpg

>>604
>・最初のクラスAを別の名前にする
と何が違うんだそれ
2019/10/27(日) 16:55:17.47ID:rrcAfXPk
>>622
一緒だよ
だからそれができないならg++(とか他のちゃんと規格準拠して処理系)にしろって書いてあるだ
まあVisual Studioが規格準拠するのを待つとかMSにねじ込むか金払って対応してもらうとかでもいいけどw
2019/10/27(日) 20:50:09.77ID:5FCyBaq0
トンチンカンな質問かもしれませんが許して。

<Base>のコンテナを巡回しながら
Base派生の多態性を引数で実現、みたいなことがやりたいのです。
https://ideone.com/PA26HG

これのManager::update()が、このままだと当然
func(shared_ptr<Base>,shared_ptr<Base>)を呼ぼうとしてしまう訳ですが

宣言してあるfunc(A,A)とかfunc(A,B)とかfunc(B,B)とかが
呼ばれるようにするにはどうしたらいいですかね?
あるいは、ガラっとコード変わってもだいたい似たようなことを実現するとしたら
どう書きますか?
2019/10/27(日) 20:52:12.38ID:oi2VB0wA
シェアポの配列を作って添え字で切り替え。
2019/10/27(日) 20:54:15.22ID:oi2VB0wA
あ、すまん。誤読していた。
>>宣言してあるfunc(A,A)とかfunc(A,B)とかfunc(B,B)とか
多態やってる意味を潰しに来てないか?
2019/10/27(日) 20:54:19.69ID:irXhIBVc
>>624
funcを仮想化すれば?
2019/10/27(日) 20:59:49.33ID:cNZwDfUU
もしくはfuncでは仮想化された関数しか使わないとか。
2019/10/27(日) 21:09:28.45ID:aWGByvYb
>>624
visitorパターン
630642
垢版 |
2019/10/27(日) 21:09:54.33ID:5FCyBaq0
>>627
func(Base,Base)だけをvirtualってこと…ですよね?
え、こういうときにもvirtualて使えるの?と思って試したけどダメですね。

>>628
もうちょっと考えてみますけどたぶん難しいです
631624
垢版 |
2019/10/27(日) 21:14:40.36ID:5FCyBaq0
名前欄間違えてた…

>>629
あー…それかも
なんとなく知ってるだけで
まだ実装したことはないですが

それ正解かもしれません
調べつつやってみます
2019/10/27(日) 21:34:36.36ID:4WtkkchW
>>624
愚直に dynamic_cast で N*N 分岐からはじめたら?
2019/10/27(日) 22:12:39.30ID:5au4GxkL
2引数ならdouble dispatchとか
2019/10/27(日) 22:14:23.71ID:SYtHJPpD
派生クラスの種類が決まっているなら
variantに置き換えたらvisit使えるから簡単
2019/10/28(月) 05:15:43.29ID:VJWcm+Z+
>>624
こうゆうことやのうて?
https://ideone.com/BoNrnP
636デフォルトの名無しさん
垢版 |
2019/10/29(火) 01:15:36.46ID:Vnr+WSpj
C++でCOM扱うの苦痛すぎる
何が正攻法なのかさっぱりわからん
2019/10/29(火) 01:32:18.86ID:CdNgVa0z
>>636
ATL
CComPtr
638デフォルトの名無しさん
垢版 |
2019/10/29(火) 01:41:40.05ID:Vnr+WSpj
別にCOMは作るんじゃないんだよ。
参照するだけなんだよ。
それでもATLなんーーーーーーーーー?
639デフォルトの名無しさん
垢版 |
2019/10/29(火) 01:43:16.61ID:Vnr+WSpj
そもそも文字コードどうなってるんやーーーー
コマンドプロンプトに出す時、どうするんやーー
現在のchcpの設定に従って変換線といかんのカーーーーーー
2019/10/29(火) 02:28:13.51ID:OOQqvLIR
変換なんてWideCharToMultiByte使って一つ変換関数作ってその関数を使い回せばいいやん。
2019/10/29(火) 02:42:32.11ID:/DWax9vx
WriteConsoleW
642デフォルトの名無しさん
垢版 |
2019/10/29(火) 04:01:15.69ID:ymnLB/52
>>640
Unicode文字列(絵文字とか)が文字化けするんだよー!
フォントの問題でないことは確認済み
643デフォルトの名無しさん
垢版 |
2019/10/29(火) 04:07:41.50ID:ymnLB/52
例えばググって見つけた、こことか
http://www.t-net.ne.jp/~cyfis/win_api/sdk/WideCharToMultiByte.html

wchar_t を const wchar_t にするのはまあいいとして、
日本語はOKだけど絵文字とか化けるじゃねーか
わーけわかねなんdfっrね;jk
644デフォルトの名無しさん
垢版 |
2019/10/29(火) 04:13:15.89ID:ymnLB/52
ん?WideCharToMultiByteってShiftJISに戻すやつじゃねーのか?
俺はUnicode文字すべてを表示したいだけだぞ
2019/10/29(火) 04:20:56.50ID:xS90z6YC
chcpくらい使えよ
2019/10/29(火) 04:26:03.90ID:/DWax9vx
windowsのコマンドプロンプトはまだ絵文字とかに対応してないよ
2019/10/29(火) 04:29:31.79ID:YQKoC2Uo
>>646
全てではないだろうけど対応してる。

↑文字化けしそうだけど、横向きのハートとか
❤ とか
2019/10/29(火) 04:29:44.12ID:YQKoC2Uo
お、文字化けしなかったw
649デフォルトの名無しさん
垢版 |
2019/10/29(火) 04:30:10.10ID:YQKoC2Uo
?????
Jane経由だとだめだろうな
650デフォルトの名無しさん
垢版 |
2019/10/29(火) 04:31:42.98ID:YQKoC2Uo
>>645
chcp 65001にしてもムダだったぞ
2019/10/29(火) 04:54:41.95ID:pnjVF+Pb
コマンドプロンプトよりJaneは早く絵文字に対応しろ
2019/10/29(火) 05:06:04.44ID:xS90z6YC
>>650
それutf8じゃねーか
653デフォルトの名無しさん
垢版 |
2019/10/29(火) 05:14:54.35ID:YQKoC2Uo
>>652
ぐぐってからいえwww
654デフォルトの名無しさん
垢版 |
2019/10/29(火) 05:19:50.17ID:YQKoC2Uo
なんでコードページ932なのに、NSimSunにすると
日本語以外もちゃんと表示できるのかわからない
2019/10/29(火) 05:26:40.69ID:xS90z6YC
wcharがutf8なのか?あほか?
656デフォルトの名無しさん
垢版 |
2019/10/29(火) 05:36:55.26ID:YQKoC2Uo
Visual StudioのソースコードのデフォルトはBOM付きUTF8なんだな
657デフォルトの名無しさん
垢版 |
2019/10/29(火) 06:38:53.94ID:d5obkYRE
Windows依存の話は、以下すれでどうぞ。

Win32API質問箱 Build125
https://mevius.5ch.net/test/read.cgi/tech/1551247748/
2019/10/29(火) 12:08:17.89ID:HlsBbRfa
自分の理解と違ってたので教えてください。

class hoge{
hoge(){}
hoge(const hoge& h){}
~hoge(){}
}

hoge func(){
hoge h;
return h;
}

main(){

hoge h = func();

}


この時、引数なしコンストラクタとコピーコンストラクタ、デストラクタが2回呼ばれると理解してたんだけど、実際動かすとコンストラクタとデストラクタが1回づつしか呼ばれない。
理由ってなんですか?

ちなみにgccで、c++03、c++11でも同様の結果でした。
2019/10/29(火) 12:09:55.91ID:0JV7MfqT
>>658

RVO でググって
2019/10/29(火) 12:10:21.23ID:gvGgQxyJ
最適化で消された
2019/10/29(火) 12:14:30.49ID:HlsBbRfa
>>659
まさにピンポイントでした。
ありがとうございます。
662デフォルトの名無しさん
垢版 |
2019/10/29(火) 13:58:53.43ID:cpD/FVFn
>>636
node.js
2019/10/29(火) 13:59:57.20ID:0JV7MfqT
>>636
マイクロソフトのコンパイラならまあまあ補助があったりするでしょ。
それでも面倒くさいことにかわりないけど。
2019/10/29(火) 15:55:18.54ID:VnX4qZP9
失礼します。テストです:
ハート:❤
横向きハート:❥
2019/10/29(火) 16:08:16.15ID:0JV7MfqT
>>664
失礼な奴だな!
2019/10/29(火) 18:43:54.18ID:NclFvQSb
>>663
補助なんてあったっけ?
まあ俺の知識はもう5年以上前の知識だから最近はちょっとはマシになったのかな
667デフォルトの名無しさん
垢版 |
2019/10/29(火) 21:55:11.67ID:daQRKG1l
typedef const struct {
int i;
int j;
} X;

X arr[2] = {
{1,3},
{2,4}
};

int main() {
X *ptr = arr;
printf("%d %d %d <- always zero", ptr->i, (ptr+1)->i, (ptr-1)->i);
return 0;
}

グローバル const struct の配列のアドレスを上に行ったら、常に0が入ってるんだけど、
これは、どのハードウェアでもこうなると仕様と決まってるの?
2019/10/29(火) 22:07:48.92ID:VnX4qZP9
>>667
決まってない。
範囲外のアクセスなので、本来は絶対にやってはいけない。
読むだけでも不法例外が起きてしまう可能性もあるが、
書くのはもっとダメ。
たまたま、コンパイラシステムが何らかの目的で使っている
グローバル変数が arr 配列の直前にい配置されていて、
それが0になっているか、padding領域がたまたまそこにある
だけだと考えられる。
2019/10/29(火) 23:33:23.00ID:B0gwdLKJ
.bssは0初期化されてる
2019/10/30(水) 04:47:43.23ID:oMdYt0Tq
オブジェクトがスタックに作られてるかヒープに作られてるかってどうやって調べるの

具体的にはboostのmulti_arrayがどっちに作られてるか知りたい
671デフォルトの名無しさん
垢版 |
2019/10/30(水) 06:54:34.02ID:2wpdugOW
>>668
そりゃそうか。0で埋まってりゃコードが少し短くなって助かるんだが、まあやめとこう。
2019/10/30(水) 07:31:59.85ID:yREk150+
>>670
アドレスでわかる
正しくはリンカからロケーションを取得だが
簡易的には自動変数のアドレスと上の方の桁が同じかどうかでも見当はつく
2019/10/30(水) 09:19:14.69ID:C/RG5q83
>>670
アドレスでも分かるが、それはスタック領域のアドレス範囲をマップファイル
やEXEヘッダなどから読み解かないといけないので、boostのソースを読むのが
一番楽。

もう一つは、
1. auto local変数でint a; printf( "%08X", &a );としたもの
2. global 変数で、int g_b; printf( "%08X", &g_b );としたもの
3.ヒープの先頭アドレスを調べるため、int *p_c = new int[16];
 printf( "%08X", p_c );としたもの

で表示されたアドレスと boost の multi_arrayのアドレスとを比較して、
上位アドレスが近いかどうかで判別できる。1,2,3のそれぞれはまとまった
領域のアドレスを使っているので、推定ではなく断定できる。
2019/10/30(水) 09:33:17.69ID:scNMtFri
どう考えてもヒープだろ
2019/10/30(水) 09:45:24.54ID:vMK+Q7lg
>>670
ローカルスコープだけがスタック。
newしたものはヒープ。
2019/10/30(水) 11:38:54.67ID:M6J6raPE
コンテナの場合はスタックに置いたつもりでも、コンテナがデータ部分を内部でnewするとかそういう話だろ
2019/10/30(水) 12:07:14.45ID:qu4eF7c5
>>667-668
仕様上は配列の範囲外を指すポインタを作るのさえも未定義。
たとえアクセスしなくても。
なので、 ptr-1 という式の時点で未定義動作になる。

ただし、アクセスしないなら配列の最後の要素より一個うしろを指すポインタを作るのは許される。
つまりこの例で言えば ptr+2 や &ptr[2] は有りだけど ptr[2] は駄目。

&ptr[2] は ptr[2] に対して & を付けているので一見すると途中で ptr[2] を評価しているように見えるけど、
・ ptr[2] は (*(ptr+2)) の構文糖である
・ * の結果に & を適用している場合には * も & も評価されず、両方とも取り除いたのと同じことになる
というルールの合わせ技によって &ptr[2] は ptr+2 と同じ意味になる。

ちなみに、配列ではないオブジェクトは要素が一個の配列と同じレイアウトを持つことは保証される。
2019/10/30(水) 12:14:10.66ID:pPHw66rS
>>677
&*p を p とみなす特別ルールは C の規格にあるけど C++ には無かったりする。
もう10年以上審議中。 https://wg21.cmeerw.net/cwg/issue232
2019/10/30(水) 12:21:16.92ID:C/RG5q83
>>677
>ちなみに、配列ではないオブジェクトは要素が一個の配列と同じレイアウトを持つこと>は保証される。

しかも、TYPE arr[N] の場合、それぞれの要素間隔であるところの
&arr[k] と &arr[k + 1] の差は、厳密に sizeof(TYPE)に一致する。
struct TXxx { BYTE a[3] }; のように中途半端な内容を持っている場合、
標準的には、sizeof(TXxx)は最後のpaddingまで含めた4になる。

その結果、古くからCの仕様書に載っている通り、
 &arr[k] = (TYPE *)(((BYTE *)arr) + sizeof(TYPE) * k)
の式が常に厳密に成り立つことが保証される。
2019/10/30(水) 12:25:41.94ID:C/RG5q83
>>678
operator&(), operator*() をユーザーが定義した場合には、それに従うが、
定義しなかった場合、&*pX == pX が どんなポインタ pX についても
成り立つことは保証されるはず。
2019/10/30(水) 13:28:14.72ID:JDSjHFuf
>>670
一般的なPC環境なら、
適当に用意した別の関数を呼び出して(multi_arrayのインスタンスがまだ有効で、インスタンス生成したスレッドと同一スレッドからなら、どこから呼び出してもよい)、
その関数のローカル変数のアドレスよりも&multi_array[0]の値のほうが大きければ、multi_arrayのデータ領域はスタックに確保されたと判断できるのでは
2019/10/30(水) 13:38:23.28ID:C/RG5q83
>>681
自分も最初、同じような勘違いをしていたが、
シングルスレッドの場合に限定すれば、
スタックの構造からすれば、最初に確保したローカル変数のアドレスが、
そのごろのローカル変数のアドレスよりも必ず大きい。
そして、ヒープから確保したオブジェクトのアドレスは、必ずそれらよりも大きい。
なので、後から別の関数を呼び出す必要はない。
main()関数の中で最初に定義したローカル変数のアドレスが分かればそれで十分。
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

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