前スレ
C++相談室 part160
https://mevius.5ch.net/test/read.cgi/tech/1649979572/
C++相談室 part161
レス数が950を超えています。1000を超えると書き込みができなくなります。
2022/05/21(土) 21:23:29.59ID:kYXfaM+5
893デフォルトの名無しさん
2022/10/19(水) 01:49:23.30ID:ACk8fEyB >>892
>y のデストラクタが呼ばれるのは y のスコープの終わりであることは保証される。
なるほど。
でも結局、
T x;
T y;
x=move(y); //(1)
と書くと、(1) の部分で、
x.operator=(yを右辺値化したもの); //(2)
が行なわれて、
yの生存期間が終わる地点で、yのデストラクタであるところの y.~T() が呼び出される、
ということになることは間違いなのですね。
つまり、(2)が行なわれたら yはもはやmove後なのだから、yのデストラクタ呼び出しが
省略されるということではなく、yのデストラクタは絶対に必ず呼び出されるわけですね。
だから、T::operator=(T &&a) は、T::operator=(T &&a)の処理が終わった後に、
コンパイラによって yのデストラクタが呼び出されることを前提に処理しなければならない、
ということになる。
>y のデストラクタが呼ばれるのは y のスコープの終わりであることは保証される。
なるほど。
でも結局、
T x;
T y;
x=move(y); //(1)
と書くと、(1) の部分で、
x.operator=(yを右辺値化したもの); //(2)
が行なわれて、
yの生存期間が終わる地点で、yのデストラクタであるところの y.~T() が呼び出される、
ということになることは間違いなのですね。
つまり、(2)が行なわれたら yはもはやmove後なのだから、yのデストラクタ呼び出しが
省略されるということではなく、yのデストラクタは絶対に必ず呼び出されるわけですね。
だから、T::operator=(T &&a) は、T::operator=(T &&a)の処理が終わった後に、
コンパイラによって yのデストラクタが呼び出されることを前提に処理しなければならない、
ということになる。
894デフォルトの名無しさん
2022/10/19(水) 02:44:50.18ID:ACk8fEyB895はちみつ餃子 ◆8X2XSCHEME
2022/10/19(水) 04:13:29.85ID:CfflWiLk >>893
そう。 move assignment operator と呼ばれてはいるが
右辺値であるということがわかる以上の違いはない。
ムーブは寿命を左右せず、内容の状態がどうなるかは実装次第。
具体例で言えば std::unique_ptr はムーブ後には空になる (メンバ関数 get は空ポインタを返す) ことが保証されるが、
std::string は (新たな内容が与えられるまでは) 未規定の値になる。
右辺値参照が導入されたのは C++11 からで、
デストラクタのタイミングが変わってしまうような変更を入れられるわけがない。
そう。 move assignment operator と呼ばれてはいるが
右辺値であるということがわかる以上の違いはない。
ムーブは寿命を左右せず、内容の状態がどうなるかは実装次第。
具体例で言えば std::unique_ptr はムーブ後には空になる (メンバ関数 get は空ポインタを返す) ことが保証されるが、
std::string は (新たな内容が与えられるまでは) 未規定の値になる。
右辺値参照が導入されたのは C++11 からで、
デストラクタのタイミングが変わってしまうような変更を入れられるわけがない。
896デフォルトの名無しさん
2022/10/19(水) 23:39:12.93ID:8y/Qrf1S C++で15年ぶりにプログラミングをすることになったんだけど、
C++11以降のことは何も知らないのでまずは復習もかねて勉強することにした
今でもbjarneの本が初心者にとって一番のテキストなの?
それとももっとシンプルで分かりやすい本が出てるのでしょうか?
C++11以降のことは何も知らないのでまずは復習もかねて勉強することにした
今でもbjarneの本が初心者にとって一番のテキストなの?
それとももっとシンプルで分かりやすい本が出てるのでしょうか?
897デフォルトの名無しさん
2022/10/19(水) 23:45:19.38ID:w93eWlNE >>895
今考えてみれば、条件分岐の中だけでmove代入される場合も有るからかも知れませんね。
今考えてみれば、条件分岐の中だけでmove代入される場合も有るからかも知れませんね。
898デフォルトの名無しさん
2022/10/20(木) 03:01:20.64ID:3bh5ldea 昔のC++知ってるならとりあえずEffective Modern C++.でいいんじゃないの
899デフォルトの名無しさん
2022/10/20(木) 06:31:14.16ID:pIDfWPXL >>896
本は読者との相性があるから一概には言えないが
俺的にはやっぱ禿の本だな
変に手加減してこないところに安心感がある
ただし「プログラミング言語C++第4版」は
あくまでC++11で、C++14以後には触れていないので
構造化バインディングやコンセプトは学べない
俺はこのあたりはここやQiitaできっかけだけ拾って
あとは規格票やhttps://cpprefjp.github.io/で憶えてる
本は読者との相性があるから一概には言えないが
俺的にはやっぱ禿の本だな
変に手加減してこないところに安心感がある
ただし「プログラミング言語C++第4版」は
あくまでC++11で、C++14以後には触れていないので
構造化バインディングやコンセプトは学べない
俺はこのあたりはここやQiitaできっかけだけ拾って
あとは規格票やhttps://cpprefjp.github.io/で憶えてる
900はちみつ餃子 ◆8X2XSCHEME
2022/10/20(木) 13:52:31.60ID:w/WeLGfC901デフォルトの名無しさん
2022/10/20(木) 17:53:11.99ID:ieIEHaM0 ビャーネの本、章の構成がよく分からんのだけど何がどうしてああなったん
902デフォルトの名無しさん
2022/10/20(木) 18:26:02.35ID:zGrDbuOl 昔は、ロベールが鉄板だった
903デフォルトの名無しさん
2022/10/20(木) 18:47:34.03ID:sgmqUmRA bj氏の本のダブルディスパッチの部分と、次のVisitorの部分、
どっちもよく分からなかった。
まず、前者のShape&の引数が何のためにあって、どういう役割を果たしているか
誰か教えて。
どっちもよく分からなかった。
まず、前者のShape&の引数が何のためにあって、どういう役割を果たしているか
誰か教えて。
904デフォルトの名無しさん
2022/10/20(木) 18:49:51.30ID:sgmqUmRA >>903
プログラミング言語C++第四版 日本語版の
p.653, 22.3.1 ダブルディスパッチの辺りから。
bool intersect(const Shape&);
関数が無くてもこの例だと動作すると思うんだけど、
なんなん?
プログラミング言語C++第四版 日本語版の
p.653, 22.3.1 ダブルディスパッチの辺りから。
bool intersect(const Shape&);
関数が無くてもこの例だと動作すると思うんだけど、
なんなん?
905デフォルトの名無しさん
2022/10/20(木) 19:41:09.72ID:tMcnfqkZ ダブルディスパッチは勘違いしやすいよね
906はちみつ餃子 ◆8X2XSCHEME
2022/10/20(木) 23:26:04.47ID:w/WeLGfC 今でも「ロベールの C++ 入門講座」で学ぼうとしているらしいやつを Teratail や Qiita でたまに見るぞ。
C++03 と C++11 でほとんど互換性は維持されてはいるはずなんだがちょっとは非互換もあるし、
残されている機能でも今となってはあまりお勧めできないということもあるから
なるべくなら新しい本のほうがよいとは思うんだが、
俺自身が読んだことがある本が古すぎていまどきの良い本が全然わからん。
C++03 と C++11 でほとんど互換性は維持されてはいるはずなんだがちょっとは非互換もあるし、
残されている機能でも今となってはあまりお勧めできないということもあるから
なるべくなら新しい本のほうがよいとは思うんだが、
俺自身が読んだことがある本が古すぎていまどきの良い本が全然わからん。
907はちみつ餃子 ◆8X2XSCHEME
2022/10/20(木) 23:52:16.92ID:w/WeLGfC >>904
メンバーアクセス演算子によるメンバの選択は抽象クラスなら動的 (仮想関数テーブルを辿る) だが、
引数を元にしたオーバーロード解決は静的型 (static type) の情報が元になる。
静的型はあくまでも Shape だから一旦は Shape& で受けて
オブジェクトと引数を入れ替えてもういちど intersect を呼び出すことで両方とも動的な型でディスパッチすることになるんだよ。
普通はメンバアクセスの側だけが動的ディスパッチだから二つのオブジェクトについて動的ディスパッチをするには
こういうトリックが必要になる。 ふたつの動的ディスパッチをするからダブルディスパッチなの。
メンバーアクセス演算子によるメンバの選択は抽象クラスなら動的 (仮想関数テーブルを辿る) だが、
引数を元にしたオーバーロード解決は静的型 (static type) の情報が元になる。
静的型はあくまでも Shape だから一旦は Shape& で受けて
オブジェクトと引数を入れ替えてもういちど intersect を呼び出すことで両方とも動的な型でディスパッチすることになるんだよ。
普通はメンバアクセスの側だけが動的ディスパッチだから二つのオブジェクトについて動的ディスパッチをするには
こういうトリックが必要になる。 ふたつの動的ディスパッチをするからダブルディスパッチなの。
908デフォルトの名無しさん
2022/10/21(金) 03:42:31.85ID:sdgXBR6P909デフォルトの名無しさん
2022/10/21(金) 19:14:57.19ID:RdD+Edtl >>980
これは分かりにくかったかも知れません。
void func(Shape &a, Shape &b)
{
x.intersect(y); //(1)
}
Circle c{xxx};
Box b{xxx};
func(c, b);
のような場合に、(1)において、x の部分は仮想関数によってC++のもともとの機能で
実行時の型によって動的に振り分けできるが、y については、仮想関数では
そのような意味では振り分けできないから特殊な方法が必要になる、ということですね。
これは分かりにくかったかも知れません。
void func(Shape &a, Shape &b)
{
x.intersect(y); //(1)
}
Circle c{xxx};
Box b{xxx};
func(c, b);
のような場合に、(1)において、x の部分は仮想関数によってC++のもともとの機能で
実行時の型によって動的に振り分けできるが、y については、仮想関数では
そのような意味では振り分けできないから特殊な方法が必要になる、ということですね。
910デフォルトの名無しさん
2022/10/22(土) 00:28:36.65ID:76y4d7LL911デフォルトの名無しさん
2022/10/22(土) 21:57:41.88ID:Q+2x5vm1 モジュールはヘッダファイル・ソースファイルに代わるものと聞きました
これからは今までインクルードしていたものは全てモジュールにすればよいのでしょうか
また、グローバル変数のみのヘッダファイルや、定数のみのヘッダファイルも
モジュールにした方がよいのでしょうか
ビルド時間が速くなるそうなので気になっています
これからは今までインクルードしていたものは全てモジュールにすればよいのでしょうか
また、グローバル変数のみのヘッダファイルや、定数のみのヘッダファイルも
モジュールにした方がよいのでしょうか
ビルド時間が速くなるそうなので気になっています
912デフォルトの名無しさん
2022/10/22(土) 22:33:36.63ID:TUU3opDF >>909
ideone に動くソースを貼ってください、全然意味がわかりません
ideone に動くソースを貼ってください、全然意味がわかりません
913はちみつ餃子 ◆8X2XSCHEME
2022/10/22(土) 22:47:49.35ID:+VggblGg >>911
時期尚早だと思う。
現状の gcc ではオプションに -std=c++20 を付けるだけではモジュールは有効にならず、
明示的に -fmodules-ts を付ける必要があるようにしてあるので、普段使いするにはまだ早いという意図を感じる。
ドキュメントにはまだ完璧じゃないと書いてあるし。
(他のコンパイラの状況は知らんけど。)
それに C++20 の段階ではモジュールの基礎の基礎が決まっただけで
標準ライブラリすらモジュールとして再編できていない。 一応は C++23 でやることになってるけど
現在の C++ の規格は三年ごとに話がまとまった分を入れる、
つまり出来てない分を完成させるために期限を延長したりはせず三年後に先送りするという運用なので
C++23 がどこまで出来るものなのか全然わからん。
標準ライブラリを再編していく内にモジュール機能の問題点が発見されたりするかもしれん。
個人的に遊ぶ分には色々とやってみてわかったことはどんどん発信してほしいけど、
製品レベルのプロジェクトではやめておいたほうがいい。
時期尚早だと思う。
現状の gcc ではオプションに -std=c++20 を付けるだけではモジュールは有効にならず、
明示的に -fmodules-ts を付ける必要があるようにしてあるので、普段使いするにはまだ早いという意図を感じる。
ドキュメントにはまだ完璧じゃないと書いてあるし。
(他のコンパイラの状況は知らんけど。)
それに C++20 の段階ではモジュールの基礎の基礎が決まっただけで
標準ライブラリすらモジュールとして再編できていない。 一応は C++23 でやることになってるけど
現在の C++ の規格は三年ごとに話がまとまった分を入れる、
つまり出来てない分を完成させるために期限を延長したりはせず三年後に先送りするという運用なので
C++23 がどこまで出来るものなのか全然わからん。
標準ライブラリを再編していく内にモジュール機能の問題点が発見されたりするかもしれん。
個人的に遊ぶ分には色々とやってみてわかったことはどんどん発信してほしいけど、
製品レベルのプロジェクトではやめておいたほうがいい。
914デフォルトの名無しさん
2022/10/23(日) 00:24:14.37ID:Ti8rkbHi915デフォルトの名無しさん
2022/10/23(日) 06:09:10.65ID:lOKqFCBz MSは怪しい機能は/std:c++latestにしてるよな
916デフォルトの名無しさん
2022/10/23(日) 08:32:09.89ID:lOKqFCBz C++17のfilesystemもそうだったけど
練りきれてない未完成品を無理に入れるのやめて欲しい
バグ出ししたいんなら拡張規格かoptionalとして出してみて
標準のmandatoryにするのはしっかり固まってからにしろやって
つーかSTLもboost由来のもISO以外のところでそこそこユーザに揉まれてから来たものだろ
開拓は標準規格の役目じゃねえよ
練りきれてない未完成品を無理に入れるのやめて欲しい
バグ出ししたいんなら拡張規格かoptionalとして出してみて
標準のmandatoryにするのはしっかり固まってからにしろやって
つーかSTLもboost由来のもISO以外のところでそこそこユーザに揉まれてから来たものだろ
開拓は標準規格の役目じゃねえよ
917はちみつ餃子 ◆8X2XSCHEME
2022/10/23(日) 10:56:19.39ID:V+VjUFIF 完璧になるまで練ってたらいつまでも進まんから三年ごとに出来た分を規格に入れるという方針に変更されたんじゃないか。
不格好でも不完全でも今使えることが大事だというのは元々の理念だし。
未完成はともかく欠陥報告を乱発するのは良くはないけどさ。
不格好でも不完全でも今使えることが大事だというのは元々の理念だし。
未完成はともかく欠陥報告を乱発するのは良くはないけどさ。
918デフォルトの名無しさん
2022/10/23(日) 11:55:48.92ID:d3fh3q91 使ってる所だけ直せばいいライブラリと違って(だからって良いわけじゃないけど)
モジュール作り込んでからやっぱdefectでしたって言われたら困るからなあ
モジュール作り込んでからやっぱdefectでしたって言われたら困るからなあ
919デフォルトの名無しさん
2022/10/23(日) 12:11:50.11ID:ncgNttCh ライブラリとモジュールの違いって何ですか?
920デフォルトの名無しさん
2022/10/23(日) 12:51:46.87ID:d3fh3q91 使うだけの標準ライブラリと、モジュール自作する時の仕様のつもりだった
921デフォルトの名無しさん
2022/10/23(日) 13:12:57.82ID:HPAI20x7 filesystemって未完成なん?
922デフォルトの名無しさん
2022/10/23(日) 13:25:59.97ID:lOKqFCBz C++17の時点ではfile_clockがなかった
923デフォルトの名無しさん
2022/10/23(日) 14:32:45.34ID:ecBGWNL0 file_time_type があったと思うが
924デフォルトの名無しさん
2022/10/23(日) 14:45:23.56ID:lOKqFCBz あったけど使いものにならんかった
925デフォルトの名無しさん
2022/10/23(日) 14:59:53.65ID:NDMzlX+C その昔、iostreamというのがあってだな
皆阿鼻叫喚の断末魔の雄叫びを上げたもんじゃった
皆阿鼻叫喚の断末魔の雄叫びを上げたもんじゃった
926デフォルトの名無しさん
2022/10/23(日) 16:01:34.86ID:lOKqFCBz printfやscanfに毒舌三昧してる人に対して持っていた、お暇な方ですねという思いが蘇る
927はちみつ餃子 ◆8X2XSCHEME
2022/10/23(日) 17:49:58.24ID:V+VjUFIF ファイルシステムやらスレッドやらはシステム (OS) 側の都合があるからなぁ。
細かいことは環境依存の機能を使えという前提で
標準ライブラリを最小限にとどめるのは C の時代からの基本的な姿勢だっただろう。
環境依存だからこそ標準で吸収しておいてくれという気持ちもあるし、
現状が良いとも思わんけど…… なんというか……
C++ ってそういうもんだろと思って納得してるから不満には感じないな。
細かいことは環境依存の機能を使えという前提で
標準ライブラリを最小限にとどめるのは C の時代からの基本的な姿勢だっただろう。
環境依存だからこそ標準で吸収しておいてくれという気持ちもあるし、
現状が良いとも思わんけど…… なんというか……
C++ ってそういうもんだろと思って納得してるから不満には感じないな。
928デフォルトの名無しさん
2022/10/23(日) 20:20:25.05ID:7je1ARgT iosteamはいかにもC++初心者がやりそうな「オペレータをオーバーロードできるから
見た目イカすちょっとシャレた表記法にしようぜ!!」っていう厨二スピリット全開だったからな
でてきた時点で「あ、これはクソなやつだ」ってわかったよ
見た目イカすちょっとシャレた表記法にしようぜ!!」っていう厨二スピリット全開だったからな
でてきた時点で「あ、これはクソなやつだ」ってわかったよ
929デフォルトの名無しさん
2022/10/23(日) 20:43:19.02ID:lOKqFCBz C with classesを始めようとして
たとえばと始めたことをずいぶん後になって
鬼の首を取ったようにキリッ
たとえばと始めたことをずいぶん後になって
鬼の首を取ったようにキリッ
930デフォルトの名無しさん
2022/10/23(日) 22:04:42.81ID:d3fh3q91 演算子チェーン自体は別に悪いもんじゃない
iostreamがクソなのはそこじゃない
iostreamがクソなのはそこじゃない
931デフォルトの名無しさん
2022/10/23(日) 22:42:38.11ID:9PrlG1Sf でも競プロで何も考えずにcin >> N >> M;とかできるでしょ
932デフォルトの名無しさん
2022/10/23(日) 23:18:01.98ID:a4G1Se92 なにかとiostream叩かれやすいけど
よく聞いてみると大した批判ではないよね常に
聞くに値するiostream批判ってお目にかからないね
よく聞いてみると大した批判ではないよね常に
聞くに値するiostream批判ってお目にかからないね
933デフォルトの名無しさん
2022/10/23(日) 23:21:04.29ID:HPAI20x7 iostreamが本当にクソならイカした再実装はあるだろう?
まさかcstdioとか言わんでくれよ
まさかcstdioとか言わんでくれよ
934デフォルトの名無しさん
2022/10/23(日) 23:23:02.52ID:d3fh3q91 まあstd::cout << foo << bar;がつい最近まで規格上未定義動作だったのは擁護のしようがないけどな
935はちみつ餃子 ◆8X2XSCHEME
2022/10/23(日) 23:33:00.12ID:V+VjUFIF iostream が設計された当時は I/O のための専用の言語機能が
必要という論調があって、 Bjarne Stroustrup 氏はそれに抵抗して
当時の C++ の範疇でライブラリを作ったという経緯がある。
ここで抵抗しなければ入出力用の文法が (ライブラリとしてではなく)
言語機能として導入することになっていたかもしれないと思うと
iostream にある粗くらいは許せてしまうなぁ。
少なくとも printf みたいな型チェックがガバガバなのは C++ 的に
放置できなかったし、バッファリングと書式化をまとめつつ拡張やカスタマイズが可能で
I/O 以外も含めてストリームというインターフェイスを一般化するというのは
当時としてはこれ以上考えられない素晴らしいデザインだと思う。
ひとつこれは (iostream 設計当時でも) どうにかできただろうと思うのは
書式の変更 (マニピュレータを使うなど) をしたら陽に戻すまではそのままというのが良くなかった。
スコープを抜けたらリセットできるような方法が標準で欲しかった。
(boost にあったような気がするが名前を忘れてしまった……。)
必要という論調があって、 Bjarne Stroustrup 氏はそれに抵抗して
当時の C++ の範疇でライブラリを作ったという経緯がある。
ここで抵抗しなければ入出力用の文法が (ライブラリとしてではなく)
言語機能として導入することになっていたかもしれないと思うと
iostream にある粗くらいは許せてしまうなぁ。
少なくとも printf みたいな型チェックがガバガバなのは C++ 的に
放置できなかったし、バッファリングと書式化をまとめつつ拡張やカスタマイズが可能で
I/O 以外も含めてストリームというインターフェイスを一般化するというのは
当時としてはこれ以上考えられない素晴らしいデザインだと思う。
ひとつこれは (iostream 設計当時でも) どうにかできただろうと思うのは
書式の変更 (マニピュレータを使うなど) をしたら陽に戻すまではそのままというのが良くなかった。
スコープを抜けたらリセットできるような方法が標準で欲しかった。
(boost にあったような気がするが名前を忘れてしまった……。)
936デフォルトの名無しさん
2022/10/23(日) 23:47:22.83ID:d3fh3q91 ステートはクソで出来るだけ無くすべきっていう現代の常識が当時はなかったからな
書式をストリームのステートにしてしまったのは今思えば大失敗だがあの時代は自然な設計だったんだろうな
書式をストリームのステートにしてしまったのは今思えば大失敗だがあの時代は自然な設計だったんだろうな
937デフォルトの名無しさん
2022/10/23(日) 23:48:05.17ID:yEdZxD03 >>934 foo, bar がどのように定義されていたらその式が未定義動作になるの?
938デフォルトの名無しさん
2022/10/23(日) 23:48:47.26ID:a4G1Se92 批判する者にその資格が無いってパティーン多々あるよな
iostream批判するやつだって
じゃあどんな素晴らしい入出力ライブラリを用意したの?
実装したの?どこの誰がどれだけ使ってるの?っていう
タダ飯喰らいがかーちゃんのご飯批判してるようなこと
iostream批判するやつだって
じゃあどんな素晴らしい入出力ライブラリを用意したの?
実装したの?どこの誰がどれだけ使ってるの?っていう
タダ飯喰らいがかーちゃんのご飯批判してるようなこと
939デフォルトの名無しさん
2022/10/23(日) 23:55:56.29ID:RbY+y3zv 未定義じゃなくて、引数の評価順が未規定だったって話では?
940デフォルトの名無しさん
2022/10/23(日) 23:56:39.14ID:d3fh3q91 >>937
何だろうと未定義(C++17以前)。なぜなら一つの式の中でstd::coutを2回変更してるから
(a+=1)+=1とか++(++a)とかも同じ
この大欠陥が見つかったせいで、式の中の評価順は基本コンパイラの好き勝手にしていいというCからの伝統を一部諦める羽目になった
何だろうと未定義(C++17以前)。なぜなら一つの式の中でstd::coutを2回変更してるから
(a+=1)+=1とか++(++a)とかも同じ
この大欠陥が見つかったせいで、式の中の評価順は基本コンパイラの好き勝手にしていいというCからの伝統を一部諦める羽目になった
941デフォルトの名無しさん
2022/10/24(月) 00:00:00.66ID:9tRgjj9T >>940
foo, bar の評価順が未規定だった件を未定義動作と勘違いしてるのか。
https://cpprefjp.github.io/lang/cpp17/expression_evaluation_order.html
cout に対する操作は関数呼び出しの内外の順序付けが入るから未定義動作にはならないよ。
foo, bar の評価順が未規定だった件を未定義動作と勘違いしてるのか。
https://cpprefjp.github.io/lang/cpp17/expression_evaluation_order.html
cout に対する操作は関数呼び出しの内外の順序付けが入るから未定義動作にはならないよ。
942デフォルトの名無しさん
2022/10/24(月) 00:02:05.10ID:9tRgjj9T >>940 (a+=1)+=1 も ++(++a) も未定義動作にはならないよ。必ず a が 2 増えて、 a への参照が得られる。
943デフォルトの名無しさん
2022/10/24(月) 00:24:37.42ID:hB4gzcTK >>940
<<は左から評価じゃね?
<<は左から評価じゃね?
944デフォルトの名無しさん
2022/10/24(月) 00:26:04.46ID:hB4gzcTK もっというと同じ2項演算子が複数でてきたら左から評価では?
数学と同じ
数学と同じ
945デフォルトの名無しさん
2022/10/24(月) 00:43:11.90ID:g4dlefHT cout<<a<<b;
の場合、左結合なので、評価順序は、
(cout<<a)<<b;
となるが、aとbの中に関数や演算子が書いてあるような場合、
それがいつ評価されるのは実装依存だったような気がする。つまり、
operator<<(operator<<(cout,a),b);
みたいに評価はされることは決まっているが、aとbの評価が、aが先かbが先かは
決まってない、というような話。もっと言えば、cout自体の部分が式や関数になって
いる場合も、cout,a,bの評価順序が決まって無いかも。
の場合、左結合なので、評価順序は、
(cout<<a)<<b;
となるが、aとbの中に関数や演算子が書いてあるような場合、
それがいつ評価されるのは実装依存だったような気がする。つまり、
operator<<(operator<<(cout,a),b);
みたいに評価はされることは決まっているが、aとbの評価が、aが先かbが先かは
決まってない、というような話。もっと言えば、cout自体の部分が式や関数になって
いる場合も、cout,a,bの評価順序が決まって無いかも。
946デフォルトの名無しさん
2022/10/24(月) 00:45:03.87ID:g4dlefHT947デフォルトの名無しさん
2022/10/24(月) 00:54:22.51ID:etIo9wEk 未規定の動作(unspecified behavior)と未定義動作(undefined behavior)は違うよ
948デフォルトの名無しさん
2022/10/24(月) 01:00:58.84ID:hB4gzcTK949デフォルトの名無しさん
2022/10/24(月) 01:15:48.16ID:g4dlefHT >>948
実は、x86などでは、スタックが、メモリーアドレスの大きい方からから小さい方
に成長するようになっているので、引数は右側から左側に評価した方が効率が良い。
そのため、逆さまに評価する処理系があっても不思議ではない。
実は、x86などでは、スタックが、メモリーアドレスの大きい方からから小さい方
に成長するようになっているので、引数は右側から左側に評価した方が効率が良い。
そのため、逆さまに評価する処理系があっても不思議ではない。
950デフォルトの名無しさん
2022/10/24(月) 01:33:32.70ID:1OFaOw+N ちょっと前までの規格では単一式(≒セミコロンとセミコロンの間)の中の評価順は基本的にコンパイラが好き勝手に弄る事が許されてた
例えばa[++b]=cとかはヒトの常識的にはbをインクリメントしてからa[b+1]にcを代入するけど、別にa[b+1]にcを代入してからbを増やしたって構わない(この前のどっかでa[b+1]を参照してればその方が最適化したら効率的かもしれない)
そんな感じで最適化に都合がいいように評価順には寛容すぎるほど寛容だったんだが、カオスを防ぐためのルールがあって、それが「単一式で同じオブジェクトを2回変更したら未定義」というもの
例えば(a+=1)+=1はどっちの1を先にaに足してもいいが、そういう自由度がある時点で未定義というルールになっていた
もっと分かりやすい例だと(a+=2)*=3は最初のaが1なら常識的には9になると思うけど、評価順ルール的には3を先に掛けてから2を足して5にしたっていい
9か5の二択で済むこれはマシな方で、ポインタが絡むと収拾がつかなくなるから、同じもん2回以上書き換えたらもう知らん未定義じゃってのがCとちょい前までのc++の規格の趣旨だった
で、この話をさっきのiostreamに持ち込むと、operator <<はconstメンバー関数じゃないので、cout << foo << barはcout << fooと、(cout<<fooの戻り値==coutの参照) << barの2回のcoutへの変更を順序は不確定な単一式でやってることになる。つまりさっきのaと同じように未定義動作って事
(cout <<fooを先に実行しないと戻り値確定しないからこっちが先に決まってるのでは?と思うだろうけど、規格の文言上はcout <<fooの戻り値を「予測」して<<barの適用を先にやったって構わないのである。そんな病的なコンパイラがたまたま実在しなかったから今まで問題にならなかったんだろうけどね)
という話がrangesのパイプでoperator|のチェーンの検討をしてるときに発覚してみんな真っ青になって慌てて評価順のルールが見直されたっていう、まあアホ臭い話でした
幸い病的な最適化コンパイラが生まれる前だったから規格文言だけの話で実害はない
例えばa[++b]=cとかはヒトの常識的にはbをインクリメントしてからa[b+1]にcを代入するけど、別にa[b+1]にcを代入してからbを増やしたって構わない(この前のどっかでa[b+1]を参照してればその方が最適化したら効率的かもしれない)
そんな感じで最適化に都合がいいように評価順には寛容すぎるほど寛容だったんだが、カオスを防ぐためのルールがあって、それが「単一式で同じオブジェクトを2回変更したら未定義」というもの
例えば(a+=1)+=1はどっちの1を先にaに足してもいいが、そういう自由度がある時点で未定義というルールになっていた
もっと分かりやすい例だと(a+=2)*=3は最初のaが1なら常識的には9になると思うけど、評価順ルール的には3を先に掛けてから2を足して5にしたっていい
9か5の二択で済むこれはマシな方で、ポインタが絡むと収拾がつかなくなるから、同じもん2回以上書き換えたらもう知らん未定義じゃってのがCとちょい前までのc++の規格の趣旨だった
で、この話をさっきのiostreamに持ち込むと、operator <<はconstメンバー関数じゃないので、cout << foo << barはcout << fooと、(cout<<fooの戻り値==coutの参照) << barの2回のcoutへの変更を順序は不確定な単一式でやってることになる。つまりさっきのaと同じように未定義動作って事
(cout <<fooを先に実行しないと戻り値確定しないからこっちが先に決まってるのでは?と思うだろうけど、規格の文言上はcout <<fooの戻り値を「予測」して<<barの適用を先にやったって構わないのである。そんな病的なコンパイラがたまたま実在しなかったから今まで問題にならなかったんだろうけどね)
という話がrangesのパイプでoperator|のチェーンの検討をしてるときに発覚してみんな真っ青になって慌てて評価順のルールが見直されたっていう、まあアホ臭い話でした
幸い病的な最適化コンパイラが生まれる前だったから規格文言だけの話で実害はない
951デフォルトの名無しさん
2022/10/24(月) 01:59:23.78ID:hB4gzcTK aが1のとき(a+=2)*=3が5に成り得たと書いているがほんまかいな?
952デフォルトの名無しさん
2022/10/24(月) 02:10:09.65ID:JEuztk1D 9か5かってのは説明上の話で、実際は未定義で鼻から悪魔だから9でも5でも0でも-1でも42でも4394967295でもどんな可能性もあった
今の規格では必ず9になった
今の規格では必ず9になった
953デフォルトの名無しさん
2022/10/24(月) 02:11:12.04ID:b0depGja https://ja.cppreference.com/w/cpp/language/eval_order
スカラーオブジェクトに対する変更にしかUB関係なくね?
スカラーオブジェクトに対する変更にしかUB関係なくね?
954デフォルトの名無しさん
2022/10/24(月) 02:19:24.78ID:od8Ytdiw operator<<が触ってるcoutのメンバ変数やグローバル変数にスカラーオブジェクトが一切含まれてなければ関係ないけど普通はそんなはずは無い
955デフォルトの名無しさん
2022/10/24(月) 07:45:35.99ID:bUVy0t4Y テキストがバラけたり変数の並び順を変えられなくてi18n対応が困難になるのがiostreamの一番の問題かな
956デフォルトの名無しさん
2022/10/24(月) 08:12:37.76ID:OQANp5iI957デフォルトの名無しさん
2022/10/24(月) 09:31:36.65ID:9tRgjj9T >>950
> それが「単一式で同じオブジェクトを2回変更したら未定義」というもの
C++11 より前のシーケンスポイント(副作用完了点よるルールの話だとしても関数呼び出しの前後には
シーケンスポイントが入るので cout の operator<< で未定義動作が起こるような話にはならない。
> それが「単一式で同じオブジェクトを2回変更したら未定義」というもの
C++11 より前のシーケンスポイント(副作用完了点よるルールの話だとしても関数呼び出しの前後には
シーケンスポイントが入るので cout の operator<< で未定義動作が起こるような話にはならない。
958デフォルトの名無しさん
2022/10/24(月) 09:49:55.97ID:9tRgjj9T >>950
「rangesのパイプでoperator|のチェーンの検討をしてるとき」とか言ってるから
本気で C++17 改定前の話をしてるっぽいなぁ。
> それが「単一式で同じオブジェクトを2回変更したら未定義」というもの
ここから間違い。 C++11 以降は "sequenced before" の順序関係に基づくルールになっていて、
そんな大雑把なルールではない。
> 例えば(a+=1)+=1はどっちの1を先にaに足してもいいが、そういう自由度がある時点で未定義というルールになっていた
C++11 時点で代入式の値取得は代入より後になると規定されているよ。
https://timsong-cpp.github.io/cppwp/n3337/expr.ass#1
> In all cases, the assignment is sequenced after the value computation of
> the right and left operands, and before the value computation of the assignment expression.
関数呼び出し前後に順序関係もある。
https://timsong-cpp.github.io/cppwp/n3337/intro.execution#15
> When calling a function (whether or not the function is inline), every value
> computation and side effect associated with any argument expression,
> or with the postfix expression designating the called function, is sequenced before
> execution of every expression or statement in the body of the called function.
「rangesのパイプでoperator|のチェーンの検討をしてるとき」とか言ってるから
本気で C++17 改定前の話をしてるっぽいなぁ。
> それが「単一式で同じオブジェクトを2回変更したら未定義」というもの
ここから間違い。 C++11 以降は "sequenced before" の順序関係に基づくルールになっていて、
そんな大雑把なルールではない。
> 例えば(a+=1)+=1はどっちの1を先にaに足してもいいが、そういう自由度がある時点で未定義というルールになっていた
C++11 時点で代入式の値取得は代入より後になると規定されているよ。
https://timsong-cpp.github.io/cppwp/n3337/expr.ass#1
> In all cases, the assignment is sequenced after the value computation of
> the right and left operands, and before the value computation of the assignment expression.
関数呼び出し前後に順序関係もある。
https://timsong-cpp.github.io/cppwp/n3337/intro.execution#15
> When calling a function (whether or not the function is inline), every value
> computation and side effect associated with any argument expression,
> or with the postfix expression designating the called function, is sequenced before
> execution of every expression or statement in the body of the called function.
959デフォルトの名無しさん
2022/10/24(月) 23:16:53.41ID:Fd/xLFmz どなたか、clangコンパイラのソースコードで、main()関数がどのソースファイル
にあるか分かりませんか?
にあるか分かりませんか?
960デフォルトの名無しさん
2022/10/24(月) 23:38:51.20ID:uNnUskRf grepで始めよう
新しい検索を
新しい検索を
961デフォルトの名無しさん
2022/10/24(月) 23:50:22.01ID:Fd/xLFmz >>960
もちろんgrepはしていますが、
test用のソースコードなどに大量に出てきてしまうのでどれか分からないのです。
探しているのですが、むしろ、clangコンパイラ自体のmain関数は存在して
無いのではないかと思えてしまいます。
もちろんgrepはしていますが、
test用のソースコードなどに大量に出てきてしまうのでどれか分からないのです。
探しているのですが、むしろ、clangコンパイラ自体のmain関数は存在して
無いのではないかと思えてしまいます。
962デフォルトの名無しさん
2022/10/25(火) 00:20:05.85ID:ALWiFOZj963デフォルトの名無しさん
2022/10/25(火) 00:20:30.61ID:ALWiFOZj まちがえたdriver.cppね
964デフォルトの名無しさん
2022/10/25(火) 15:32:20.93ID:VfaC5Wzc このコードでfunc(a)だけがコンパイル通らないんだけどどう対策すれば綺麗な感じになる?
ユニバーサル参照の受け取りのとこでT=int&がstd::integralを満たさないのが原因なんだけど
integral_or_lrefコンセプト作るしかない?
#include<utility>
#include<concepts>
template<std::integral T>
void func(T&&);
int main(){
int a=0;
func(0);
//func(a);
func(std::move(a));
}
ユニバーサル参照の受け取りのとこでT=int&がstd::integralを満たさないのが原因なんだけど
integral_or_lrefコンセプト作るしかない?
#include<utility>
#include<concepts>
template<std::integral T>
void func(T&&);
int main(){
int a=0;
func(0);
//func(a);
func(std::move(a));
}
965デフォルトの名無しさん
2022/10/25(火) 15:33:30.00ID:Ct0eul8Q 超初心者+わかりにくい文章で、ごめんなさい。
今までは、.NetFramewor4.72でWinFormを使って実装していました。
今、.Net6.0 の WinFormで実装する必要が出てきたので
.Net6.0 で実装しています。
.NetFramewor4.72 でWindowsBaseの参照の追加で使えていた
System.Windows.Threading.Dispatcher が
.Net6.0 では、「依存関係」の「COM」で設定しようとしても、
WindowsBaseが表示されず、WindowsBaseを設定できなくて
System.Windows.Threading.Dispatcherが使えなくて、困っています。
同じような課題を諸先輩方は
どのように解決されましたか?
今までは、.NetFramewor4.72でWinFormを使って実装していました。
今、.Net6.0 の WinFormで実装する必要が出てきたので
.Net6.0 で実装しています。
.NetFramewor4.72 でWindowsBaseの参照の追加で使えていた
System.Windows.Threading.Dispatcher が
.Net6.0 では、「依存関係」の「COM」で設定しようとしても、
WindowsBaseが表示されず、WindowsBaseを設定できなくて
System.Windows.Threading.Dispatcherが使えなくて、困っています。
同じような課題を諸先輩方は
どのように解決されましたか?
966デフォルトの名無しさん
2022/10/25(火) 15:37:45.19ID:VfaC5Wzc967デフォルトの名無しさん
2022/10/25(火) 15:39:23.68ID:Yrt8fN18 CLIはこっちか?
968はちみつ餃子 ◆8X2XSCHEME
2022/10/25(火) 15:54:18.45ID:kIG3TWOj >>964
参照を剥がすのを入れるのが常道じゃないかな?
template<class T>
requires std::integral<std::remove_reference_t<T>>
void func(T&&);
参照を剥がすのを入れるのが常道じゃないかな?
template<class T>
requires std::integral<std::remove_reference_t<T>>
void func(T&&);
969デフォルトの名無しさん
2022/10/25(火) 16:15:10.24ID:2SxwmPby970デフォルトの名無しさん
2022/10/25(火) 18:06:59.76ID:NHQVrZyF そういうとき脳死でstd::decay使っちゃうけどあんま行儀良くないかな
971デフォルトの名無しさん
2022/10/25(火) 18:13:31.96ID:UwkZi3XT >>962
ありがとう。関数名が main() ではなく、
clang_main()
なんですね。
cmakeすると、これがすぐ呼び出されるような main() 関数が
作られるようです。
cmakeがどういう仕組みでそうやっているのかは分かりませんが。
ありがとう。関数名が main() ではなく、
clang_main()
なんですね。
cmakeすると、これがすぐ呼び出されるような main() 関数が
作られるようです。
cmakeがどういう仕組みでそうやっているのかは分かりませんが。
972デフォルトの名無しさん
2022/10/25(火) 18:15:07.22ID:UwkZi3XT973デフォルトの名無しさん
2022/10/25(火) 20:38:52.33ID:m6AygvvN どっちかってーと リンカで実行時のエントリポイントを細工してるんじゃないのかな?
974デフォルトの名無しさん
2022/10/26(水) 01:01:19.91ID:lrkwz/4D 追加質問です。
llvm のソースの中に、以下の様に、
配置 new に似ていてもそれとは違うような new 演算子の使用方法が
有りますが、分かる人いますか? 例えば、
new (2) CatchReturnInst(CatchPad, BB, InsertBefore);
は、配置 new の new (p) T(引数列) に似ていますが、
p の位置は、アドレスを指定することになっているのに、
「2」という整数値を指定しています。
llvm-project-main/llvm/include/llvm/IR/Instructions.h
の
class CatchPadInst : public FuncletPadInst {・・・}
の中の
static CatchPadInst *Create(Value *CatchSwitch, ArrayRef<Value *> Args,
const Twine &NameStr = "",
Instruction *InsertBefore = nullptr) {
unsigned Values = 1 + Args.size();
return new (Values)
CatchPadInst(CatchSwitch, Args, Values, NameStr, InsertBefore);
}
class CatchReturnInst : public Instruction {・・・}
の中の
static CatchReturnInst *Create(Value *CatchPad, BasicBlock *BB,
Instruction *InsertBefore = nullptr) {
assert(CatchPad);
assert(BB);
return new (2) CatchReturnInst(CatchPad, BB, InsertBefore);
}
llvm のソースの中に、以下の様に、
配置 new に似ていてもそれとは違うような new 演算子の使用方法が
有りますが、分かる人いますか? 例えば、
new (2) CatchReturnInst(CatchPad, BB, InsertBefore);
は、配置 new の new (p) T(引数列) に似ていますが、
p の位置は、アドレスを指定することになっているのに、
「2」という整数値を指定しています。
llvm-project-main/llvm/include/llvm/IR/Instructions.h
の
class CatchPadInst : public FuncletPadInst {・・・}
の中の
static CatchPadInst *Create(Value *CatchSwitch, ArrayRef<Value *> Args,
const Twine &NameStr = "",
Instruction *InsertBefore = nullptr) {
unsigned Values = 1 + Args.size();
return new (Values)
CatchPadInst(CatchSwitch, Args, Values, NameStr, InsertBefore);
}
class CatchReturnInst : public Instruction {・・・}
の中の
static CatchReturnInst *Create(Value *CatchPad, BasicBlock *BB,
Instruction *InsertBefore = nullptr) {
assert(CatchPad);
assert(BB);
return new (2) CatchReturnInst(CatchPad, BB, InsertBefore);
}
976デフォルトの名無しさん
2022/10/26(水) 01:09:20.17ID:AzbtQsoy977デフォルトの名無しさん
2022/10/26(水) 01:53:26.73ID:U/bwzoe1 >>975
以下の様に、new (Us) CatchReturnInst(引数列)は、
Userクラスの operator new(Size, Us) を使っていて、
で、Usには、アドレス値ではなく、Use 型の個数を入れるようです。
通常の operatoe new()では、第二引数はアドレス値です。
class CatchReturnInst : public Instruction {・・・};
class Instruction : public User,
public ilist_node_with_parent<Instruction, BasicBlock> {・・・};
void *User::operator new(size_t Size, unsigned Us) {
return allocateFixedOperandUser(Size, Us, 0);
}
void *User::operator new(size_t Size, unsigned Us, unsigned DescBytes) {
return allocateFixedOperandUser(Size, Us, DescBytes);
}
void *User::allocateFixedOperandUser(size_t Size, unsigned Us,
unsigned DescBytes) {
・・・
uint8_t *Storage = static_cast<uint8_t *>(
::operator new(Size + sizeof(Use) * Us + DescBytesToAllocate));
・・・
}
以下の様に、new (Us) CatchReturnInst(引数列)は、
Userクラスの operator new(Size, Us) を使っていて、
で、Usには、アドレス値ではなく、Use 型の個数を入れるようです。
通常の operatoe new()では、第二引数はアドレス値です。
class CatchReturnInst : public Instruction {・・・};
class Instruction : public User,
public ilist_node_with_parent<Instruction, BasicBlock> {・・・};
void *User::operator new(size_t Size, unsigned Us) {
return allocateFixedOperandUser(Size, Us, 0);
}
void *User::operator new(size_t Size, unsigned Us, unsigned DescBytes) {
return allocateFixedOperandUser(Size, Us, DescBytes);
}
void *User::allocateFixedOperandUser(size_t Size, unsigned Us,
unsigned DescBytes) {
・・・
uint8_t *Storage = static_cast<uint8_t *>(
::operator new(Size + sizeof(Use) * Us + DescBytesToAllocate));
・・・
}
978デフォルトの名無しさん
2022/10/26(水) 01:56:10.10ID:U/bwzoe1 >>976
>ごめん、tools/driver/driver.cppだった。321行目あたりにmainあるけどこれじゃないの?
そのサイトは、mirrorサイトで「legacy」とされ、だいぶ古いバージョンなんです。
最新バージョンのソースでは、driver.cpp には clang_main()しかないと思います。
cmakeすると、buildフォルダに、
int main(int argc, char *argv[]) { return clang_main(argc, argv); }
のような一行の関数が出来ます。
>ごめん、tools/driver/driver.cppだった。321行目あたりにmainあるけどこれじゃないの?
そのサイトは、mirrorサイトで「legacy」とされ、だいぶ古いバージョンなんです。
最新バージョンのソースでは、driver.cpp には clang_main()しかないと思います。
cmakeすると、buildフォルダに、
int main(int argc, char *argv[]) { return clang_main(argc, argv); }
のような一行の関数が出来ます。
979デフォルトの名無しさん
2022/10/26(水) 02:33:27.35ID:U/bwzoe1 >>978
(1) 本当の clang の main() 関数本体 :
(llvm-project-main/clang/tools/driver/driver.cpp):
int clang_main(int Argc, char **Argv) {
・・・
・・・
}
(2) clang_main() を呼び出す main() 関数 :
(llvm-project-main/build/tools/clang/tools/driver/clang-driver.cpp):
↑
build は、cmake の destination ディレクトリです。
int clang_main(int argc, char **argv);
int main(int argc, char **argv) { return clang_main(argc, argv); }
↑本当にこんな風に一行の関数になっています。恐らく、cmake が
生成したものと思われます。
(1) 本当の clang の main() 関数本体 :
(llvm-project-main/clang/tools/driver/driver.cpp):
int clang_main(int Argc, char **Argv) {
・・・
・・・
}
(2) clang_main() を呼び出す main() 関数 :
(llvm-project-main/build/tools/clang/tools/driver/clang-driver.cpp):
↑
build は、cmake の destination ディレクトリです。
int clang_main(int argc, char **argv);
int main(int argc, char **argv) { return clang_main(argc, argv); }
↑本当にこんな風に一行の関数になっています。恐らく、cmake が
生成したものと思われます。
980デフォルトの名無しさん
2022/10/26(水) 09:07:24.21ID:AzbtQsoy981デフォルトの名無しさん
2022/10/26(水) 09:39:06.48ID:8n8wOLOb >>968
やはりrequiresを1行足すしかないか...
template<allow_ref<std::integral> T>
void func(T&&);
とでも書きたかったけど、コンセプトを受け取るテンプレートが書けないっぽいから諦めた
やはりrequiresを1行足すしかないか...
template<allow_ref<std::integral> T>
void func(T&&);
とでも書きたかったけど、コンセプトを受け取るテンプレートが書けないっぽいから諦めた
982デフォルトの名無しさん
2022/10/27(木) 02:01:40.47ID:XIiqnbUh clangのソースで、CPUのマシン語を生成している場所を調べていて、
X86AsmPrinter クラスや X86MCInstLower クラスがそれに強く関与していることが分かって
きました。
X86AsmPrinter クラスや X86MCInstLower クラスは、お互いに参照されてますが、
この2つのクラスは、いずれも「作られている場所」が見つかりません。
「作られている」とは、new X86AsmPrinter や、X86AsmPrinter a;、
new X86MCInstLower や X86MCInstLower b; のようにしている場所です。
どなたか分かりませんか?
X86AsmPrinter クラスや X86MCInstLower クラスがそれに強く関与していることが分かって
きました。
X86AsmPrinter クラスや X86MCInstLower クラスは、お互いに参照されてますが、
この2つのクラスは、いずれも「作られている場所」が見つかりません。
「作られている」とは、new X86AsmPrinter や、X86AsmPrinter a;、
new X86MCInstLower や X86MCInstLower b; のようにしている場所です。
どなたか分かりませんか?
983デフォルトの名無しさん
2022/10/27(木) 02:32:01.95ID:XIiqnbUh >>982
すみません、多分、以下の部分ですね。
これで、new X86AsmPrinterしたアドレスを、getTheX86_32Target()やgetTheX86_64Target()
が返した Target クラスのシングルトンのインスタンス xxx に対して
xxx.AsmPrinterCtorFn = アドレス;
のように記録しているようです。
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeX86AsmPrinter() {
RegisterAsmPrinter<X86AsmPrinter> X(getTheX86_32Target());
RegisterAsmPrinter<X86AsmPrinter> Y(getTheX86_64Target());
}
template <class AsmPrinterImpl> struct RegisterAsmPrinter {
RegisterAsmPrinter(Target &T) {
TargetRegistry::RegisterAsmPrinter(T, &Allocator);
}
private:
static AsmPrinter *Allocator(TargetMachine &TM,
std::unique_ptr<MCStreamer> &&Streamer) {
return new AsmPrinterImpl(TM, std::move(Streamer));
}
};
/// TargetRegistry - Generic interface to target specific features.
struct TargetRegistry {
・・・
static void RegisterAsmPrinter(Target &T, Target::AsmPrinterCtorTy Fn) {
T.AsmPrinterCtorFn = Fn;
}
・・・
};
すみません、多分、以下の部分ですね。
これで、new X86AsmPrinterしたアドレスを、getTheX86_32Target()やgetTheX86_64Target()
が返した Target クラスのシングルトンのインスタンス xxx に対して
xxx.AsmPrinterCtorFn = アドレス;
のように記録しているようです。
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeX86AsmPrinter() {
RegisterAsmPrinter<X86AsmPrinter> X(getTheX86_32Target());
RegisterAsmPrinter<X86AsmPrinter> Y(getTheX86_64Target());
}
template <class AsmPrinterImpl> struct RegisterAsmPrinter {
RegisterAsmPrinter(Target &T) {
TargetRegistry::RegisterAsmPrinter(T, &Allocator);
}
private:
static AsmPrinter *Allocator(TargetMachine &TM,
std::unique_ptr<MCStreamer> &&Streamer) {
return new AsmPrinterImpl(TM, std::move(Streamer));
}
};
/// TargetRegistry - Generic interface to target specific features.
struct TargetRegistry {
・・・
static void RegisterAsmPrinter(Target &T, Target::AsmPrinterCtorTy Fn) {
T.AsmPrinterCtorFn = Fn;
}
・・・
};
984デフォルトの名無しさん
2022/10/27(木) 02:43:40.35ID:InDGsMhW なんかコンセプト以前にテンプレートにもあまり慣れてなさそう
985デフォルトの名無しさん
2022/10/27(木) 02:44:18.56ID:XIiqnbUh 間違えました。
xxx.AsmPrinterCtorFn に登録しているのは、new X86AsmPrinterの
アドレスではなく、
RegisterAsmPrinter<X86AsmPrinter>::Allocator(・・・)
のアドレスのようですね。
そして、このAllocator (==関数)を呼び出すと、new X86AsmPrinter
を行なえるようです。
xxx.AsmPrinterCtorFn に登録しているのは、new X86AsmPrinterの
アドレスではなく、
RegisterAsmPrinter<X86AsmPrinter>::Allocator(・・・)
のアドレスのようですね。
そして、このAllocator (==関数)を呼び出すと、new X86AsmPrinter
を行なえるようです。
986デフォルトの名無しさん
2022/10/27(木) 08:37:49.38ID:yP/aIJbf 関係ないけどあんまりnewせんほうがええよ
それしかないと思ってるならちょっと古い感じ
それしかないと思ってるならちょっと古い感じ
987デフォルトの名無しさん
2022/10/27(木) 22:03:08.74ID:+UGgATct あんまりデータメンバに直アクセスしないほうがええよ
あんまりグローバル変数使わんほうがええよ
あんまりSendMessageを直に使わんほうがええよ
あんまりナマポ使わんほうがええよ
あんまりアセンブラ使わんほうがええよ
あんまりC++使わんほうがええよ
ラップしろってことだろうけど
一切離れたやつはもうC++使いじゃない
あんまりグローバル変数使わんほうがええよ
あんまりSendMessageを直に使わんほうがええよ
あんまりナマポ使わんほうがええよ
あんまりアセンブラ使わんほうがええよ
あんまりC++使わんほうがええよ
ラップしろってことだろうけど
一切離れたやつはもうC++使いじゃない
988デフォルトの名無しさん
2022/10/28(金) 00:40:37.68ID:sQHy7sst989デフォルトの名無しさん
2022/10/28(金) 08:56:31.64ID:+oOKe7Yr 可変長テンプレートはじみて使ったけど便利だなこれ
990デフォルトの名無しさん
2022/10/28(金) 09:06:12.57ID:kPJo8naK threadがあんなに使いやすくなっているのは
ひとえにtemplate-parameter-packのおかげ
ひとえにtemplate-parameter-packのおかげ
991デフォルトの名無しさん
2022/10/29(土) 23:34:49.08ID:Ank2ZEY0 >>950の話は終わりかな?
レスついたけど反論がないようだけど
レスついたけど反論がないようだけど
992デフォルトの名無しさん
2022/10/30(日) 03:51:06.75ID:i1fpLCEI 5ch始めたばかりなのかな?
レス数が950を超えています。1000を超えると書き込みができなくなります。
ニュース
- 習政権、高市首相への態度硬化 台湾有事発言で連日非難 中国 ★10 [ぐれ★]
- 【日本大使館】中国在留邦人は安全確保を [ぐれ★]
- 【外国人問題】小野田紀美担当相「不法就労や不法滞在は許さない」 [シャチ★]
- 【野球】井端監督 大谷翔平、山本由伸らのWBCへの参加 「1日も早く返事ほしい」「待っててといっても、国内組が遅くなってしまう」★3 [冬月記者★]
- 橋下徹氏 外務省幹部の訪中受け「口だけ番長」へ痛烈指摘 「喧嘩は日本の完敗…なんとかっこ悪い日本か」 [冬月記者★]
- 中国で「クレしん」公開延期 対日報復、エンタメに波及 [蚤の市★]
- 【朗報】愛国烈士ほんこん、高市首相のために長文を投稿wwwwwwwwwwwww [834922174]
- 小池百合子「キィィ…!なんでアタシより先に総理になってンのよ…あの女狐ッ!」
- ニートしかいない時間ってマジでつまんないよな
- 有識者「高市総理が発言を撤回したり、辞職するしかないと言っている人は、それで日中関係が今まで通りになると思ってる?」 [834922174]
- 高市コイン、155円突破wwwwwwwwww [246620176]
- おじゃる丸をまったり待機するスレ🏡
