結局C++とRustってどっちが良いの?

■ このスレッドは過去ログ倉庫に格納されています
1デフォルトの名無しさん
垢版 |
2023/02/25(土) 09:49:46.74ID:VRyB88xR
C++の色々配慮してめんどくさい感じは好きだけど、実務になったらメモリ安全性とか考えて今後Rustに変わっていくんかな?
2023/03/28(火) 07:15:22.07ID:qh0NVSBO
>>663
それはPythonでもJavaScriptでも同じ
Web APIと関係なくプログラム独自の部分も自分でどんどんクラスを編み出して問題解決する
他を知らないためC++だけを何か特別だと思い込んでそうだな
2023/03/28(火) 07:20:37.19ID:uty8q6BB
>>659 をちょっとだけ擁護してみたくなっただけだよw
どこだって、ライブラリ作成者はOOPに精通してるもんだが、
C++は、OOPに精通してないと、使ってますとか公言できないもんね
むっちゃ煽られるよw その違いはあるなって思った
2023/03/28(火) 07:41:04.68ID:qh0NVSBO
OOPは精通するしないとか難しいものではないだろ
初心者かね
2023/03/28(火) 07:49:36.20ID:uty8q6BB
C++でOOPができるといったら、当然のようにSTLが使え、boostが使える
あるいは、traitsやattribute,constexpr を織り交ぜて、ほぼゼロサンクなバイナリを叩き出せるレベル
俺は初心者だからそのレベルにはないな

ちょっとよそよりは要求レベルは高いだろって思ってる
母語のことはちょっとだけ誇りに思ってるけど、それより、一長一短的立場
2023/03/28(火) 08:58:26.51ID:C7yLEzi8
上のほうでだれかいってたけど、まともなC++erは、スマポくらい使えて当然
なんだけど…ソース単位で生ポ禁止ってのが普及しないんだよね
2023/03/28(火) 09:04:22.01ID:u9f8RzdU
newを書かなきゃ良いだけなのにね
670デフォルトの名無しさん
垢版 |
2023/03/28(火) 09:37:27.95ID:fedCMYV9
>>661
嫌だからわかってないんだってばこいつはさ
だからC++の依存関係で頭パンクすんだよ
671デフォルトの名無しさん
垢版 |
2023/03/28(火) 09:39:21.00ID:fedCMYV9
とりあえず
>>641
こいつがオブジェクト指向理解してないのは確かだろ
672デフォルトの名無しさん
垢版 |
2023/03/28(火) 09:56:21.67ID:cZnvlJgt
>>661
君がオブジェクト指向理解できてなさそう
2023/03/28(火) 10:06:33.49ID:C7yLEzi8
>>669
C++も なんでもスタックに置きたいんだけど、きつきつなのが本来なんだよね
どんどんスタックを食うのは野暮っていう流儀もある

Rust流はメモリ使用の局所化を促進するから、
メモリキャッシュまで考慮すると、悔しいけどC++より効率出る余地がある
まあ実測してみないと、知らんけどw
674デフォルトの名無しさん
垢版 |
2023/03/28(火) 10:06:36.56ID:vBvHBfxi
>どんどんクラスを編み出して問題解決する
奴はクラスを書けたらオブジェクト指向を理解してると思ってるみたいだからな
675デフォルトの名無しさん
垢版 |
2023/03/28(火) 10:09:59.68ID:fedCMYV9
>>674
確かになw
普通逆で一番抽象化できるところで遡ってツリー形式にやっていくもんだもんな
2023/03/28(火) 10:28:38.80ID:u9f8RzdU
>>673
「newを書かなきゃ」ってのは
make_uniqueとmake_sharedを使えって意味でした
2023/03/28(火) 10:51:13.90ID:P0df9Gxx
JavaScriptとPythonは
極力オブジェクト指向的な書き方をしないほうが
メンテナンス性も可読性も高まる言語だから
C++やC#とは事情が違うわな
2023/03/28(火) 17:06:18.21ID:aUMSgZvE
>>662
CRTPはC++のOOPで最も効率よい実装となり必須なテクニックであるが
美しいというのはウソでむしろC++の汚さの象徴の一つになっている

