C++相談室 part138
■ このスレッドは過去ログ倉庫に格納されています
次スレを立てる時は本文の1行目に以下を追加して下さい。
!extend:on:vvvvv:1000:512
C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
IDE (VC++など)などの使い方の質問はその開発環境のスレにお願いします。
前スレ
C++相談室 part137
http://mevius.5ch.net/test/read.cgi/tech/1531558382/
このスレもよろしくね。
【初心者歓迎】C/C++室 Ver.103【環境依存OK】
http://mevius.5ch.net/test/read.cgi/tech/1530384293/
■長いソースを貼るときはここへ。■
http://codepad.org/
https://ideone.com/
[C++ FAQ]
https://isocpp.org/wiki/faq/
http://www.bohyoh.com/CandCPP/FAQ/ (日本語)
VIPQ2_EXTDAT: default:vvvvv:1000:512:----: EXT was configured STLつかうと一気に実行ファイルサイズが10倍に?!
環境によるだろ。
俺はBorland-C++5.6.2に -D_RTLDLL オプションを指定して、極力
ランタイムを使用するようにして使っているが、例えばstd::vectorを
使っても使わない時と比べ10Kほどしか増えない
すげえ。ダイナミックリンクしといてファイルサイズが増えないとかいってるよ。この人。
C1010: プリコンパイル済みヘッダーの検索中に予期しない EOF を検出しました。
とかいうエラーが出るんだけどこれってどうすればいいの?
#include <stdafx.h>
後死ね。
言葉が悪いな。それで教えているつもりか。
まぁヒントぐらいにはなったな。
うむごくろう。
---- テンプレ ここまで ---- rad c++ builderでファイルの入出力やドラッグ&ドロップ 簡単なdb操作は出来る様になったけど、もう一歩踏み出したいです
福岡当たりで勉強会みたいなのはないでしょうか?
大阪、東京でも有るなら飛行機使っていきたいです 6です
c++ builderのスレッドが合ったので
そちらで聞いてみます
失礼しました >>6
「C++ の勉強会」
なんだか魅惑的な響きですね… 関数内にstaticつけたクラス変数定義した場合、
コンストラクタは関数を最初に呼び出したときだけ呼ばれると思います。
これはどういう仕掛けなのですか?どこかにフラグがこっそり用意されるのでしょうか。 >10
ちょっと書き方間違えました。
定義ではなく宣言です。
間違ってますでしょうか?ではコンストラクタが呼ばれるタイミングはどこでしょうか >>9
クラス変数とは言わないよ
そのとおりフラグがある
さらに11か14かは忘れたけどmt safeにもなった
つまり同期プリミティブも裏で作られている >>9
コードで書いた方がいい。
どうせ用語を間違っていて、正確には通じてないから。
エスパーで話すのもありだとは思うけど、回答を信頼出来ないだろ。 virtualなデストラクタを持たないクラスを継承しているクラスを派生していない状態でコンテナ等に入れた場合、
エラーまたは警告にする方法ってある?
典型的な「デストラクタをvirtualにしろ」のケースであり、
安全性だけを取るのならそうすれば済むのだが、大量使用したいのでコストを限界までケチりたい。
可能であればコンパイラにチェックさせたい。
具体的に言うと、Matz曰く「実装が漏れてる」の典型的なケース、配列について、
長さと先頭のポインタをstructにして、各操作をそれに対するメソッドとして記述し、
スクリプト言語風に簡潔に書けるか試したい。
std::spanの再実装に近いので、そちらで言うと、
https://github.com/tcbrindle/span/blob/master/include/tcb/span.hpp
std::spanを継承して各種メソッドを生やし、(クラスM)
さらにそれを継承して以下3つのコンストラクタを持たせる。
クラスA. 型と既存ポインタと長さからの生成
クラスB. 型と長さを与え、allocaでの生成
クラスC. 型と長さを与え、heap上への生成
A,Bは問題ないが、Cはデストラクタでdeleteをする必要がある。
ここでstd::spanのデストラクタはvirtualではないので、(上記実装例の場合)
vector<C>をvector<M>等と間違えたら不味い。
このときに、警告またはエラーを発生させたい。 もう一つよろしく。
C++でkey/valueソートしたい場合は
・std::unordered_multimap等にコピーしてからstd::sort
・自前で<key,value>を含んだ構造体を用意し、それに < を定義して、コピーしてstd::sort
のどちらかって感じ?
ちょっとまどろっこしいので、もう少し簡単な方法無いかな?
doubleの配列をソートした際、何番目がどこに行ったか追跡したい。
.NETだと Array::sort(array0, array1) があり、
array0 に double の配列、
array1 に [0 ... N-1] な配列を指定しておけば、array1の結果で簡単に追跡出来た。
記法が原始的ではあるが、結果的にはこっちの方が楽で良かった。
std::sortで2つの配列を取る物があれば助かるのだが、なさそうだし。
boostも見たが、よく分からん。 抽象型のメソッドを使ったときにも型を失わず、派生型のままで返す方法って無いよね?
継承を使わず、テンプレートで展開するしかないか?
コード上で展開されるのが、多少勿体ないんだが。
>>14の実装で、
各種メソッドをクラスMに突っ込み、それを継承していると、
Cからメソッドを呼び出した際、どうしてもM&等の型しか返せず、
ダウンキャストがいちいち必要なのがウザイ。
具体的には、fromは既存の配列からコピー、sortはソートするメソッドとして、メソッドチェーンで初期化する際、
C& test = (C&)C( ... ).from( ... ).sort();
となり、fromやsortがM&を返すのでC&にダウンキャストする必要がある。
従来方式の初期化して使用なら問題はない。
コンストラクタは派生型を返し、メソッド群はM&で閉じているので。
A& test = A( ... );
test.from( ... ).sort();
メソッドをvirtualにすれば回避出来るはずだが、無駄にvirtualにしたくない。
B/C共に全く同一の関数で済むはずなので、可能で有れば共有したい。
諦めてB/C毎に同じ関数をtemplateで展開すれば出来るのは分かるが、これはしたくない。
何か方法有る? そもそもなんのためにMから継承してんのか考えてみたら >>17
オブジェクト指向ではMで閉じるというのが正しいと思いこんでるんだろ。
それは一面にすぎない。
JavaScriptではメソッドチェーンで型を失わない。
だから上記のようなことも平気で出来る。
勿論C++でも実装を別々にすれば出来るが、ダブる分無駄に膨らむ。
或いはvirtualにしても出来るが、これはポインタ一つ分データが膨らみ、呼び出しも遅くなる。
最適化した状態での記述方法がない。
今回、AとCの違いはデストラクタ内で解放するかどうかだけであり、
当然全てのメソッドは共有出来る。
順当なら継承が妥当だが、virtualにしないと型を失ってしまう。
(この点、全てvirtualであるJavaはオブジェクト指向原理主義としては筋が通っている) ちなみに技術的には、super に対するキーワード derived が足りないのだと思う。
クラスM内で、
M& from(){ ... ; return *this;}
ではなく
derived& from(){ ... ; return *this;}
と出来て「呼び出した型」を返せれば全く問題ないんだが。
この辺のキーワードって無いよね? なんだ、JavaScriptという一側面だけ見てC++に立ち向かってるアホだったのか
まぁがんばれよ C++がメソッドチェーンに向いてないのは確かだよ。
それ向けの文法も用意されてない。
多分「継承」に対して型を失うこと自体が間違いなんだよ。
C++はそこら辺が古い。
ただ、ダブって良ければtemplateで解決出来るのも確かだが。 JavaScriptの場合は型が失われないんじゃなくて「無い」んだな。
レシーバの型に関係なく呼び出せてしまうだけ。 >>20
あとついでに言うと、その選民思想はマジで止めろ。
C++だけの話でもないが。
というより最近「俺がやってる言語スゲー」な奴が多いのは何でだ?
一昔前は全員Cが出来、その上で他言語だったから、その手の争いは皆無だった。
それ以前にプログラミングがきちんと出来れば、後は文法だけの問題だから、
多言語化は容易だし、実際全く問題ない。
「俺の言語スゲー」でイキれる奴って文法しか見えない馬鹿のような気がするが。
C++はコンパイラ向けの文法ばかり多くて、本質的なプログラミング用の文法は多くない。
今回も、JavaScriptだと容易に実現出来るのに、C++だと記述出来ないだろ。
あまり他言語を馬鹿にしていると足をすくわれるぞ。 CRTP使えばどうだろう?
template <typename Derived>
class M {
public:
Derived &from(){ return static_cast<Derived &>(*this); }
};
class A : public M<A>{};
class B : public M<B>{}; >>22
まあその通りだが、
C++: 記述出来ない
JavaScript: 動的型なのでそのまま書けるし、動作する
Java: 全部virtualだからそのまま書ける(ただし、これでいいのならC++でも書ける)
Go: 継承を廃止してしまったからそもそもこの問題は発生しない?
Rust: ちょっと見たがよく分からん
まあ俺はやっぱり、「継承」で親の関数を呼んだら型が失われるのは間違いだと思うよ。
仮に Z : Y : X と継承していたとして、
(Zの実体).(Xのメソッド).(Yのメソッド) とは出来ないでしょ。(Xのメソッドの時点でX&になるから)
これはメソッドチェーンする気なら使いにくい。
(これまでは居なかったから問題にならなかっただけ。バラバラに書けば出来るので) >>24
とりあえず今はそれで実装してる。
それが16で言ってる
> 諦めてB/C毎に同じ関数をtemplateで展開すれば出来る
というやつ。
ただどう見ても無駄なので、可能で有れば実体も一つにしたい。 >>26
> ただどう見ても無駄なので、
どのへんが無駄なのか教えてほしい >>27
テンプレートは型毎に展開されるし、自明では?
むしろ通じない方が不思議だ。
仮に俺が言ったように19の表記が出来れば、
オブジェクトコードはその部分は半分で済むし、命令キャッシュのヒット率も上がる。
勿論C++でもvirtualにすればこれらの点は解決するが、
呼び出しが遅くなってデータオブジェクトもポインタ一つ分膨らむだろ。
今のC++では最適化したオブジェクトコードを吐かせる記述が出来ない。 C++コンパイラの気持ちになって考えてみなよ
お前の望みは無理だから
どうせベンチとらずに遅いとか言ってんだろ
だまってvirtual使うかダウンキャストするかそもそも継承使わないかどれかにしとけ >>29
ベンチ取らなくても自明だろ。
そしてC流の「手動」オブジェクト指向なら、自分で関数を手動で切り替えるのだから、実現出来るんだよ。
ただ、現実的には、derived等のキーワードが出来ればC++でも普通に可能だぞ。
単一継承ではthisの値は型によらず同じだし、
この場合に親のメソッドを使ったら親の型になるというのは、
純粋に「コンパイラがエラーを検出するだけ」の為であり、実装には何ら影響がない。
だからコンパイラがエラー検出さえしなければ通るし、そのまま動作するコードになる。
C++は過剰にエラーを検出しているだけなんだよ。 なお、やっぱ継承じゃないと使いにくいわ。
A/B/Cってのはコンストラクタ/デストラクタだけの違いだから、
他から呼び出すときは型Mにして多態したいのだが、
CRTPだとこれが出来ないorz 必要なのは「ダウンキャストの型推論」か?
文法的に見てダウンキャストが安全な場所はあるだろ。例えば、25の
> 仮に Z : Y : X と継承していたとして、
> (Zの実体).(Xのメソッド).(Yのメソッド)
とか。
X& → Y&のダウンキャストも自動アップキャストと同様出来てもおかしくないし、これが有れば解決だ。
「ダウンキャストは悪」って事で止まってしまってるだろ。
もっとも、全部virtualで単一継承ならダウンキャストはほぼ要らないのも事実だが。 自己修正。
>>28
> 今のC++では最適化したオブジェクトコードを吐かせる記述が出来ない。
これは間違いだった。
いちいちダウンキャストすれば(ソースはうざくなるが)最適なオブジェクトコードが出る。
ダウンキャスト忘れはSyntaxErrorだし、妥協するならこっちかも。 Mを継承してるのが間違い
Mは実装を共通化してるだけだろ
Mをコンポジションにしてデリゲート
C++ならprivate継承にしてデリゲートはテンプレートにすりゃいい >>35
それで何が嬉しいんだ?
記述も無駄に増えるし、何もメリット無いように思うが。
(Mへのデリゲートの部分が余分に必要)
どうせ委譲部分を全部書く気なら、
コンポジションせずに単に自前で戻り値をダウンキャストした方がいいと思うが。
例:
Class C : M {
C& from( ... ){
return (C&)((M*)this)->from( ... );
}
};
コンポジションにすると上記のアップキャスト部分(M*)が必要なくなるが、
その分無駄にポインタ一つ分データが膨らむだろ。
上記のダウンキャスト/アップキャストは実行コード上には現れないのだし、
2段呼び出しを省いてくれる最適化がかかるのなら、
呼び出し側でダウンキャストする必要が無い為、まあまあ。
(ただしfromの実体と委譲でクラス側のソースコードは増えるが) ちなみに単純な実装なら
「呼び出し側でダウンキャスト必須」になってウザイのだが、
C++的にはこれが正しいような気がしてきた。
俺にはこれは「過剰な型チェック」にしか見えないが、C++はそういう言語でもある。
コンパイラのチェックから逃れる為にデータ構造を変更するのは本末転倒だし。
ダウンキャスト撲滅教の信者は、次から
・derived等、継承で親のメソッドを使ったときにも「呼び出し側の型」を返す為のキーワードの整備
・ダウンキャストの型推論
のどっちかをプッシュしておいてくれ。 傍から見ていると、メソッドチェーン自体なにが嬉しいんだろう、と思ってしまう。 >>38-40
そりゃ君らが老害だからだよ。
老害ってのは肉体的な年齢のことではない。
好奇心/興味を失った結果、新しい価値観を認めないから老害となる。
新しい言語を見てみろ。全てメソッドチェーン出来るだろ。
最初は戸惑うかもしれないが、慣れれば相当便利なんだよ。簡単に凝集度を上げていける。
もう1行に1個ずつ処理を書いていていい時代じゃなくなりつつあるのさ。
とはいえ、クラスも当初は無駄だと言われていたのだろうし、今ならラムダやLINQが該当するのだろうけど。 thisポインタ返すメソッドチェーンってクソだろw
perl脳と同じ おかしな主張を生暖かく見守っていたのに、そんなストレートな御意見を ■ このスレッドは過去ログ倉庫に格納されています