C++相談室 part131 [無断転載禁止]©2ch.net
■ このスレッドは過去ログ倉庫に格納されています
次スレを立てる時は本文の1行目に以下を追加して下さい
!extend:on:vvvvv:1000:512
C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
IDE (VC++など)などの使い方の質問はその開発環境のスレにお願いします。
前スレ
C++相談室 part130
http://mevius.2ch.net/test/read.cgi/tech/1490917669/
このスレもよろしくね。
【初心者歓迎】C/C++室 Ver.100【環境依存OK】
http://echo.2ch.net/test/read.cgi/tech/1478440682/
■長いソースを貼るときはここへ。■
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
VIPQ2_EXTDAT: default:vvvvv:1000:512:----: EXT was configured >>50
privateをpublicでdefineするやつじゃ? >>50
微妙に違うような
アクセス制御が適用されない文脈でメンバーへのポインターやstatic変数のポインターを取得してアクセスする手法 privateをpublicでdefineするのは潔くてカッコいいが
>>54は全てが糞すぎる >>57
うむ、こんなところだろう
1.既存のクラスに普通に手入れている
2.それは違うと>>53で言っているのに投下されるアスペなレス
3.privateな変数にアクセスするかと思いきや、privateな変数を出力するprivateな関数を呼び出すという意味の無い構成
4.deleteを使用するUNKOなコード
5.newを使用する残念なコード
6.コードへのリンクを投下するのでなくクソスレを経由するクソレス
7.例外安全でない
8.非staticにする必要性が感じられない
9.「(hoge->*(hoge->g()))();」というブザマな呼び出し方 >>58
https://ideone.com/Y4LPCV
改善:3, 4, 5, 6, 7
保留:1, 2, 8, 9 いやそこは無視するだろ普通
>hoge.get()->*(hoge->g2()) = 54321;
もう何が何だか… 読んでないけどg()は関数ポインタを返す関数?
設計からしてダメだろ 既存のクラスに手を入れてる時点でキモイ。
それならもっとやりようあるでしょ。 >>61
メンバのオフセット(たぶん) ->* ::* 使用前提のやつ
>>59 は一箇所どうにもこうにもならないので放置している部分がある
ともかく笑いのネタというより他にない >>63
遠慮せずともじゃんじゃんプライベートにアクセスしてよいぞ
http://ideone.com/BJHsgK >>63
オフセットして実装するのが普通だと思うけど、メンバ変数へのポインタがオフセットで実装されるとは決まってないんじゃないの? C++の場合クラス(およびその基底クラス)内のメンバは全部ヘッダファイルを辿っていけばワカルのだから
まず全く同じ内容のヘッダファイルのコピーを作り、
ファイル名を適当に変えて、多重インクルード箇所もコピーしたもので閉じるように変更して、
privateやprotectedを全部publicにして、
クラスの名前をFoo→Foo2とか改変して、
仮想関数は適当に空の定義でもつけて、
((Foo2*)p)->(Fooのデータメンバ)
式にキャストしてアクセスすればデータメンバと仮想関数については問題なくアクセスできる
(ODR違反は都市伝説なので事実上これで動く
だいたいprivate破りを意図している時点で実コードレベルで影響しない規約とか気にしても仕方が無い Foo2の仮想関数が空ではないか、というのは動作上問題にならない
vtableのしくみがわかっているならワカル以下略
一方非仮想関数の方はちょっとうまい方法が思いつかない…
private属性のメンバ関数のアドレスがとれれば勝つるのだが class Base {
public:
Base() {};
virtual void func() {};
};
class Sub: public Base {
public:
Sub() {};
virtual void func() {};
};
Sub a();
std::vector<Base> b;
b.push_back(a);
b[0].func();
これだと継承前のBaseのfuncが実行されてSubのfuncが実行されないんですが
Subのfuncを実行するにはどうしたらいいですか そりゃpushするときにBaseへの暗黙の型変換かかるからダメっしょ
ポインタつかえよBaseの >>68
そのコード本当に動く?
本質じゃなくて申し訳ないが、そのまま追試出来るコードじゃないと…
ちなみに質問の回答はスライスな。 おかしいな、確かに
コピーコンストラクタもないのにコンパイラ通るのかコレ >>69
ありがとうございます
ポインタにすることで解決しました
>>70-71
動かしてるコードを簡略化したのでもしかしたら動かないかもしれないです 「本当に動く? (中略) そのまま追試出来るコードじゃないと…」
↓
「もしかしたら動かないかもしれない」
これがアスペというやつだな この言語はどこの業務で使われてるの?
組み込み・制御はC++使ってますとか言いながら大体これCじゃん!だから論外として gcc が c++ で書き直された、という話はあったな >>76
https://github.com/search?utf8=%E2%9C%93&q=language%3AC%2B%2B+stars%3A%3E%3D1000&type=Repositories >>76
Better C として使ってもええんやで 質問です。
宣言は、全ての要素に対して必要なのですか?
n = a+b:
という行があるとすると、
#include <n>
#include <a>
#include <b>
が必要なのですか?
とても初心者なので、なにとぞ教えてください。
お願いします。 意図がわかりにくいがその場合だったら#include <n> だけあればいいんじゃないの?
そうでないとしたらinclude順は#include <a>と#include <b>を先に書くべき。 >>84
#include は宣言じゃない
多分
int n;
int a:;
int b;
のことじゃないかな? >84
#include
というのは、外部にあるファイルを読み込め
という命令なので、変数の宣言ではありません。
#include <a>
というのは、aというファイルを読み込めという
命令です。
n=a+b
という場合には、この式の前に、n, a, bという
変数の型を宣言する必要があります。
全てが整数ならば、
int a, b, n;
単精度実数ならば
float a, b, n;
と、倍精度実数ならば、
double a, b, n;
と書きます。
と変数の型を宣言します。
このことは、基本の基本なので、解説書の最初に書いてあるはずです。
解説書をよく読んで、その上で分からないことを
質問しましょう >>85-87様
googleだけの独学なので、とても勉強になりました。
とても、ありがとうございました。 >#include <a>
>というのは、aというファイルを読み込めという命令です。
んなこたーない >>87
>この式の前に、n, a, bという変数の型を宣言する必要があります
それは規格のどこに書いてあるのですか? DEFINEもincludeも本質的にやってることは同じだしファイルを読み込めは間違ってるな includeがファイルをその位置に展開しろっていうのはあってると思うけど、何が不満なんだ?
defineはただの文字列置換。 × #include <a>というのは、aというファイルを読み込めという命令
○ #include <a>というのは、aというヘッダーを読み込めという命令
○ #include <a>というのは、#include <a>をaというヘッダーの内容で置き換えろという命令 >>84のレベルの人に説明するのに、厳密な用語をどうこういうより、>>87レベルの説明の方が適切だろう 仕様だとヘッダーとソースファイルは区別されてるみたいだけど
#includeはヘッダーとソースファイルのどちらも扱うから
二つを纏めてファイルと呼称しているとしたら>>94は間違いじゃないの? 「C++の#includeがファイルを読み込むとは限らない」
という説明を何かで読んだ記憶がある。
例えばソースに #include <hoge.h> と書いてあっても
hoge.h というファイルの実体は存在しなくて、
コンパイラが内部的なスイッチとして使っても構わない、みたいな話。
実際にそういう動作をするコンパイラは知らんけど。 >>97
もとの>>87は#includeでなく#include <>なのだが
>二つを纏めてファイルと呼称しているとしたら
いきなり自分の結論を大前提に置かれても
まあこのへんはC++17で少し変わるだろう CSVファイルを読み込むときに#include使うことある てか、学ぶなら1冊くらい本買えよ
Googleで独学とか効率悪すぎる 軸がわからないと自分が何をわかってないかすらわからないからクソみてぇな思い込みで検索して見当違いの方向に突っ込んでしまうから、
そうなってから質問しても質問が見当違いすぎて回答しようがないことはよくある。 >>102
いっちょコンパイラを書いてやろうと思っているんだが何をやっていいかわからない…
手元の教科書は必死に正規表現やらチューリングマシンやらを追求している…
これってコンパイラ本だと思って買ったのだが、どうも本を間違えてしまったらしい
軸がわからないと悲惨ですね http://ideone.com/RcWgQx
これ、C++17でできるようになるんだっけ?どうだっけ? 少なくとも似たケースを支援する機能は追加されるがそのままでは通らない
[*this] と思ってよく読んだら関係無かったしTは生存期間内だった
つまりC++17では無理 そうなんだ。ありがとう。
またウインドウを出せないのか。
綺麗なウインドウクラスを書く日は遠い・・・。 >>103
LLVMのtutorialでもやってみたら? (↓の一番上)
https://llvm.org/docs/tutorial/
たしか日本語訳もあったと思うけど、内容が古いので注意。 >>103
yacc, lex (または bison, flex) とかは知ってる?
使うと構文解析が楽になるよ。 >>108
単にstd::function使えって話じゃねーの? >>111
WindowsのウィンドウをWin32APIで出すときは、Cのインターフェースに渡さないといけない。
なので、デフォルトキャプチャにthisのアドレスコピーが入ってくれないと厳しい。 >>112
typedef bool(*Fun)();
にキャプチャしたデータを置いとく場所が無いんだからいつまでまっても実現しないよ
そういうC言語のAPIにはvoid*でユーザーデータ渡せて引数で取得できるようになってるはずなんだからそれに規則性があるのなら(例えば最初の引数がユーザーデータになってるとか)テンプレートでラッパー書くの簡単でしょ >>105
できるも何も型が違うからエラーでしょ。
ラムダ型のオブジェクトはautoでしか受けられない。 >>113
クロージャって知らない?
>>114
条件を限定することで関数ポインタに束縛できるようになりました。
まぁ今回書いたのは願望ですけど。 >>115
キャプチャしないラムダ式は関数ポインタに変換出来るだけ。束縛じゃない。 クロージャがどのように実装されているか調べてみることを勧める。
そしてそれをC言語の関数ポインタと互換性がある形で実装可能か考えてみるといい。 >>117だよ。
駄々っ子みたいになってるが、
スレッドローカルみたいな変数を持たせれば持てないことも無いと思う。
まぁ、もうできないことはわかったので抜けます。 もういない宣言出てるけど、スレッドローカルでやられても困るだけだと思う。 >そしてそれをC言語の関数ポインタと互換性がある形で実装可能か考えてみるといい。
もともとC言語はλ式とか、(束縛変数がクラスのこともありえるが)クラスを構文でサポートしていないのだから
「C言語の関数ポインタと互換性がある形」と逝っただけでは何を指しているのか不明確にならざるおえない
呼び出し側がいかに煩雑な記述になろうとも、動けば互換性があるという立場をとってみるテスト、
束縛変数も毎回引数渡しすればC言語の関数ポインタと互換にできるのでは…
もはやクロージャでも何でも無いが一応動く >>121
>もはやクロージャでも何でも無いが一応動く
ちなみにどうでもいいことだがラムダ式から取得した関数ポインターはC++リンケージ型なのでC関数に渡してコンパイルが通る保証が無い >>122
関数ポインタ経由の関数呼び出しに関数名のマングルは関係無いのでは… >>123
関数名だけではない
extern "C" using CF = void(); と
using CPPF = void(); は似て非なる関数型
この二つはオーバーロード可能で互換性も無い
恐らくマングリのみならず関数呼び出し規約の違いを許容する思想
ただこれを正しく実装したコンパイラーを見たことは無い a = 0
2.times do
b = 1
3.times do
p a, b
end
end
「Rubyのしくみ」に書いてあるけど、Rubyは、Cで作ってあり、
do 〜 end のブロックは、クロージャの実装。
ラムダ・Proc も、ほとんど同じ
子のブロック内で、変数が見つからなければ、
外のスコープ(先祖の方向)へ遡って、探しに行く >>125
そのとおり
規格では別の型と規定されている
atexitなど関数ポインターを渡す関数ではCリンケージの関数ポインターを渡すかC++リンケージの関数ポインターを渡すかで
C版atexitとC++版atexitのオーバーロード呼び分けができることになっている
clang/G++は意図的に規格に従っていないというのが痛説
Visual C++は規格より自分が正しいという意味不明な見解 や、互換性がない→別の型 は真でも 別の型→互換性がない はそうじゃないような。 そのとおりだ
暗黙の変換は禁止されていない
ただ暗黙の変換が可能というルールも存在しないので「コンパイルが通る保証が無い」と書いた なるほど。
上の方で原理的に無理みたいなことが書いてあった気がしたので念のため。 そういうCのインタフェースにはたいてい関数ポインタの他にユーザデータを指定できるようになっててそこにthisなんかを入れておくものだが、 >>105 は関数オブジェクトを関数ポインタだけに変換したいと言っているわけか……
コードを動的に生成すれば不可能ではないだろうけど、色々トレードオフがあるから言語の機能にするのはどうだろうね。
ライブラリを作っても良いんだろうけど、おとなしく定石に従っておいた方が良いよ >>132
動的にコードを生成したとしてもどこにその生成したコードを置くのか、それをどうやって解放するのかが問題になるね。だったらコード生成してもしなくても同じ事。 >>133
> 動的にコードを生成したとしてもどこにその生成したコードを置くのか、それをどうやって解放するのかが問題になるね。
そうだね。
> だったらコード生成してもしなくても同じ事。
同じではないね。 >>134
言い方が悪かったかな?
「どこにその生成したコードを置くのか、それをどうやって解放するのか」が解決するのであれば、コードを動的に生成しなくてもキャプチャしたデータ自体をそこに置けばいいだけ。 >>135
キャプチャしたデータ(またはそれへのポインタ)をコード以外のどこかに置くとして、それは関数ポインタ一つ(コードへのポインタをとるCのAPIにそのまま渡せる形)にはならないだろ。
何の話をしてるんだ? MS は mfc の頃から動的コード生成でやってだ記憶がある。
this をロードして jmp みたいな小さいコードを生成して Window Proc として使う。 >>139
コードだっつーの
関数ポインタ一つしか渡せないwindowprocにthisを渡すためにそうやってるんだよ。
なんで知らんのに反論するかなー >>140
ひょっとして各インスタンスにコードが含まれてるとか思ってる? w >>138
そのサンクらしきものはどこのセグメントに置くの? >>143
MFCのどのクラスに動的コード生成の実装が書いてんの? >>145
なんで急にキレるんですか?
あなたがソース読めとアドバイスしたからMFCのどのソースか聞いただけなのに。 理解しようという気持ちも理解する力もないのに質問すんなよ…
mfc ではやってたっけ?やってないんじゃないの?
というツッコミならともかく、
>>141>>142なんて思考力が虫以下だろ…どこのセグメントとかアホか
Win32 は古来よりフラットなリニアアドレスモデルだろ。
VirtualAlloc も知らなそうだし。 質問だと思ってる時点で低能確定やん w
まあセグメントと聞いてセグメントレジスタしか頭に思い浮かばない低能はROMってろ >古来よりフラットなリニアアドレスモデル
まさかそっちのセグメントに反応するとは予想外だった ■ このスレッドは過去ログ倉庫に格納されています