初心者や他言語の人たちもいるようだからわかりやすいコード
例として各派生のadd1()を用いて共通のadd2()やadd3()などを用意する場合

template<typename T>
struct AddN {
void add2() {
static_cast<T*>(this)->add1();
static_cast<T*>(this)->add1();
}
void add3 ...略
};

struct Foo : AddN<Foo> {
int x;
Foo(int i) : x(i) {}
void add1() {
this->x++;
}
};

以上となり慣れてしまうと感覚が麻痺してしまうが
CRTP (Curiously Recurring Template Pattern)の名の通り
「Foo : AddN<Foo>」といちいち自分をパタメータとして与えなければならない
「static_cast<T*>(this)」といちいちダウンキャストをしなければならない
このように「美しくない無駄なコード」になっている
つづく
2023/03/28(火) 17:07:43.55ID:aUMSgZvE
>>678のつづき
一方でRustではトレイトを用いて以下のコードとなる
C++での「美しくない無駄なコード」部分を消し去った状況とほぼ一致している

trait AddN {
fn add1(&mut self);
fn add2(&mut self) {
self.add1();
self.add1();
}
fn add3 ...略
}

struct Foo(i32);
impl AddN for Foo {
fn add1(&mut self) {
self.0 += 1;
}
}

逆にRustのこのコードと同じことを同じようにゼロコストで実現するには
C++ではCRTPを「美しくない無駄なコード」とはいえ使わざるをえない
2023/03/28(火) 17:58:49.48ID:C7yLEzi8
>>678-679
早まるな、俺は【CRTPが】美しいとは言ってない
初めて見たときは、なんじゃこりゃすげぇとは思ったけどねw
2023/03/28(火) 20:04:32.17ID:jfKwOIRn
>>679
CRTPを使わないで仮想関数にすると実行時のvtable経由のオーバーヘッドがあるんだよな
Rustは何も指定しなくてもCRTPと同じ状況になるから記述はシンプルで実行時オーバーヘッドもなく速いわけか
682デフォルトの名無しさん
垢版 |
2023/03/28(火) 20:17:15.74ID:fedCMYV9
そういえば初心者向けのサイト無いな
アイペンテックとか?
2023/03/28(火) 20:32:01.59ID:iKmwqFtY
C++のオブジェクト指向は動的ポリモーフィズムだから遅い
関数呼び出しのvtableオーバーヘッドがあるだけでなくインライン展開ができず最適化の機会も失われている
Rustは基本が静的ポリモーフィズムだからそれらのコストがなく速い
2023/03/28(火) 20:33:07.14ID:QUV/Fh6a
CRTP使うと全部インライン展開されるのマジで不思議だよな
2023/03/28(火) 21:00:58.63ID:HSIaJTs3
>>684
適当なことを言うと規格票で殴り殺される
それがC++村の掟
悪いことは言わない
君はここから早く撤退したほうがいい
686デフォルトの名無しさん
垢版 |
2023/03/28(火) 21:30:24.26ID:pvMX8JEc
>>627
Rubyの話はもういいよ
2023/03/28(火) 21:35:05.32ID:iKmwqFtY
>>684
CRTPを使えば常にインライン展開されるわけではない
CRTPを使った時のみ(vtable経由にならず静的に動作が確定するため)インライン展開が可能となり最適化の可能性も広がり速くなるという話
C++ではCRTPを使わないとRustと同等の速さになれない
688デフォルトの名無しさん
垢版 |
2023/03/28(火) 22:58:28.07ID:rZiXTukV
vtableが重く感じるとかどんな環境やねん。どうせエアプやろ。
2023/03/28(火) 23:08:36.42ID:u9f8RzdU
呼び出し回数多いと馬鹿にならんよ
2023/03/29(水) 00:01:28.04ID:jlgG+N1i
vtableが重いというよりインライン展開+αの最適化が効かなくなるのが問題なんでしょ
使ってる関数が常に固定値(nullとか)を返すって事前に分かればそれによって分岐の整理ができたりするけど
間にvtableが挟まるとそういう予測が難しくなる
2023/03/29(水) 00:09:55.54ID:jqKX3lj0
>>687
CRTPを使わないと真に実現できないのはメソッド記法だけ

