探検
結局C++とRustってどっちが良いの?
■ このスレッドは過去ログ倉庫に格納されています
1デフォルトの名無しさん
2023/02/25(土) 09:49:46.74ID:VRyB88xR C++の色々配慮してめんどくさい感じは好きだけど、実務になったらメモリ安全性とか考えて今後Rustに変わっていくんかな?
701デフォルトの名無しさん
2023/03/29(水) 12:42:03.29ID:KmrCY6Bh そもそもBarはFooを継承してないんだから
ダウンキャストのところでコンパイルエラー出て良いようなもんだけど
何で通すんだろ? templateだとチェックを緩和してるのかな?
あるいはコンパイラのバグかな?
$ g++ --version
g++ (Debian 10.2.1-6) 10.2.1 20210110
ダウンキャストのところでコンパイルエラー出て良いようなもんだけど
何で通すんだろ? templateだとチェックを緩和してるのかな?
あるいはコンパイラのバグかな?
$ g++ --version
g++ (Debian 10.2.1-6) 10.2.1 20210110
702デフォルトの名無しさん
2023/03/29(水) 12:43:14.11ID:KmrCY6Bh -ダウンキャストのところでコンパイルエラー出て良いようなもんだけど
+static_cast<T*>(this)->add1();のところでコンパイルエラー出て良いようなもんだけど
+static_cast<T*>(this)->add1();のところでコンパイルエラー出て良いようなもんだけど
703デフォルトの名無しさん
2023/03/29(水) 12:55:36.31ID:jlgG+N1i 最近のC++はよく分からんけどその例だとadd2使わないと多分変なことにならない
doubleをint扱いして1足しても1/(2^53)(←不正確、指数部による)くらいしか変動しないのかな
FooもBarもAddN継承してるからstatic_castでコンパイルエラーは出ないはず
Rustはクラス継承がないからstatic_castとの正確な比較はできない
traitで似たようなコード書くときはSelfキーワードで自分の型を指すからダウンキャスト必要ないし
敢えてstatic_castと対応させるならtransmuteだろうけどunsafe付きの関数だから危険でもコンパイルは通せる
(unsafeを使う範囲の安全性保証はプログラマの責任)
doubleをint扱いして1足しても1/(2^53)(←不正確、指数部による)くらいしか変動しないのかな
FooもBarもAddN継承してるからstatic_castでコンパイルエラーは出ないはず
Rustはクラス継承がないからstatic_castとの正確な比較はできない
traitで似たようなコード書くときはSelfキーワードで自分の型を指すからダウンキャスト必要ないし
敢えてstatic_castと対応させるならtransmuteだろうけどunsafe付きの関数だから危険でもコンパイルは通せる
(unsafeを使う範囲の安全性保証はプログラマの責任)
704デフォルトの名無しさん
2023/03/29(水) 13:10:19.46ID:KmrCY6Bh >>703
>最近のC++はよく分からんけどその例だとadd2使わないと多分変なことにならない
あーごめんごめん!興味があったのはadd2を呼んだときの挙動だった
- foo.add1 (); bar.add1 ();
+ foo.add2 (); bar.add2 ();
$ ./test
foo.x: 1
bar.y: 0.1
foo.x: 3
bar.y: 0.1 <- 鼻から悪魔
>FooもBarもAddN継承してるからstatic_castでコンパイルエラーは出ないはず
なるほどキャストしているthisはAddN<Foo>*だから
Foo*にもBar*にもダウンキャストできるってことね
ありがとう
>最近のC++はよく分からんけどその例だとadd2使わないと多分変なことにならない
あーごめんごめん!興味があったのはadd2を呼んだときの挙動だった
- foo.add1 (); bar.add1 ();
+ foo.add2 (); bar.add2 ();
$ ./test
foo.x: 1
bar.y: 0.1
foo.x: 3
bar.y: 0.1 <- 鼻から悪魔
>FooもBarもAddN継承してるからstatic_castでコンパイルエラーは出ないはず
なるほどキャストしているthisはAddN<Foo>*だから
Foo*にもBar*にもダウンキャストできるってことね
ありがとう
705デフォルトの名無しさん
2023/03/29(水) 13:47:10.36ID:KmrCY6Bh 正当?なC++的にはdynamic_castすべきなんじゃなかろうかって思うんだよね
でそれはvtable介してadd1にアクセスするのと変わらない
プログラマの責任でstatic_castして効率化する
ってテクニックは俺は割と好きだけども
でそれはvtable介してadd1にアクセスするのと変わらない
プログラマの責任でstatic_castして効率化する
ってテクニックは俺は割と好きだけども
706デフォルトの名無しさん
2023/03/29(水) 14:18:14.91ID:JN59fMMe >>703
transmuteはダウンキャストではなく任意の型同士の強引な型変換(読み替え)だから当然unsafe
一方でダウンキャストは親から子、基底から派生、抽象から具体への変換を指す
Rustの場合は抽象的なトレイトから具体的な型への変換がダウンキャストとなる
Rustは基本的には静的ポリモーフィズムで
コンパイル時点で各具体的な型のコードへ安全に置き換わるモノモーフィズムなので
C++のstatic_castのような危険のあるダウンキャストを必要としないが正解
Rustでもdyn Traitを用いた場合のみ動的ポリモーフィズムとなり
C++のdynamic_castと同様に実行時ダウンキャストがdowncast()/downcast_ref()/downcast_mut()で可能だが
C++とは異なりRustはNull安全でダウンキャストできる
transmuteはダウンキャストではなく任意の型同士の強引な型変換(読み替え)だから当然unsafe
一方でダウンキャストは親から子、基底から派生、抽象から具体への変換を指す
Rustの場合は抽象的なトレイトから具体的な型への変換がダウンキャストとなる
Rustは基本的には静的ポリモーフィズムで
コンパイル時点で各具体的な型のコードへ安全に置き換わるモノモーフィズムなので
C++のstatic_castのような危険のあるダウンキャストを必要としないが正解
Rustでもdyn Traitを用いた場合のみ動的ポリモーフィズムとなり
C++のdynamic_castと同様に実行時ダウンキャストがdowncast()/downcast_ref()/downcast_mut()で可能だが
C++とは異なりRustはNull安全でダウンキャストできる
707デフォルトの名無しさん
2023/03/29(水) 14:59:38.14ID:hbkToQM4 そこは、わずかにコストを支払って、reinterpret_castでもいいとは思うけどね
708デフォルトの名無しさん
2023/03/29(水) 15:00:17.60ID:hbkToQM4 ああちがう、reinterpret_castを避ける、だ
709デフォルトの名無しさん
2023/03/29(水) 15:30:35.32ID:jlgG+N1i 動的検査のコストよりもキャストに失敗した時の分岐処理のせいで最適化が阻害されるのを問題視してる感じ
かといって分岐しないなら動的検査の意味ないし
かといって分岐しないなら動的検査の意味ないし
710デフォルトの名無しさん
2023/03/29(水) 15:35:36.31ID:jd4hHaC+711デフォルトの名無しさん
2023/03/29(水) 15:40:07.88ID:R/bWJVR7 Rustのポインタ(参照)のNull安全ってすごく上手い仕組みだな
C++のdynamic_castもRustのdowncast_refも生成コードはどちらもダウンキャスト成功時はそのままポインタを返して失敗時は0を返す点で効率も同じだけど
Rustでは返す型としてはそれをポインタで直接に表さずにOption<&T>を返すと表現させて
成功時はOption::Some(&T)を返して失敗時の0はOption::Noneとして返すため
プログラムコード上はNoneかSomeか生成コードでは0か否かをチェックせずには使えないわけだ
C++でのNullポインタか否かのチェック忘れを静的な型チェックで防止できるってことは
もしかしてC++でもdynamic_castやその他のNullポインタを返すライブラリ全てをstd::optionalを返すように変更すればNull安全になるんじゃないか?
C++のdynamic_castもRustのdowncast_refも生成コードはどちらもダウンキャスト成功時はそのままポインタを返して失敗時は0を返す点で効率も同じだけど
Rustでは返す型としてはそれをポインタで直接に表さずにOption<&T>を返すと表現させて
成功時はOption::Some(&T)を返して失敗時の0はOption::Noneとして返すため
プログラムコード上はNoneかSomeか生成コードでは0か否かをチェックせずには使えないわけだ
C++でのNullポインタか否かのチェック忘れを静的な型チェックで防止できるってことは
もしかしてC++でもdynamic_castやその他のNullポインタを返すライブラリ全てをstd::optionalを返すように変更すればNull安全になるんじゃないか?
712デフォルトの名無しさん
2023/03/29(水) 15:45:49.19ID:RttupHdJ713デフォルトの名無しさん
2023/03/29(水) 17:50:54.05ID:aWl/4JyA714デフォルトの名無しさん
2023/03/29(水) 18:18:44.67ID:eKurmGUm たぶん人違いじゃないかな?
dynamic_castの返り値を確認しないやつは
流石におらんと思うよ
静的に確認してくれても全く嬉しくない
dynamic_castの返り値を確認しないやつは
流石におらんと思うよ
静的に確認してくれても全く嬉しくない
715デフォルトの名無しさん
2023/03/29(水) 18:19:38.85ID:eKurmGUm 訂正
静的に確認を強制されても嬉しくない
静的に確認を強制されても嬉しくない
716デフォルトの名無しさん
2023/03/29(水) 18:50:51.61ID:3DtieHtv ヌルポインタが返る全ての関数についてそうしないとヌル安全にならない
ヌルを使ってはダメ
ヌルを使ってはダメ
717デフォルトの名無しさん
2023/03/29(水) 19:05:30.65ID:KmrCY6Bh それは当然だよ
C++では指し示した先にインスタンスがあるかどうか
分からんときにのみポインタを使う
確実にあるときは参照を使うのが流儀
ポインタが使われるところではnullptrのチェックを行う
この流儀の部分を守らないスカタンが問題なんだな
Cに参照がないので上記流儀が守られないことも問題
C++では指し示した先にインスタンスがあるかどうか
分からんときにのみポインタを使う
確実にあるときは参照を使うのが流儀
ポインタが使われるところではnullptrのチェックを行う
この流儀の部分を守らないスカタンが問題なんだな
Cに参照がないので上記流儀が守られないことも問題
718デフォルトの名無しさん
2023/03/29(水) 19:30:08.82ID:ap6Xt56V719デフォルトの名無しさん
2023/03/29(水) 19:36:28.24ID:KmrCY6Bh >>718
BarはAddN<Bar>ではなくAddN<Foo>を継承しているから
BarはAddN<Bar>ではなくAddN<Foo>を継承しているから
720デフォルトの名無しさん
2023/03/29(水) 19:41:07.31ID:ap6Xt56V721デフォルトの名無しさん
2023/03/29(水) 19:53:07.69ID:KmrCY6Bh templateを展開すると
void Add <Foo>::add2() {
static_cast<Foo*>(this)->add1();
static_cast<Foo*>(this)->add1();
}
thisはBarの基底AddN<Foo>*のポインタ
これをBarと無関係のFoo*にキャストしたら動作は不定
void Add <Foo>::add2() {
static_cast<Foo*>(this)->add1();
static_cast<Foo*>(this)->add1();
}
thisはBarの基底AddN<Foo>*のポインタ
これをBarと無関係のFoo*にキャストしたら動作は不定
722デフォルトの名無しさん
2023/03/29(水) 20:09:37.10ID:ap6Xt56V なるほど
浮動小数点に対してそれを整数と見て+2してしまっているのかな
本来はコンパイル段階でエラーにしないとやばそうだ
今回はっきり動いていないとわかるケースだからいいけど何となく動いてしまってるケースがあると恐ろしい
浮動小数点に対してそれを整数と見て+2してしまっているのかな
本来はコンパイル段階でエラーにしないとやばそうだ
今回はっきり動いていないとわかるケースだからいいけど何となく動いてしまってるケースがあると恐ろしい
723デフォルトの名無しさん
2023/03/29(水) 20:11:29.28ID:KmrCY6Bh 正当?なC++的にはdynamic_castすべきだと思うんだよね
template<typename T> struct AddN {
void add2() {
dynamic_cast<T&>(*this).add1();
dynamic_cast<T&>(*this).add1();
}
virtual ~AddN () {};
};
template<typename T> struct AddN {
void add2() {
dynamic_cast<T&>(*this).add1();
dynamic_cast<T&>(*this).add1();
}
virtual ~AddN () {};
};
724デフォルトの名無しさん
2023/03/29(水) 20:13:55.05ID:AtW1ukjc 静的に一意に決まるんならいいのでは
725デフォルトの名無しさん
2023/03/29(水) 20:29:34.23ID:KmrCY6Bh 俺は割と好きだけどもね
726デフォルトの名無しさん
2023/03/29(水) 20:42:15.15ID:rGt9yURA C++最適化効きすぎてadd2そのものが展開されて最短コードにしかならん
727デフォルトの名無しさん
2023/03/29(水) 20:50:49.78ID:ij9aGzzi doubleのビット列をintとして扱ってインクリメントしてるから結果がおかしいんだろ
なぜコンパイラは型不一致エラーを出せないんだ?
なぜコンパイラは型不一致エラーを出せないんだ?
728デフォルトの名無しさん
2023/03/29(水) 21:21:00.23ID:iEVzPlea 問題があれば何でもコンパイル時点でエラーを出してくれるRustを使おう
実行デバッグが激減して開発効率も高い
実行デバッグが激減して開発効率も高い
729デフォルトの名無しさん
2023/03/29(水) 21:39:38.92ID:KmrCY6Bh でもunsafeないとダメなんでしょ?
730デフォルトの名無しさん
2023/03/29(水) 22:02:01.80ID:iEVzPlea 普通のプログラムでunsafeは出てこない
731デフォルトの名無しさん
2023/03/29(水) 23:01:50.75ID:UIOCT5jB ライブラリが一個もない状態から基本的なライブラリを作るためにunsafeが必要という話だったら
有限個のバイナリファイルが正しく出力されればいいだけなので
ソースコードをチェックしなくても出力をチェックすればいいのでは?
有限個のバイナリファイルが正しく出力されればいいだけなので
ソースコードをチェックしなくても出力をチェックすればいいのでは?
732デフォルトの名無しさん
2023/03/30(木) 06:54:28.38ID:xjlzONIR733デフォルトの名無しさん
2023/03/30(木) 06:54:54.18ID:uZvbGS3c そういえばJavaが全然話題にもならないが言語のヒエラルキーって
C++ 最強カミソリ
剃り残しナシ
Rust 安全カミソリ
キレテナーィ なまくら
C# イケてるが
GCがあるからダメぽ
Java 論外
ヌルポとGCがあるからダメぽ
こんな感じ?
C++ 最強カミソリ
剃り残しナシ
Rust 安全カミソリ
キレテナーィ なまくら
C# イケてるが
GCがあるからダメぽ
Java 論外
ヌルポとGCがあるからダメぽ
こんな感じ?
734デフォルトの名無しさん
2023/03/30(木) 07:08:43.78ID:xjlzONIR 一つ間違うと自分の手とか余計なところまで切れちゃうw
735デフォルトの名無しさん
2023/03/30(木) 07:25:50.11ID:xjlzONIR 俺にとってのC++は、日本語だよ 物心ついたときには、C++だったんだ
氏ぬまで忘れないと思う だからある意味最強、そんな奴が結構多いんだと思う
「ちゃんと話せ」って躾けられたのも、良し悪し
氏ぬまで忘れないと思う だからある意味最強、そんな奴が結構多いんだと思う
「ちゃんと話せ」って躾けられたのも、良し悪し
736デフォルトの名無しさん
2023/03/30(木) 07:29:05.38ID:Lly0YXlC737デフォルトの名無しさん
2023/03/30(木) 07:42:11.73ID:w91B/KcY C++が出来なくてRustが出来ることってある?
738デフォルトの名無しさん
2023/03/30(木) 07:43:46.76ID:xjlzONIR 縛りプレイ
739デフォルトの名無しさん
2023/03/30(木) 08:01:00.44ID:Lly0YXlC740デフォルトの名無しさん
2023/03/30(木) 08:18:36.82ID:PJ70lfxq プリミティブはいろいろ備わってるから、やってできなくはないんだろうけど、
強制する方法がないから、ちっとも普及しないんだよね
強制する方法がないから、ちっとも普及しないんだよね
741デフォルトの名無しさん
2023/03/30(木) 08:28:14.61ID:Lly0YXlC >>740
C++はそのプリミティブを多数欠いている
まさか代数的データ型をunionで頑張ればできると主張するのか?
パターンマッチングは構文だからC++には無理
データ競合を静的に検知する方法もない
C++はそのプリミティブを多数欠いている
まさか代数的データ型をunionで頑張ればできると主張するのか?
パターンマッチングは構文だからC++には無理
データ競合を静的に検知する方法もない
742デフォルトの名無しさん
2023/03/30(木) 08:32:28.84ID:PJ70lfxq C/C++には昔から、「なければgenerateすればいいじゃん」っていう文化がある
パターンマッチングは、いまどきIDEが記述支援するんだから、やってできなくはない
データ競合やらは、「そういう」スマポを導入すればいい
でもね、みんな使わないんだわ 使われないものは、ないものとして詰られても仕方ない
あ、Cとおんなじように、入れ子になった構造体をささっと書きたいとかは思うね
もうできるようになったっけ?
パターンマッチングは、いまどきIDEが記述支援するんだから、やってできなくはない
データ競合やらは、「そういう」スマポを導入すればいい
でもね、みんな使わないんだわ 使われないものは、ないものとして詰られても仕方ない
あ、Cとおんなじように、入れ子になった構造体をささっと書きたいとかは思うね
もうできるようになったっけ?
743デフォルトの名無しさん
2023/03/30(木) 08:35:47.70ID:2ioUidZk Rustのマクロって結構凄くね?
744デフォルトの名無しさん
2023/03/30(木) 09:18:55.32ID:PJ70lfxq …いやまてよ、パターンマッチングって、エラー等検出のことだと思ってたけど、
パターンマッチング Rust でぐぐったら全然違うものが出てきたぜ その節は撤回 ちょっと読んでみる
パターンマッチング Rust でぐぐったら全然違うものが出てきたぜ その節は撤回 ちょっと読んでみる
745デフォルトの名無しさん
2023/03/30(木) 10:37:10.30ID:z+Rtq9PG r
746デフォルトの名無しさん
2023/03/30(木) 10:45:06.95ID:7YA3tv0i std::visitはパターンマッチに含まれますか
747デフォルトの名無しさん
2023/03/30(木) 10:56:39.82ID:7YA3tv0i こういうのね
提案段階の機能を除けば一番直和型を直接的に表現できていると思う
https://www.modernescpp.com/index.php/visiting-a-std-variant-with-the-overload-pattern
提案段階の機能を除けば一番直和型を直接的に表現できていると思う
https://www.modernescpp.com/index.php/visiting-a-std-variant-with-the-overload-pattern
748デフォルトの名無しさん
2023/03/30(木) 10:58:13.17ID:xP+9HiJo パターンマッチングはC++23に入れようとしたがRustと比べて機能も弱すぎて失敗している
Rustのパターンマッチングはこんな感じで記述性や可読性を向上させている
fn slice_pattern(slice: &[(i32, i32)]) {
match slice {
[] => println!("空です"),
[(a, b)] => println!("要素は1つで({a},{b})です"),
[_, (123, b), ..] => println!("2つ目の前者が123なものは(123,{b})です"),
[.., next_last, _] => println!("その他の最後から2つ目の要素は{next_last:?}です"),
}
}
fn enum_pattern(shape: Shape) {
match shape {
Shape::Circle(r) => println!("半径{r}の円です"),
Shape::Rectangle(w, h) if w == h => println!("長さ{w}の正方形です"),
Shape::Rectangle(w, h) => println!("幅{w}高さ{h}の長方形です"),
x => println!("その他の図形{x:?}です"),
}
}
fn struct_pattern() {
let a = Foo { bar: 123, baz: 456, qux: 789 };
let b = Foo { baz: 555, ..a };
for Foo { bar, baz, qux } in &[a, b] {
println!("Foo: bar={bar}, baz={baz}, qux={qux}");
}
}
fn range_pattern(c: char) {
match c {
'0'..='9' => println!("数字({c})です"),
'a'..='z' | 'A'..='Z' => println!("アルファベット({c})です"),
_ => println!("その他の文字({c})です"),
}
}
Rustのパターンマッチングはこんな感じで記述性や可読性を向上させている
fn slice_pattern(slice: &[(i32, i32)]) {
match slice {
[] => println!("空です"),
[(a, b)] => println!("要素は1つで({a},{b})です"),
[_, (123, b), ..] => println!("2つ目の前者が123なものは(123,{b})です"),
[.., next_last, _] => println!("その他の最後から2つ目の要素は{next_last:?}です"),
}
}
fn enum_pattern(shape: Shape) {
match shape {
Shape::Circle(r) => println!("半径{r}の円です"),
Shape::Rectangle(w, h) if w == h => println!("長さ{w}の正方形です"),
Shape::Rectangle(w, h) => println!("幅{w}高さ{h}の長方形です"),
x => println!("その他の図形{x:?}です"),
}
}
fn struct_pattern() {
let a = Foo { bar: 123, baz: 456, qux: 789 };
let b = Foo { baz: 555, ..a };
for Foo { bar, baz, qux } in &[a, b] {
println!("Foo: bar={bar}, baz={baz}, qux={qux}");
}
}
fn range_pattern(c: char) {
match c {
'0'..='9' => println!("数字({c})です"),
'a'..='z' | 'A'..='Z' => println!("アルファベット({c})です"),
_ => println!("その他の文字({c})です"),
}
}
749デフォルトの名無しさん
2023/03/30(木) 11:05:35.09ID:wHEiYRW7 C++はユーザが多いので標準でなくてもライブラリがあるからね
Rustはユーザが少ないので標準で用意しとく必要がある
パタンマッチングは言語の話だけども
Rustはユーザが少ないので標準で用意しとく必要がある
パタンマッチングは言語の話だけども
750デフォルトの名無しさん
2023/03/30(木) 11:06:04.96ID:dh4KEwq/ Rust の TcpListener のサンプルについて質問です
1ページ目は無料で1ページ目だけで動作するはずですが
https://xtech.nikkei.com/atcl/nxt/column/18/01920/081600022/
何故か1byteしか受け取らず常に 404 NotFound になります
何処を治せばよいですか?
1ページ目は無料で1ページ目だけで動作するはずですが
https://xtech.nikkei.com/atcl/nxt/column/18/01920/081600022/
何故か1byteしか受け取らず常に 404 NotFound になります
何処を治せばよいですか?
751デフォルトの名無しさん
2023/03/30(木) 11:14:15.70ID:xP+9HiJo752デフォルトの名無しさん
2023/03/30(木) 11:14:43.48ID:PJ70lfxq 一発目から GET / HTTP/1.1 じゃないものが来てるかもよ、buffer 表示させてみては
753デフォルトの名無しさん
2023/03/30(木) 11:28:11.87ID:7YA3tv0i >>751
記事読んだ?
記事読んだ?
754デフォルトの名無しさん
2023/03/30(木) 11:32:57.91ID:xP+9HiJo755デフォルトの名無しさん
2023/03/30(木) 11:39:46.03ID:PJ70lfxq パターンマッチングの件、5分くらい読んできた
そういう風に書きたいっていうニーズがあるんだな、表現力を誇るC++でこれが書けないのは確かに手落ちw
この型はあれでもこれでもあるっていうの、あんまり扱ってこなかったけど、
上手く書けば便利になるかもね ただし、ゼロサンクでね
そういう風に書きたいっていうニーズがあるんだな、表現力を誇るC++でこれが書けないのは確かに手落ちw
この型はあれでもこれでもあるっていうの、あんまり扱ってこなかったけど、
上手く書けば便利になるかもね ただし、ゼロサンクでね
756デフォルトの名無しさん
2023/03/30(木) 11:39:46.85ID:xP+9HiJo >>750
そのRustのTcpListenerのサンプル動かしてみたけど普通に動いた
返すindex.htmlを用意してcargo run
ブラウザからhttp://localhost:9999/で表示された
そのRustのTcpListenerのサンプル動かしてみたけど普通に動いた
返すindex.htmlを用意してcargo run
ブラウザからhttp://localhost:9999/で表示された
757デフォルトの名無しさん
2023/03/30(木) 11:46:33.32ID:7YA3tv0i758デフォルトの名無しさん
2023/03/30(木) 11:47:15.19ID:xP+9HiJo759デフォルトの名無しさん
2023/03/30(木) 11:49:39.34ID:xP+9HiJo760デフォルトの名無しさん
2023/03/30(木) 11:58:04.66ID:7YA3tv0i761デフォルトの名無しさん
2023/03/30(木) 11:58:20.56ID:PJ70lfxq 教科書的サンプルとは別に、実践的なサンプルが見たいぞ
必要だから入った仕様だろう、手ごろにどっかあるはずだ お勧めのやつをたのむ
必要だから入った仕様だろう、手ごろにどっかあるはずだ お勧めのやつをたのむ
762デフォルトの名無しさん
2023/03/30(木) 11:59:10.65ID:wHEiYRW7 >>751
>>749>パタンマッチングは言語の話だけども
>例えば>>748のShapeの定義例は
>enum Shape {
> Circle(u32),
> Rectangle(u32, u32),
> Parallelogram(u32, u32),
>}
>これだけで済む
>さらに型Shapeに対して様々なメソッドを実装できる
>C++ではそれぞれ困難と不可能
横レスだけども
namespace Shape {
struct Circle {uint32_t r;};
struct Rectangle {uint32_t w; uint32_t h;};
struct Parallelogram {uint32_t ui0; uint32_t ui1;};
template <typename T> void function (ostream &os, const T &p);
void function (ostream &os, const Circle &p);
void function (ostream &os, const Rectangle &p);
// void function (ostream &os, const Parallelogram &p);
}
>>749>パタンマッチングは言語の話だけども
>例えば>>748のShapeの定義例は
>enum Shape {
> Circle(u32),
> Rectangle(u32, u32),
> Parallelogram(u32, u32),
>}
>これだけで済む
>さらに型Shapeに対して様々なメソッドを実装できる
>C++ではそれぞれ困難と不可能
横レスだけども
namespace Shape {
struct Circle {uint32_t r;};
struct Rectangle {uint32_t w; uint32_t h;};
struct Parallelogram {uint32_t ui0; uint32_t ui1;};
template <typename T> void function (ostream &os, const T &p);
void function (ostream &os, const Circle &p);
void function (ostream &os, const Rectangle &p);
// void function (ostream &os, const Parallelogram &p);
}
763デフォルトの名無しさん
2023/03/30(木) 12:23:51.98ID:8gDdaVz7 >>762
それだとShapeが型ではなく名前空間になってしまってるからダメでしょ
それだとShapeが型ではなく名前空間になってしまってるからダメでしょ
764デフォルトの名無しさん
2023/03/30(木) 12:29:16.05ID:wHEiYRW7 >>763
namespaceをstructに置換して最後に;つければ?
namespaceをstructに置換して最後に;つければ?
765デフォルトの名無しさん
2023/03/30(木) 12:32:22.56ID:8gDdaVz7 >>764
それだと全ての図形で必要となるメモリサイズの合計サイズが必要になっちゃうよ
それだと全ての図形で必要となるメモリサイズの合計サイズが必要になっちゃうよ
766デフォルトの名無しさん
2023/03/30(木) 12:32:39.23ID:wHEiYRW7 関数はstaticにする
767デフォルトの名無しさん
2023/03/30(木) 12:34:53.74ID:wHEiYRW7 >>765
何か問題でも?
何か問題でも?
768デフォルトの名無しさん
2023/03/30(木) 12:35:39.04ID:7YA3tv0i >>765
メンバ型定義しただけではメンバ変数は増えないから、サイズも増えないよ
メンバ型定義しただけではメンバ変数は増えないから、サイズも増えないよ
769デフォルトの名無しさん
2023/03/30(木) 12:35:54.76ID:wHEiYRW7770デフォルトの名無しさん
2023/03/30(木) 12:47:49.82ID:xP+9HiJo771デフォルトの名無しさん
2023/03/30(木) 12:56:56.84ID:wHEiYRW7 パターンマッチングは便利だけども必須じゃないよね
所有権システムと違って後方互換性が犠牲になることはないので
そのうちC++に入るよ
所有権システムと違って後方互換性が犠牲になることはないので
そのうちC++に入るよ
772デフォルトの名無しさん
2023/03/30(木) 13:16:45.82ID:tVTq+AM2 >>769
パターンマッチング>>748の2番目の例の話だからShapeは関数に渡ってくる型じゃないとまずい
単体で動くコードで比較すればはっきりすると思うのでC++版を書いて。以下はRust版
// ここは再掲
fn enum_pattern(shape: Shape) {
match shape {
Shape::Circle(r) => println!("半径{r}の円です"),
Shape::Rectangle(w, h) if w == h => println!("長さ{w}の正方形です"),
Shape::Rectangle(w, h) => println!("幅{w}高さ{h}の長方形です"),
x => println!("その他の図形{x:?}です"),
}
}
#[derive(Debug)]
enum Shape {
Circle(u32),
Rectangle(u32, u32),
Parallelogram(u32, u32),
}
fn main() {
enum_pattern(Shape::Circle(100));
enum_pattern(Shape::Rectangle(200, 300));
enum_pattern(Shape::Rectangle(567, 567));
enum_pattern(Shape::Parallelogram(789, 456));
}
// 実行結果
半径100の円です
幅200高さ300の長方形です
長さ567の正方形です
その他の図形Parallelogram(789, 456)です
パターンマッチング>>748の2番目の例の話だからShapeは関数に渡ってくる型じゃないとまずい
単体で動くコードで比較すればはっきりすると思うのでC++版を書いて。以下はRust版
// ここは再掲
fn enum_pattern(shape: Shape) {
match shape {
Shape::Circle(r) => println!("半径{r}の円です"),
Shape::Rectangle(w, h) if w == h => println!("長さ{w}の正方形です"),
Shape::Rectangle(w, h) => println!("幅{w}高さ{h}の長方形です"),
x => println!("その他の図形{x:?}です"),
}
}
#[derive(Debug)]
enum Shape {
Circle(u32),
Rectangle(u32, u32),
Parallelogram(u32, u32),
}
fn main() {
enum_pattern(Shape::Circle(100));
enum_pattern(Shape::Rectangle(200, 300));
enum_pattern(Shape::Rectangle(567, 567));
enum_pattern(Shape::Parallelogram(789, 456));
}
// 実行結果
半径100の円です
幅200高さ300の長方形です
長さ567の正方形です
その他の図形Parallelogram(789, 456)です
773デフォルトの名無しさん
2023/03/30(木) 13:28:40.22ID:wHEiYRW7774デフォルトの名無しさん
2023/03/30(木) 13:31:04.03ID:wHEiYRW7775デフォルトの名無しさん
2023/03/30(木) 13:31:12.50ID:tVTq+AM2776デフォルトの名無しさん
2023/03/30(木) 13:32:51.26ID:wHEiYRW7777デフォルトの名無しさん
2023/03/30(木) 13:35:28.76ID:wHEiYRW7 図形は典型的なオブジェクト指向の例題だから
enumを使う例としては適切ではないんじゃないかな?
Rustをよく知らん俺からしたらピンとこないよ
enumを使う例としては適切ではないんじゃないかな?
Rustをよく知らん俺からしたらピンとこないよ
778デフォルトの名無しさん
2023/03/30(木) 13:39:12.89ID:8gDdaVz7 >>774
ディスパッチは静的には不可能で動的にしか行われないでしょ
静的に可能なのはモノモーフィゼイションだけど今回の例では適用できませんね
いずれにしてもC++で可能だと言うコードを示してみたら?
ディスパッチは静的には不可能で動的にしか行われないでしょ
静的に可能なのはモノモーフィゼイションだけど今回の例では適用できませんね
いずれにしてもC++で可能だと言うコードを示してみたら?
779デフォルトの名無しさん
2023/03/30(木) 13:39:52.45ID:PJ70lfxq お、俺の>>761をだな。。
780デフォルトの名無しさん
2023/03/30(木) 13:41:01.47ID:wHEiYRW7781デフォルトの名無しさん
2023/03/30(木) 13:42:20.94ID:7YA3tv0i https://wandbox.org/permlink/Q94E20qAAS5G8iiX
std::variantとstd::visitでパターンマッチする例です
std::variantとstd::visitでパターンマッチする例です
782デフォルトの名無しさん
2023/03/30(木) 13:52:02.49ID:tVTq+AM2783デフォルトの名無しさん
2023/03/30(木) 14:01:06.19ID:7YA3tv0i >>782
enumのバリアント判定に相当するパターンマッチを行っていますので、全く行っていないという指摘は正しくありません
また、>>748のenum_patternにShape::Rectangle(100, h)にマッチするコードは含まれておらず、あなたの当初の要求に含まれていないものです
新しい要求を後から追加して批判するのは、誠実な態度とは言えません
このようなことが無いように、「何が無理か」を明確にするよう確認したつもりでした
今後はこうしたことが無いように、事前よく確認することをお願い申し上げます
また値によるマッチについてですが、同様の考えで似たライブラリを実装された方を見つけました
こちらは値によるマッチに拡張したライブラリを実装されているようです
https://qiita.com/Naotonosato/items/a1e710de2b78346146d1
enumのバリアント判定に相当するパターンマッチを行っていますので、全く行っていないという指摘は正しくありません
また、>>748のenum_patternにShape::Rectangle(100, h)にマッチするコードは含まれておらず、あなたの当初の要求に含まれていないものです
新しい要求を後から追加して批判するのは、誠実な態度とは言えません
このようなことが無いように、「何が無理か」を明確にするよう確認したつもりでした
今後はこうしたことが無いように、事前よく確認することをお願い申し上げます
また値によるマッチについてですが、同様の考えで似たライブラリを実装された方を見つけました
こちらは値によるマッチに拡張したライブラリを実装されているようです
https://qiita.com/Naotonosato/items/a1e710de2b78346146d1
784デフォルトの名無しさん
2023/03/30(木) 14:04:54.89ID:8gDdaVz7785デフォルトの名無しさん
2023/03/30(木) 14:14:54.28ID:wHEiYRW7 >>782
別に関数プロトタイプまで書いてるんだから分かりそうなものだけど...
以下は静的ディスパッチでコンパイル時に定まるよ
>>772が静的ディスパッチできないとしても
たぶん同じように書けばRustでも静的にディスパッチできると思うよ
#include <iostream>
using namespace std;
namespace Shape {
struct Circle {uint32_t r;};
struct Rectangle {uint32_t w; uint32_t h;};
struct Parallelogram {uint32_t ui0; uint32_t ui1;};
template <typename T> void function (ostream &os, const T &p) {}
void function (ostream &os, const Circle &p) {}
void function (ostream &os, const Rectangle &p) {}
}
int main () {
using namespace Shape;
Circle circle;
function (cout, circle);
Parallelogram parallelogram;
function (cout, parallelogram);
return 0;
}
別に関数プロトタイプまで書いてるんだから分かりそうなものだけど...
以下は静的ディスパッチでコンパイル時に定まるよ
>>772が静的ディスパッチできないとしても
たぶん同じように書けばRustでも静的にディスパッチできると思うよ
#include <iostream>
using namespace std;
namespace Shape {
struct Circle {uint32_t r;};
struct Rectangle {uint32_t w; uint32_t h;};
struct Parallelogram {uint32_t ui0; uint32_t ui1;};
template <typename T> void function (ostream &os, const T &p) {}
void function (ostream &os, const Circle &p) {}
void function (ostream &os, const Rectangle &p) {}
}
int main () {
using namespace Shape;
Circle circle;
function (cout, circle);
Parallelogram parallelogram;
function (cout, parallelogram);
return 0;
}
786デフォルトの名無しさん
2023/03/30(木) 14:47:32.70ID:Evbafc70 静的ではなくて動的ディスパッチだろ
このように次々と何が来るかわからないリストが渡ってきた場合
Shape::Shape shape_list[4];
shape_list[0] = Shape::Rectangle{w: 33, h: 33};
shape_list[1] = Shape::Parallelogram{ui0: 4, ui1: 33};
shape_list[2] = Shape::Rectangle{w: 33, h: 4};
shape_list[3] = Shape::Circle{10};
その時にこれで処理できるのだから動的ディスパッチをしている
for (int i = 0; i < 4; i++) {
enum_pattern(shape_list[i]);
}
このように次々と何が来るかわからないリストが渡ってきた場合
Shape::Shape shape_list[4];
shape_list[0] = Shape::Rectangle{w: 33, h: 33};
shape_list[1] = Shape::Parallelogram{ui0: 4, ui1: 33};
shape_list[2] = Shape::Rectangle{w: 33, h: 4};
shape_list[3] = Shape::Circle{10};
その時にこれで処理できるのだから動的ディスパッチをしている
for (int i = 0; i < 4; i++) {
enum_pattern(shape_list[i]);
}
787デフォルトの名無しさん
2023/03/30(木) 15:01:18.46ID:wHEiYRW7788デフォルトの名無しさん
2023/03/30(木) 15:04:41.33ID:PJ70lfxq もうちょっと調べてたが、C++にもinspectってのが来そうみたいじゃん
パタンマッチングって、こんなもんが流行ってるのね、また一つ取り残されてたぜ
パタンマッチングって、こんなもんが流行ってるのね、また一つ取り残されてたぜ
789デフォルトの名無しさん
2023/03/30(木) 15:04:46.89ID:7YA3tv0i >>786
いいえ、これは静的ディスパッチです
簡単に確認する方法として、生成されたアセンブリ中のvtableを確認する方法があります:
https://godbolt.org/z/1W7jGnWEd
"vtable for std::bad_variant_access:"が唯一のvtableであり、Circleなどのためのvtableはありません
このことから、動的ディスパッチは発生しないことが分かります
いいえ、これは静的ディスパッチです
簡単に確認する方法として、生成されたアセンブリ中のvtableを確認する方法があります:
https://godbolt.org/z/1W7jGnWEd
"vtable for std::bad_variant_access:"が唯一のvtableであり、Circleなどのためのvtableはありません
このことから、動的ディスパッチは発生しないことが分かります
790デフォルトの名無しさん
2023/03/30(木) 15:09:53.24ID:Evbafc70791デフォルトの名無しさん
2023/03/30(木) 15:10:42.88ID:wHEiYRW7792デフォルトの名無しさん
2023/03/30(木) 15:12:35.47ID:wHEiYRW7 >>790
それはRsutのコードか? C++のコードか?
それはRsutのコードか? C++のコードか?
793デフォルトの名無しさん
2023/03/30(木) 15:20:37.87ID:Evbafc70 >>792
そのC++コードの話しかしていない
そのC++コードの話しかしていない
794デフォルトの名無しさん
2023/03/30(木) 15:23:32.35ID:78T5MT6s795デフォルトの名無しさん
2023/03/30(木) 15:29:45.34ID:7YA3tv0i >>790
いいえ
動的ディスパッチとは、多態メソッドの呼び出し式を実行するときに、具体型に応じて実際に呼ばれる関数が振り分けられることを言います
https://en.wikipedia.org/wiki/Dynamic_dispatch
動的ディスパッチはしばしばパフォーマンスの低下をもたらすと言われますが、その最大の理由は、
選択される各関数ポインタを一度メモリから(vtableから)読み出し、それをcallする必要があることです
動的ディスパッチをどう定義するかはさておき、vtableが無い>>789ではこのパフォーマンス低下の懸念が無いことが分かります
また、「実行時にデータ内容に応じて分岐することを動的ディスパッチと言う」という定義には明らかな問題があります
それは、この定義ではmatchやifなど通常の制御構造も動的ディスパッチに当てはまってしまうということです
これは、この定義が一般的な定義から大きく逸脱していることをよく象徴的に表わしています
少なくとも「データ内容」は「型」に置き換える必要があることが分かるでしょう
いいえ
動的ディスパッチとは、多態メソッドの呼び出し式を実行するときに、具体型に応じて実際に呼ばれる関数が振り分けられることを言います
https://en.wikipedia.org/wiki/Dynamic_dispatch
動的ディスパッチはしばしばパフォーマンスの低下をもたらすと言われますが、その最大の理由は、
選択される各関数ポインタを一度メモリから(vtableから)読み出し、それをcallする必要があることです
動的ディスパッチをどう定義するかはさておき、vtableが無い>>789ではこのパフォーマンス低下の懸念が無いことが分かります
また、「実行時にデータ内容に応じて分岐することを動的ディスパッチと言う」という定義には明らかな問題があります
それは、この定義ではmatchやifなど通常の制御構造も動的ディスパッチに当てはまってしまうということです
これは、この定義が一般的な定義から大きく逸脱していることをよく象徴的に表わしています
少なくとも「データ内容」は「型」に置き換える必要があることが分かるでしょう
796デフォルトの名無しさん
2023/03/30(木) 15:38:08.65ID:RiLc+pIf797デフォルトの名無しさん
2023/03/30(木) 15:39:00.20ID:PJ70lfxq >>791
inspectは、godboltでclangのexperimentalを遊べるようになってた
型に対しては、もうちょっとまだみたい、error: expected expression って言われた
ラムダみたいに、みんなが欲しがるものはそれでもわりと早いんだよね
一応入れとくか…みたいのは、いつまでたっても入らないw
ところで、godboltに、-Wlifetime ってのがみえたけど…これってもしかして
inspectは、godboltでclangのexperimentalを遊べるようになってた
型に対しては、もうちょっとまだみたい、error: expected expression って言われた
ラムダみたいに、みんなが欲しがるものはそれでもわりと早いんだよね
一応入れとくか…みたいのは、いつまでたっても入らないw
ところで、godboltに、-Wlifetime ってのがみえたけど…これってもしかして
798デフォルトの名無しさん
2023/03/30(木) 15:59:56.98ID:QNJ4BihP C++の仕様を変えようという時に国語辞典の変更を許さないのはタイパ最悪だな
C++の仕様変更を許さない、とすれば秒速で終わる
C++の仕様変更を許さない、とすれば秒速で終わる
799デフォルトの名無しさん
2023/03/30(木) 16:08:41.30ID:7YA3tv0i800デフォルトの名無しさん
2023/03/30(木) 16:15:52.14ID:tFh1pq1g このスレレベル高いね。
文系の俺にはちんぷんかんぷん。
雑魚はPHPでもしてるわ。
文系の俺にはちんぷんかんぷん。
雑魚はPHPでもしてるわ。
801デフォルトの名無しさん
2023/03/30(木) 16:26:34.28ID:8gDdaVz7 Rustはそのへんの話も明瞭で
「dyn」という予約語キーワードが出てきたものだけがvtableを使う動的ディスパッチとなるよ
>>772のRustコードは「dyn」が全く出てこないので、vtableを使う動的ディスパッチは一切無し、とわかる仕組み
「dyn」という予約語キーワードが出てきたものだけがvtableを使う動的ディスパッチとなるよ
>>772のRustコードは「dyn」が全く出てこないので、vtableを使う動的ディスパッチは一切無し、とわかる仕組み
■ このスレッドは過去ログ倉庫に格納されています
ニュース
- 【おこめ】「有能だったんじゃ」おこめ券で批判殺到の鈴木農水大臣…ネットでは前任の“進次郎再評価” ★2 [ぐれ★]
- 「暖房が使えない」「食費が高くて子どもの栄養が…」 物価高に苦しむ子育て世帯、政府に期待する支援は ★2 [蚤の市★]
- オイルマッサージ施術中20代女性にわいせつ行為か セラピストの男(30)を再逮捕 余罪複数とみて警視庁が捜査 [どどん★]
- 内閣支持、微減59.9% 5割超が補正予算評価 時事通信世論調査 [どどん★]
- 【中国外務省】日本への渡航自粛を再度呼びかけ 今度は「地震発生」を理由に [ぐれ★]
- 日本語が話せない「外国籍」の子が急増中、授業がストップ、教室から脱走も…先生にも大きな負担「日本語支援」追いつかず★3 [七波羅探題★]
- 高市内閣の支持率、下落wwwwwwwwwww [834922174]
- Vtuber「人気アニメとコラボします!」←これでVが叩かれるの謎じゃね
- Xでフォローしてきた人をフォロバして相手のフォロー解除するのが趣味なんだが
- 愛国者「徴兵されるのは嫌。でも敵が侵略してきたら考えます」 [834922174]
- (´・ω・`)おみゃんりゃ〜
- 【悲報】日中戦争5割が賛成、高市キッズたち徴兵へ [834922174]