そしてvtableとインライン展開に君が想像するような関係性は無い
というか、同じ推論をRustで適用すれば「object-safeなtraitへのimplはvtableを量産しインライン展開を阻害するので悪、やめろ」ということにならないかい?

自分が何を書こうとしているのかよく考えてから書き込むことだ
2023/03/29(水) 00:26:00.18ID:hbkToQM4
C++もRustも、OOPなアセンブラの用途があるからね
少々vtableを経ても平気だとしても、そういうバイナリ吐いてほしくないときはある
バイナリは覗かれるもの
693デフォルトの名無しさん
垢版 |
2023/03/29(水) 02:17:33.72ID:0e8thR9U
こういうしょーもない連中に限ってvtableによって速度が何%落ちるかなんて測ったこともないんだよ。
馬鹿馬鹿しい。
2023/03/29(水) 03:03:32.31ID:F3x5gAOr
>>688
vtableの参照による速度低下よりも最適化できないことによる関数呼び出しのコストが重い
例えば>>679のRust及びCRTPで書かれたC++コードはどちらもadd2()関数呼び出しの中身は最適化されて単なる「add 2」となる
しかしCRTPを用いずにC++で書くとadd2()関数呼び出しの中身は「vtable参照」+「add1()関数呼び出し」+「add 1」を2回することになる
2023/03/29(水) 08:27:05.33ID:hbkToQM4
>>693
パフォーマンスを測るまでもなく、吐かれるバイナリの汚さ
書いた一言一句が何になるか、気になって仕方ないのがC++erだよ(諸派あり、用途にもよる
バイナリエディタに放り込んだらわかるまである
2023/03/29(水) 08:41:42.91ID:jqKX3lj0
>>694
おっ、そうだな
https://godbolt.org/z/M71z9cx74
2023/03/29(水) 09:39:43.93ID:gptXJHJd
この英語版wikipediaのC++サンプルコードとコンパイル結果が詳しい
https://en.wikipedia.org/wiki/Virtual_method_table#Example
CRTPを使わないとvirtual method tableが出てきて不利になる
698デフォルトの名無しさん
垢版 |
2023/03/29(水) 10:58:30.49ID:DCEr0ZuV
CRTPが嫌ならテンプレート分ければいいだけでは?
2023/03/29(水) 11:49:15.76ID:KmrCY6Bh
>>678
これってダウンキャスト入ってるから危険なこともできそう
相当するコードはRustではコンパイル通らない?
#include <iostream>
#define DOUT(arg) std::cout << #arg": " << arg << std::endl
template<typename T> struct AddN {
void add2() {
static_cast<T*>(this)->add1();
static_cast<T*>(this)->add1();
}
};
struct Foo : AddN<Foo> {
int x;
Foo(int i) : x(i) {}
void add1() {
this->x++;
}
};
struct Bar : AddN<Foo> {
double y;
Bar(double i) : y(i) {}
void add1() {
this->y+=0.1;
}
};
int main () {
Foo foo (1); Bar bar (0.1);
DOUT (foo.x); DOUT (bar.y);
foo.add1 (); bar.add1 ();
DOUT (foo.x); DOUT (bar.y);
return 0;
}
2023/03/29(水) 11:51:44.76ID:KmrCY6Bh
実行したら以下のようになった
$ ./a.out
foo.x: 1
bar.y: 0.1
foo.x: 2
bar.y: 0.2
最後のbar.yは1.1になると思ってたんだがはて?
2023/03/29(水) 12:42:03.29ID:KmrCY6Bh
そもそもBarはFooを継承してないんだから
ダウンキャストのところでコンパイルエラー出て良いようなもんだけど
何で通すんだろ? templateだとチェックを緩和してるのかな?
あるいはコンパイラのバグかな?
$ g++ --version
g++ (Debian 10.2.1-6) 10.2.1 20210110
2023/03/29(水) 12:43:14.11ID:KmrCY6Bh
-ダウンキャストのところでコンパイルエラー出て良いようなもんだけど
+static_cast<T*>(this)->add1();のところでコンパイルエラー出て良いようなもんだけど
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を使う範囲の安全性保証はプログラマの責任)
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*にもダウンキャストできるってことね
ありがとう
2023/03/29(水) 13:47:10.36ID:KmrCY6Bh
正当?なC++的にはdynamic_castすべきなんじゃなかろうかって思うんだよね
でそれはvtable介してadd1にアクセスするのと変わらない
プログラマの責任でstatic_castして効率化する
ってテクニックは俺は割と好きだけども
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安全でダウンキャストできる
2023/03/29(水) 14:59:38.14ID:hbkToQM4
そこは、わずかにコストを支払って、reinterpret_castでもいいとは思うけどね
2023/03/29(水) 15:00:17.60ID:hbkToQM4
ああちがう、reinterpret_castを避ける、だ
2023/03/29(水) 15:30:35.32ID:jlgG+N1i
動的検査のコストよりもキャストに失敗した時の分岐処理のせいで最適化が阻害されるのを問題視してる感じ
かといって分岐しないなら動的検査の意味ないし
710デフォルトの名無しさん
垢版 |
2023/03/29(水) 15:35:36.31ID:jd4hHaC+
>>706
ダウンキャストの根本的な問題点を理解してないね
静的か動的かUBかどうかは副次的な問題点に過ぎない
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安全になるんじゃないか?
2023/03/29(水) 15:45:49.19ID:RttupHdJ
>>710はいつものデタラメ言いがかり君に似てる
闇雲に否定して別の問題点があると主張しつつ
その問題点を述べることは一切ないので書き込みの中身がない
713デフォルトの名無しさん
垢版 |
2023/03/29(水) 17:50:54.05ID:aWl/4JyA
>>711
デフォルトmoveの導入は無理だと思ってるくせにNull安全は導入できると思ってるのかw
オツム弱っww
2023/03/29(水) 18:18:44.67ID:eKurmGUm
たぶん人違いじゃないかな?
dynamic_castの返り値を確認しないやつは
流石におらんと思うよ
静的に確認してくれても全く嬉しくない
2023/03/29(水) 18:19:38.85ID:eKurmGUm
訂正
静的に確認を強制されても嬉しくない
2023/03/29(水) 18:50:51.61ID:3DtieHtv
ヌルポインタが返る全ての関数についてそうしないとヌル安全にならない
ヌルを使ってはダメ
2023/03/29(水) 19:05:30.65ID:KmrCY6Bh
それは当然だよ
C++では指し示した先にインスタンスがあるかどうか
分からんときにのみポインタを使う
確実にあるときは参照を使うのが流儀
ポインタが使われるところではnullptrのチェックを行う
この流儀の部分を守らないスカタンが問題なんだな
Cに参照がないので上記流儀が守られないことも問題
2023/03/29(水) 19:30:08.82ID:ap6Xt56V
>>704
なぜそのC++のプログラムは正しく動かいていないの?
bar.yはadd2()で0.2足されて0.1から0.3にならないといけないのに0.1のままになってる
>>699のソースコードを見ても正しく動かない原因がよくわからない
2023/03/29(水) 19:36:28.24ID:KmrCY6Bh
>>718
BarはAddN<Bar>ではなくAddN<Foo>を継承しているから
2023/03/29(水) 19:41:07.31ID:ap6Xt56V
>>719
add2()としてBarの+0.2が使われずFooの+2か使われるということ?
bar.yが2.1になっていないのはなぜ?
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*にキャストしたら動作は不定
2023/03/29(水) 20:09:37.10ID:ap6Xt56V
なるほど
浮動小数点に対してそれを整数と見て+2してしまっているのかな
本来はコンパイル段階でエラーにしないとやばそうだ
今回はっきり動いていないとわかるケースだからいいけど何となく動いてしまってるケースがあると恐ろしい
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 () {};
};
2023/03/29(水) 20:13:55.05ID:AtW1ukjc
静的に一意に決まるんならいいのでは
2023/03/29(水) 20:29:34.23ID:KmrCY6Bh
俺は割と好きだけどもね
2023/03/29(水) 20:42:15.15ID:rGt9yURA
C++最適化効きすぎてadd2そのものが展開されて最短コードにしかならん
2023/03/29(水) 20:50:49.78ID:ij9aGzzi
doubleのビット列をintとして扱ってインクリメントしてるから結果がおかしいんだろ
なぜコンパイラは型不一致エラーを出せないんだ?
2023/03/29(水) 21:21:00.23ID:iEVzPlea
問題があれば何でもコンパイル時点でエラーを出してくれるRustを使おう
実行デバッグが激減して開発効率も高い
2023/03/29(水) 21:39:38.92ID:KmrCY6Bh
でもunsafeないとダメなんでしょ?
2023/03/29(水) 22:02:01.80ID:iEVzPlea
普通のプログラムでunsafeは出てこない
2023/03/29(水) 23:01:50.75ID:UIOCT5jB
ライブラリが一個もない状態から基本的なライブラリを作るためにunsafeが必要という話だったら
有限個のバイナリファイルが正しく出力されればいいだけなので
ソースコードをチェックしなくても出力をチェックすればいいのでは?
2023/03/30(木) 06:54:28.38ID:xjlzONIR
>>727
「違う」ところにひっかかってる traceを加えてみると誤解がとけるぞ
https://wandbox.org/permlink/AsyGpe34rpZ3en8v
733デフォルトの名無しさん
垢版 |
2023/03/30(木) 06:54:54.18ID:uZvbGS3c
そういえばJavaが全然話題にもならないが言語のヒエラルキーって

C++ 最強カミソリ
剃り残しナシ

Rust 安全カミソリ
キレテナーィ なまくら

C# イケてるが
GCがあるからダメぽ

Java 論外
ヌルポとGCがあるからダメぽ

こんな感じ?
2023/03/30(木) 07:08:43.78ID:xjlzONIR
一つ間違うと自分の手とか余計なところまで切れちゃうw
2023/03/30(木) 07:25:50.11ID:xjlzONIR
俺にとってのC++は、日本語だよ 物心ついたときには、C++だったんだ
氏ぬまで忘れないと思う だからある意味最強、そんな奴が結構多いんだと思う

「ちゃんと話せ」って躾けられたのも、良し悪し
2023/03/30(木) 07:29:05.38ID:Lly0YXlC
>>733
逆だろ
RustはC++ができることは何でもできる
C++はできないことが多すぎ
737デフォルトの名無しさん
垢版 |
2023/03/30(木) 07:42:11.73ID:w91B/KcY
C++が出来なくてRustが出来ることってある?
2023/03/30(木) 07:43:46.76ID:xjlzONIR
縛りプレイ
2023/03/30(木) 08:01:00.44ID:Lly0YXlC
>>737
C++はできないことが多すぎる
このスレに出てきた話だけでも
代数的データ型
パターンマッチング
各種null安全
データ競合安全
メモリ安全
など多数
2023/03/30(木) 08:18:36.82ID:PJ70lfxq
プリミティブはいろいろ備わってるから、やってできなくはないんだろうけど、
強制する方法がないから、ちっとも普及しないんだよね
2023/03/30(木) 08:28:14.61ID:Lly0YXlC
>>740
C++はそのプリミティブを多数欠いている
まさか代数的データ型をunionで頑張ればできると主張するのか?
パターンマッチングは構文だからC++には無理
データ競合を静的に検知する方法もない
2023/03/30(木) 08:32:28.84ID:PJ70lfxq
C/C++には昔から、「なければgenerateすればいいじゃん」っていう文化がある
パターンマッチングは、いまどきIDEが記述支援するんだから、やってできなくはない
データ競合やらは、「そういう」スマポを導入すればいい

でもね、みんな使わないんだわ 使われないものは、ないものとして詰られても仕方ない

あ、Cとおんなじように、入れ子になった構造体をささっと書きたいとかは思うね
もうできるようになったっけ?
2023/03/30(木) 08:35:47.70ID:2ioUidZk
Rustのマクロって結構凄くね?
2023/03/30(木) 09:18:55.32ID:PJ70lfxq
…いやまてよ、パターンマッチングって、エラー等検出のことだと思ってたけど、
パターンマッチング Rust でぐぐったら全然違うものが出てきたぜ その節は撤回 ちょっと読んでみる
745デフォルトの名無しさん
垢版 |
2023/03/30(木) 10:37:10.30ID:z+Rtq9PG
2023/03/30(木) 10:45:06.95ID:7YA3tv0i
std::visitはパターンマッチに含まれますか
2023/03/30(木) 10:56:39.82ID:7YA3tv0i
こういうのね
提案段階の機能を除けば一番直和型を直接的に表現できていると思う
https://www.modernescpp.com/index.php/visiting-a-std-variant-with-the-overload-pattern
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})です"),
}
}
2023/03/30(木) 11:05:35.09ID:wHEiYRW7
C++はユーザが多いので標準でなくてもライブラリがあるからね
Rustはユーザが少ないので標準で用意しとく必要がある
パタンマッチングは言語の話だけども
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 になります
何処を治せばよいですか?
2023/03/30(木) 11:14:15.70ID:xP+9HiJo
>>747
C++のstd::variantは全体の型名を命名できない
各要素に対して専用の型を用意しなければならない
扱いづらいなど欠陥品

例えば>>748のShapeの定義例は
enum Shape {
Circle(u32),
Rectangle(u32, u32),
Parallelogram(u32, u32),
}
これだけで済む
さらに型Shapeに対して様々なメソッドを実装できる
C++ではそれぞれ困難と不可能

>>749
言語がサポートしないとライブラリでは無理
2023/03/30(木) 11:14:43.48ID:PJ70lfxq
一発目から GET / HTTP/1.1 じゃないものが来てるかもよ、buffer 表示させてみては
2023/03/30(木) 11:28:11.87ID:7YA3tv0i
>>751
記事読んだ?
2023/03/30(木) 11:32:57.91ID:xP+9HiJo
>>753
読んだけどそれでは無理
こちらはパターンマッチングのRustのコード例を>>748に出した
C++でも可能だと主張するならばそれぞれの実現コードをまず出すべき
2023/03/30(木) 11:39:46.03ID:PJ70lfxq
パターンマッチングの件、5分くらい読んできた
そういう風に書きたいっていうニーズがあるんだな、表現力を誇るC++でこれが書けないのは確かに手落ちw

この型はあれでもこれでもあるっていうの、あんまり扱ってこなかったけど、
上手く書けば便利になるかもね ただし、ゼロサンクでね
2023/03/30(木) 11:39:46.85ID:xP+9HiJo
>>750
そのRustのTcpListenerのサンプル動かしてみたけど普通に動いた
返すindex.htmlを用意してcargo run
ブラウザからhttp://localhost:9999/で表示された
2023/03/30(木) 11:46:33.32ID:7YA3tv0i
>>754
「無理」とだけ言われても何も分からないので具体的にお願いします
それとも記事を読んだうえでも、無理な点の指摘は>>751ですべてだということですか
例を読んでいれば「各要素に対して専用の型を用意しなければならない」は嘘だとすぐ分かるはずですが
2023/03/30(木) 11:47:15.19ID:xP+9HiJo
>>755
Rustは>>748の各パターンマッチング例をオーバーヘッド無しで処理してくれる
使わずに手動でダラダラと書ける分もパターンマッチング記述の方が最適化が良いかもしれん
2023/03/30(木) 11:49:39.34ID:xP+9HiJo
>>757
具体的に>>748にRustのパターンマッチングの各例のコードを書きました
次はC++でも可能だと主張するあなたが対応するC++のコードを出す番です
2023/03/30(木) 11:58:04.66ID:7YA3tv0i
>>759
あなたの要求に答えるために質問だけさせてください
明確にしてほしいのは「何が無理なのか」の「何」の部分です
よろしくおねがいします
2023/03/30(木) 11:58:20.56ID:PJ70lfxq
教科書的サンプルとは別に、実践的なサンプルが見たいぞ
必要だから入った仕様だろう、手ごろにどっかあるはずだ お勧めのやつをたのむ
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);
}
2023/03/30(木) 12:23:51.98ID:8gDdaVz7
>>762
それだとShapeが型ではなく名前空間になってしまってるからダメでしょ
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

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