C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
IDE (VC++など)などの使い方の質問はその開発環境のスレにお願いします。
前スレ
C++相談室 part149
https://mevius.5ch.net/test/read.cgi/tech/1581974381/
このスレもよろしくね。
【初心者歓迎】C/C++室 Ver.105【環境依存OK】
http://mevius.5ch.net/test/read.cgi/tech/1556142878/
■長いソースを貼るときはここへ。■
http://codepad.org/
https://ideone.com/
[C++ FAQ]
https://isocpp.org/wiki/faq/
http://www.bohyoh.com/CandCPP/FAQ/ (日本語)
テンプレここまで
探検
C++相談室 part150
■ このスレッドは過去ログ倉庫に格納されています
2020/03/24(火) 00:04:33.93ID:YFRNwZnv
781デフォルトの名無しさん
2020/05/08(金) 12:06:11.41ID:Fn7VYFHg782デフォルトの名無しさん
2020/05/08(金) 12:18:21.10ID:Fn7VYFHg >>778
BlockingCollectionってどこにあります?
ぐぐったらC#のクラスは見つかりましたが
上に書いた通り、stop時の処理がまわりくどくなりそうなのを気にしてます
実行時のロジックがシンプルなやり方を追求したいです
BlockingCollectionってどこにあります?
ぐぐったらC#のクラスは見つかりましたが
上に書いた通り、stop時の処理がまわりくどくなりそうなのを気にしてます
実行時のロジックがシンプルなやり方を追求したいです
783843
2020/05/08(金) 12:23:41.84ID:UXU8nfWQ784デフォルトの名無しさん
2020/05/08(金) 12:39:35.76ID:N+8ZKU+/ 普通は終了を意味する番兵オブジェクトを用意するんじゃないの
キューの中身を最後まで処理して欲しいなら単に番兵を積めばいいし、無理矢理終わらせたいならキューを強制的に空にしてから番兵放り込めばいい
キューの中身を最後まで処理して欲しいなら単に番兵を積めばいいし、無理矢理終わらせたいならキューを強制的に空にしてから番兵放り込めばいい
785デフォルトの名無しさん
2020/05/08(金) 13:50:27.60ID:Fn7VYFHg >>784
なるほどそれだときれいに書けますね
runningフラグは不要にできると
しかしわりとクリティカルな処理を想定してるので
stopを呼ぶスレッドで(イベントオブジェクトの)解放処理が起るのは問題に
なるかもしれないです(例ではintですが実際はもうちょっと凝った構造体)
runningフラグ前提だときれいに書けないですかね?
なるほどそれだときれいに書けますね
runningフラグは不要にできると
しかしわりとクリティカルな処理を想定してるので
stopを呼ぶスレッドで(イベントオブジェクトの)解放処理が起るのは問題に
なるかもしれないです(例ではintですが実際はもうちょっと凝った構造体)
runningフラグ前提だときれいに書けないですかね?
786デフォルトの名無しさん
2020/05/08(金) 17:13:05.00ID:+t+L26mC こんなんでいいのでは。running2回チェックは避けられそうにないなあ。チェックよろ
start() {
{
lock()
running = true
}
run(loop)
}
stop() {
{
lock()
running = false
}
notify()
join()
}
loop() {
lock()
while(true) {
cond_wait(!empty() or !running)
if (!running) {
break
}
pop()
}
}
start() {
{
lock()
running = true
}
run(loop)
}
stop() {
{
lock()
running = false
}
notify()
join()
}
loop() {
lock()
while(true) {
cond_wait(!empty() or !running)
if (!running) {
break
}
pop()
}
}
787デフォルトの名無しさん
2020/05/08(金) 17:29:10.43ID:NOJZfKLR スレッド動作トリガーはcond 1個にして
スレッド内で、キューやrunningフラグを見る
スレッド内で、キューやrunningフラグを見る
788デフォルトの名無しさん
2020/05/08(金) 17:32:31.56ID:NOJZfKLR Windowsみたいな高機能な同期が有れば
イベント、タイマー、ファイルアクセス、ネットワーク通信
などなど色々な物を同時にトリガーに出来る
linux系はその辺が貧弱
スレッドを動かす為のスレッドが必要になったりする
イベント、タイマー、ファイルアクセス、ネットワーク通信
などなど色々な物を同時にトリガーに出来る
linux系はその辺が貧弱
スレッドを動かす為のスレッドが必要になったりする
789デフォルトの名無しさん
2020/05/08(金) 17:46:30.97ID:+t+L26mC >>788
全部selectやepollでまとめて待てるけど、winはもっと高機能なん?
全部selectやepollでまとめて待てるけど、winはもっと高機能なん?
790デフォルトの名無しさん
2020/05/08(金) 18:43:53.40ID:NOJZfKLR yes
791デフォルトの名無しさん
2020/05/08(金) 19:10:58.40ID:Fn7VYFHg >>786
インデントつけました
void loop() {
lock()
while (true) {
cond_wait(!empty() or !running)
if (!running) {
break
}
pop()
}
}
cond_waitの前にrunningみなくて大丈夫ですかね?
startの直後loopが始まる直前でstopが呼ばれた場合cond_waitって起きます?
インデントつけました
void loop() {
lock()
while (true) {
cond_wait(!empty() or !running)
if (!running) {
break
}
pop()
}
}
cond_waitの前にrunningみなくて大丈夫ですかね?
startの直後loopが始まる直前でstopが呼ばれた場合cond_waitって起きます?
792デフォルトの名無しさん
2020/05/08(金) 19:27:16.63ID:V12mYFi1793デフォルトの名無しさん
2020/05/08(金) 20:07:48.20ID:DADrWmcq >>791
cond.waitはブロックする前に一度条件式を確認する動きになってる。
条件式が初めからtrueであればそもそもブロッキングをしないからcond.waitの前にrunningをみなくても大丈夫だと思う
cond.waitはブロックする前に一度条件式を確認する動きになってる。
条件式が初めからtrueであればそもそもブロッキングをしないからcond.waitの前にrunningをみなくても大丈夫だと思う
794デフォルトの名無しさん
2020/05/08(金) 20:36:08.72ID:Fn7VYFHg795デフォルトの名無しさん
2020/05/08(金) 22:51:30.97ID:Fn7VYFHg もうひとつ質問させてください
>>774 のrunningはstd::atomic_boolにする必要はあります?
C言語だとこの手の変数はvolatileにすると思うのですが
C++ならatomicでしょうか?
上の方でatomicのこといろいろ書いてありますがこの場合はどうなんでしょう?
>>774 のrunningはstd::atomic_boolにする必要はあります?
C言語だとこの手の変数はvolatileにすると思うのですが
C++ならatomicでしょうか?
上の方でatomicのこといろいろ書いてありますがこの場合はどうなんでしょう?
796デフォルトの名無しさん
2020/05/09(土) 00:53:16.27ID:8wHk9BWj void Foo::pushReq(const XXXReq& req)
{
EnterCriticalSection(&m_csec);
{
if (!m_bTerminate) {
m_requests.push(req);
SetEvent(m_hEvtNewRequest);
}
}
LeaveCriticalSection(&m_csec);
}
{
EnterCriticalSection(&m_csec);
{
if (!m_bTerminate) {
m_requests.push(req);
SetEvent(m_hEvtNewRequest);
}
}
LeaveCriticalSection(&m_csec);
}
797デフォルトの名無しさん
2020/05/09(土) 00:57:33.61ID:8wHk9BWj bool Foo::popReq(XXXReq& req)
for (;;) {
if (!m_bInOperation) {
// イベント待機
WaitForSingleObject(m_hEvtNewRequest, INFINITE);
if (m_bTerminate) {
return false;
}
m_bInOperation = true;
} else {
EnterCriticalSection(&m_csec);
{
if (m_requests.empty()) {
m_bInOperation = false;
// 今入っているイベントはbInProcess中に入ったもので
// 明らかに古いのでリセット
ResetEvent(m_hEvtNewRequest);
} else {
// 要求があればpopして処理
req = m_requests.front();
m_requests.pop();
}
}
LeaveCriticalSection(&m_csec);
if (m_bInOperation) {
// 処理すべきリクエスト有り
break;
}
}
}
}
for (;;) {
if (!m_bInOperation) {
// イベント待機
WaitForSingleObject(m_hEvtNewRequest, INFINITE);
if (m_bTerminate) {
return false;
}
m_bInOperation = true;
} else {
EnterCriticalSection(&m_csec);
{
if (m_requests.empty()) {
m_bInOperation = false;
// 今入っているイベントはbInProcess中に入ったもので
// 明らかに古いのでリセット
ResetEvent(m_hEvtNewRequest);
} else {
// 要求があればpopして処理
req = m_requests.front();
m_requests.pop();
}
}
LeaveCriticalSection(&m_csec);
if (m_bInOperation) {
// 処理すべきリクエスト有り
break;
}
}
}
}
798デフォルトの名無しさん
2020/05/09(土) 01:01:13.28ID:8wHk9BWj ウィンドーズの同期APIの仕様により
同期API呼び出し時点であらゆる変数のメモリへの書込みとメモリからの読み込みが完了するので
とくにvolatileは不要
なはず、
同期API呼び出し時点であらゆる変数のメモリへの書込みとメモリからの読み込みが完了するので
とくにvolatileは不要
なはず、
799デフォルトの名無しさん
2020/05/09(土) 06:06:39.41ID:1JWVR6vl >>795
>>786のようにrunningの更新をlockで保護するのであればatomic_boolにする必要はないと思うよ
void stop() {
std::lock_guard<std::mutex> lk(mtx);
running = false;
cond.notify_all();
}
お手本でも普通のboolを使ってる
https://cpprefjp.github.io/reference/condition_variable/condition_variable.html
https://cpprefjp.github.io/article/lib/how_to_use_cv.html
>>786のようにrunningの更新をlockで保護するのであればatomic_boolにする必要はないと思うよ
void stop() {
std::lock_guard<std::mutex> lk(mtx);
running = false;
cond.notify_all();
}
お手本でも普通のboolを使ってる
https://cpprefjp.github.io/reference/condition_variable/condition_variable.html
https://cpprefjp.github.io/article/lib/how_to_use_cv.html
800デフォルトの名無しさん
2020/05/09(土) 11:17:56.00ID:KZFWOt7Z >>799
loop()内のrunningは毎度メモリから読まれる必要があるので
C言語ならvolatileにすると理解しています
つまりループ内で最適化されてしまわないようにするためだと思います
これがC++だと仕様的にもともと問題ないのでしょうか?
逆に最適化がかかりにくくなってしまう気がします
ただ手元で実装したものは最適化かけていても確かに期待通り動いています
loop()内のrunningは毎度メモリから読まれる必要があるので
C言語ならvolatileにすると理解しています
つまりループ内で最適化されてしまわないようにするためだと思います
これがC++だと仕様的にもともと問題ないのでしょうか?
逆に最適化がかかりにくくなってしまう気がします
ただ手元で実装したものは最適化かけていても確かに期待通り動いています
801デフォルトの名無しさん
2020/05/09(土) 12:59:28.79ID:1JWVR6vl >>800
POSIX準拠のシステムでは同時アクセスを防ぐ書き方(mutexによるlockとかstd::atomicによるstore/loadとか)
をすれば自動的にメモリ同期(メモリへのフラッシュ)が行われる作りになっていてvolatileとかを気にする必要がないらしい
https://yupo5656.hatenadiary.org/entry/20040618/p2
POSIX準拠のシステムでは同時アクセスを防ぐ書き方(mutexによるlockとかstd::atomicによるstore/loadとか)
をすれば自動的にメモリ同期(メモリへのフラッシュ)が行われる作りになっていてvolatileとかを気にする必要がないらしい
https://yupo5656.hatenadiary.org/entry/20040618/p2
802デフォルトの名無しさん
2020/05/09(土) 13:06:53.14ID:8wHk9BWj >>800
>>774のコードの全体の当否はおくとして
while()の中でlockしているのであればlockされるブロックに出入りする際に
>runningは毎度メモリから読まれる
が実現されるからrunningフラグはvolatile無しでもむ無問題、
C++の標準的なlockの仕様は知らんがlockに出入りするときに
CPUのライトキューやリードキューに未処理のライトコマンドやリードコマンドが乗ったままだと
正しいロックにならないから普通のlockの実装ではメモリバリアを行う
メモリバリアはコンパイラに対してはイントリンシックな関数か何かとして定義されており、
それらの呼び出しのときコンパイラは空気を読んでレジスタに乗ったままの変数を放置しないはず…
(変数に対する副作用がある関数呼び出しとみなす
>>774のコードの全体の当否はおくとして
while()の中でlockしているのであればlockされるブロックに出入りする際に
>runningは毎度メモリから読まれる
が実現されるからrunningフラグはvolatile無しでもむ無問題、
C++の標準的なlockの仕様は知らんがlockに出入りするときに
CPUのライトキューやリードキューに未処理のライトコマンドやリードコマンドが乗ったままだと
正しいロックにならないから普通のlockの実装ではメモリバリアを行う
メモリバリアはコンパイラに対してはイントリンシックな関数か何かとして定義されており、
それらの呼び出しのときコンパイラは空気を読んでレジスタに乗ったままの変数を放置しないはず…
(変数に対する副作用がある関数呼び出しとみなす
803デフォルトの名無しさん
2020/05/09(土) 13:16:40.60ID:2pLCfdPK POSIXスレッドはetchになってからようやく使い物になった
woody以前は酷い出来だったのは酔い思い出
woody以前は酷い出来だったのは酔い思い出
804デフォルトの名無しさん
2020/05/09(土) 13:46:46.99ID:8wHk9BWj しかし以下のような実装のときrunningにvolatileが本当に要らないかどうかわわからん…
void bar() { (内部でlockを行う) }
====↓↓↓異なる翻訳単位↓↓↓====
void foo {
bool running = false; // runningはローカル変数
while (running) {
bar(); // 一見runninguへの副作用が考えられないシグネチャ
}
}
どうやっているのかは知らんが、ウィンドーズの同期系API(上の例でbar()にあたる)は
うまいことやってくれる(と思う!
void bar() { (内部でlockを行う) }
====↓↓↓異なる翻訳単位↓↓↓====
void foo {
bool running = false; // runningはローカル変数
while (running) {
bar(); // 一見runninguへの副作用が考えられないシグネチャ
}
}
どうやっているのかは知らんが、ウィンドーズの同期系API(上の例でbar()にあたる)は
うまいことやってくれる(と思う!
806デフォルトの名無しさん
2020/05/09(土) 13:52:06.16ID:8wHk9BWj よく考えたら上のコードではrunningへのポインタを他のスレッドが知っていることもありえないから、
そういう意味でvolatile不要(最適化上等)か…orz
一方、runningがグローバル変数なら、異なる翻訳系で定義された関数を呼び出した後に、
runningは改めてメモリから読まれることはコンパイラが生成するコードの規定の動作なので
volatile不要
まとめると、runningがグローバル変数でありかつ同期目的の関数内でメモリフェンスしており、
かつそこが毎回通る限り、runningにvolatileは不要
そういう意味でvolatile不要(最適化上等)か…orz
一方、runningがグローバル変数なら、異なる翻訳系で定義された関数を呼び出した後に、
runningは改めてメモリから読まれることはコンパイラが生成するコードの規定の動作なので
volatile不要
まとめると、runningがグローバル変数でありかつ同期目的の関数内でメモリフェンスしており、
かつそこが毎回通る限り、runningにvolatileは不要
807デフォルトの名無しさん
2020/05/09(土) 13:53:07.30ID:VRhqXw8t >>804
running がローカル変数なら bar() での副作用は無理だから volatile の有無によらず foo() は空にできちゃうのでは?
running がローカル変数なら bar() での副作用は無理だから volatile の有無によらず foo() は空にできちゃうのでは?
808デフォルトの名無しさん
2020/05/09(土) 13:54:44.10ID:VRhqXw8t (リロードしてなかった・・・)
>>806 つまり volatile が必要なケースは無いね?
>>806 つまり volatile が必要なケースは無いね?
809デフォルトの名無しさん
2020/05/09(土) 14:01:00.47ID:8wHk9BWj810デフォルトの名無しさん
2020/05/09(土) 14:22:58.21ID:KZFWOt7Z811デフォルトの名無しさん
2020/05/09(土) 14:32:48.74ID:KZFWOt7Z >>802
> >>800
> >>774のコードの全体の当否はおくとして
> while()の中でlockしているのであればlockされるブロックに出入りする際に
> >runningは毎度メモリから読まれる
> が実現されるからrunningフラグはvolatile無しでもむ無問題、
一度目はメモリから読まれるのは確実だと思います
ただループの場合、2度目のリードからはコンパイラが最適化をかけて
一度目の値を使いまわす可能性があると思います
void loop()
{
unique_lock lock(mtx);
auto r = running
while (r) {
....
}
}
と置き換えてしまう可能性があるのでは?ということを心配しています
私のC言語開発の経験ではこの場合はvolatileにするのが鉄則でした
c++のコンパイラはかしこくrunningは都度メモリから読み出すべしと判断していると
なるとその判定はどうやって行っているのでしょう?
一律にローカル変数以外はメモリから呼び出すわけではないと思います
(それだとかなり性能が落ちると思います)
> >>800
> >>774のコードの全体の当否はおくとして
> while()の中でlockしているのであればlockされるブロックに出入りする際に
> >runningは毎度メモリから読まれる
> が実現されるからrunningフラグはvolatile無しでもむ無問題、
一度目はメモリから読まれるのは確実だと思います
ただループの場合、2度目のリードからはコンパイラが最適化をかけて
一度目の値を使いまわす可能性があると思います
void loop()
{
unique_lock lock(mtx);
auto r = running
while (r) {
....
}
}
と置き換えてしまう可能性があるのでは?ということを心配しています
私のC言語開発の経験ではこの場合はvolatileにするのが鉄則でした
c++のコンパイラはかしこくrunningは都度メモリから読み出すべしと判断していると
なるとその判定はどうやって行っているのでしょう?
一律にローカル変数以外はメモリから呼び出すわけではないと思います
(それだとかなり性能が落ちると思います)
812デフォルトの名無しさん
2020/05/09(土) 14:56:31.18ID:8wHk9BWj >>811
コンパイラ視点で見れば中身のわからないcond.wait()と言う関数呼び出しが
グローバル変数runningに対する副作用を持たない(値を書き換えない)ことの保証が無いから、
cond.wait()をループ外にくくりだす最適化が行われることは普通は無い。 --- (A)
また、ソースコード上cond.wait()を呼び出した後にrunningを参照する箇所があれば、
普通はかならずメモリからrunningを読み直すコードが吐かれる --- (B)
普通でない場合というのはコンパイラがcond.wait()メソッドの中身まで知っていて
runningに対する副作用が無いと結論付ける場合が考えられるが、
それでもcond.wait()の中で
(1) メモリバリアを行っており、
(2) その意味をコンパイラが知っている
限り、コンパイラが「(cond.wait()呼び出しによる)runningに対する副作用が無い」と結論付けることはありえない --- (C)
というわけで、普通は(A)、(B)が成立するからrunningのvolatileは不要
(A)、(B)非成立な変に賢いコンパイラでも、(1)と(2)が成立するなら(C)が成立するからrunningのvolatileは不要
コンパイラ視点で見れば中身のわからないcond.wait()と言う関数呼び出しが
グローバル変数runningに対する副作用を持たない(値を書き換えない)ことの保証が無いから、
cond.wait()をループ外にくくりだす最適化が行われることは普通は無い。 --- (A)
また、ソースコード上cond.wait()を呼び出した後にrunningを参照する箇所があれば、
普通はかならずメモリからrunningを読み直すコードが吐かれる --- (B)
普通でない場合というのはコンパイラがcond.wait()メソッドの中身まで知っていて
runningに対する副作用が無いと結論付ける場合が考えられるが、
それでもcond.wait()の中で
(1) メモリバリアを行っており、
(2) その意味をコンパイラが知っている
限り、コンパイラが「(cond.wait()呼び出しによる)runningに対する副作用が無い」と結論付けることはありえない --- (C)
というわけで、普通は(A)、(B)が成立するからrunningのvolatileは不要
(A)、(B)非成立な変に賢いコンパイラでも、(1)と(2)が成立するなら(C)が成立するからrunningのvolatileは不要
813デフォルトの名無しさん
2020/05/09(土) 15:08:39.92ID:1JWVR6vl814デフォルトの名無しさん
2020/05/09(土) 15:08:46.08ID:KZFWOt7Z >>812
それはstd:::condition_variableを使った場合に限定していますか?
基本的にpthreadのwrapperだと思うのですが、仮にコンパイラがそれを特別扱いしているとすると
pthreadをダイレクトに使った場合はどうなりますか?
あと客観的な文献を示してほしいです
それはstd:::condition_variableを使った場合に限定していますか?
基本的にpthreadのwrapperだと思うのですが、仮にコンパイラがそれを特別扱いしているとすると
pthreadをダイレクトに使った場合はどうなりますか?
あと客観的な文献を示してほしいです
815デフォルトの名無しさん
2020/05/09(土) 15:11:10.97ID:KZFWOt7Z816デフォルトの名無しさん
2020/05/09(土) 15:20:05.99ID:1JWVR6vl817デフォルトの名無しさん
2020/05/09(土) 15:38:10.36ID:8wHk9BWj >>814
>それはstd:::condition_variableを使った場合に限定していますか?
いいえ
>pthreadをダイレクトに使った場合はどうなりますか?
どう使うつもりかわわからんが、コンパイラに中身を知りようが無い関数の
呼び出しがループ内に生じる限り同じ話
>客観的な文献を示してほしいです
(1) 変数に対する副作用がある(かもしれない)関数がループ外にくくりだされないこと
コンパイラはソースコードをオブジェクトコードに翻訳する際、
ソースコードに書かれたアルゴリズム(有限ステップで終わる&非同期要素無し)の
動作結果を変えてはならない。この原則はコンパイラの教科書に書いてあるし常識と言っても過言ではない
で、変数に対する副作用がある(かもしれない)関数の不適切な最適化はこの原則にひっかかる
(2) 少なくともMSVCがメモリバリアの意味を知っている根拠
https://docs.microsoft.com/ja-jp/cpp/intrinsics/readwritebarrier?view=vs-2015
これ、VS2010までは非推奨ではなかったし、サンプルコードも載っていたが無くなってたorz
>それはstd:::condition_variableを使った場合に限定していますか?
いいえ
>pthreadをダイレクトに使った場合はどうなりますか?
どう使うつもりかわわからんが、コンパイラに中身を知りようが無い関数の
呼び出しがループ内に生じる限り同じ話
>客観的な文献を示してほしいです
(1) 変数に対する副作用がある(かもしれない)関数がループ外にくくりだされないこと
コンパイラはソースコードをオブジェクトコードに翻訳する際、
ソースコードに書かれたアルゴリズム(有限ステップで終わる&非同期要素無し)の
動作結果を変えてはならない。この原則はコンパイラの教科書に書いてあるし常識と言っても過言ではない
で、変数に対する副作用がある(かもしれない)関数の不適切な最適化はこの原則にひっかかる
(2) 少なくともMSVCがメモリバリアの意味を知っている根拠
https://docs.microsoft.com/ja-jp/cpp/intrinsics/readwritebarrier?view=vs-2015
これ、VS2010までは非推奨ではなかったし、サンプルコードも載っていたが無くなってたorz
818デフォルトの名無しさん
2020/05/09(土) 15:40:22.80ID:VRhqXw8t >>814
標準スレッドライブラリを使った前後の読み書きについては、
ライブラリ関数呼び出し( lock/unlock など)が提供するスレッドをまたぐ "synchronize with" 関係と
スレッド内での, "sequenced before/after" による前後関係とをつないだ
"inter-thread happens before" 関係(順序付け)に基づく挙動が規定されている。
https://timsong-cpp.github.io/cppwp/n4659/intro.multithread#intro.races-9
>811 のような書き換えは許されない。
規格化以前の pthread などをダイレクトに使った場合は >>812 の挙げるような
「事実上問題にならない」に頼ることになり、これに volatile を加えても「事実上問題にならない」の
範疇であることに変わりはない。
問題の可能性が減ったり、実際に起こっていた問題の解決につながることはあっただろうけどね。
これについては「客観的な文献」といったものが無かったことも規格化の動機になっただろう。
https://isocpp.org/wiki/faq/cpp11#cpp11-specific-goals
> - Machine model and concurrency ? provide stronger guarantees for and better facilities
> for using modern hardware (e.g. multicores and weakly coherent memory models). ...
標準スレッドライブラリを使った前後の読み書きについては、
ライブラリ関数呼び出し( lock/unlock など)が提供するスレッドをまたぐ "synchronize with" 関係と
スレッド内での, "sequenced before/after" による前後関係とをつないだ
"inter-thread happens before" 関係(順序付け)に基づく挙動が規定されている。
https://timsong-cpp.github.io/cppwp/n4659/intro.multithread#intro.races-9
>811 のような書き換えは許されない。
規格化以前の pthread などをダイレクトに使った場合は >>812 の挙げるような
「事実上問題にならない」に頼ることになり、これに volatile を加えても「事実上問題にならない」の
範疇であることに変わりはない。
問題の可能性が減ったり、実際に起こっていた問題の解決につながることはあっただろうけどね。
これについては「客観的な文献」といったものが無かったことも規格化の動機になっただろう。
https://isocpp.org/wiki/faq/cpp11#cpp11-specific-goals
> - Machine model and concurrency ? provide stronger guarantees for and better facilities
> for using modern hardware (e.g. multicores and weakly coherent memory models). ...
819デフォルトの名無しさん
2020/05/09(土) 16:27:23.02ID:KZFWOt7Z >>817
なるほど
つまりc/c++コンパイラの最適化において、
副作用がある(pure functionでない)関数があると、それをまたいだ
リオーダーや値の流用をすることはない
当然メモリバリアを張るcond(pthreadも含む)は副作用ありなので
これがループ中に存在する場合はrunningは毎度メモリから読み出されることになる
ということですね
非常によくわかりました
なるほど
つまりc/c++コンパイラの最適化において、
副作用がある(pure functionでない)関数があると、それをまたいだ
リオーダーや値の流用をすることはない
当然メモリバリアを張るcond(pthreadも含む)は副作用ありなので
これがループ中に存在する場合はrunningは毎度メモリから読み出されることになる
ということですね
非常によくわかりました
820デフォルトの名無しさん
2020/05/09(土) 16:30:24.63ID:KZFWOt7Z >>817
しかし、この場合volatileが不要といえることはわかりましたが、
これはあくまで副作用あり関数の存在に依存しています
と考えると一般的にはvolatileはつけておく方習慣の方がやはり無難だと思いますがいかがでしょう?
(c++ならatomicに置き換えるとして)
しかし、この場合volatileが不要といえることはわかりましたが、
これはあくまで副作用あり関数の存在に依存しています
と考えると一般的にはvolatileはつけておく方習慣の方がやはり無難だと思いますがいかがでしょう?
(c++ならatomicに置き換えるとして)
821デフォルトの名無しさん
2020/05/09(土) 16:33:07.67ID:KZFWOt7Z822デフォルトの名無しさん
2020/05/09(土) 16:41:37.74ID:8wHk9BWj >>819
レジスタに載ったままな変数の流用はともかく、
リオーダーは副作用がある(pure functionでない)関数をまたいでも特に阻害されないんじゃね;
リオーダーの効果はプログラムの実行に関して普通の状況では透過的なので、普通の状況でコンパイラがそれをやめさせる理由が無い
普通でない状況としては>>714みたく同一データに対する複数コアからの同時アクセスがありえるケース
(コンパイラが知りようが無い非同期事象が生じるケース)があるが、
これは(ユーザーコードかライブラリの)プログラマがメモリバリアを明示的に書き、
コンパイラが空気を呼んでその前後の変数の流用も抑止することで処置される
と思うが真実は知らん
気分としてはあくまで>>800の立場であって非同期の問題に関してはノーコメント
事実として出来上がったプログラムが正しく動いているなら問題ないのじゃガッハッハッハ、
レジスタに載ったままな変数の流用はともかく、
リオーダーは副作用がある(pure functionでない)関数をまたいでも特に阻害されないんじゃね;
リオーダーの効果はプログラムの実行に関して普通の状況では透過的なので、普通の状況でコンパイラがそれをやめさせる理由が無い
普通でない状況としては>>714みたく同一データに対する複数コアからの同時アクセスがありえるケース
(コンパイラが知りようが無い非同期事象が生じるケース)があるが、
これは(ユーザーコードかライブラリの)プログラマがメモリバリアを明示的に書き、
コンパイラが空気を呼んでその前後の変数の流用も抑止することで処置される
と思うが真実は知らん
気分としてはあくまで>>800の立場であって非同期の問題に関してはノーコメント
事実として出来上がったプログラムが正しく動いているなら問題ないのじゃガッハッハッハ、
823デフォルトの名無しさん
2020/05/09(土) 16:43:21.63ID:8wHk9BWj824デフォルトの名無しさん
2020/05/09(土) 17:00:35.76ID:1JWVR6vl >>820
複数スレッドで共有する変数を読み込む以上絶対にlockなりatomicなりを使うわけだから必ず副作用あり関数が存在する
複数スレッドで共有する変数を読み込む以上絶対にlockなりatomicなりを使うわけだから必ず副作用あり関数が存在する
825はちみつ餃子 ◆8X2XSCHEME
2020/05/09(土) 18:56:58.72ID:MmeKQuXy >>820
見かけ上の挙動が仕様通りだったらどうコンパイルしてもよいというのが言語としての基本的なルール。
https://timsong-cpp.github.io/cppwp/n3337/intro.execution
昔は並列実行に関する動作モデルの既定がなかったので、
既定にないことをするプログラムを書いたときに
最適化で除去されたり順序が入れ替わったりしてもそれは仕様通りだったんだよ。
volatile はプログラムとして書いてある通りのことを (たとえ観測できなくても) 実際の動作にも
反映させろというヒントをコンパイラに伝えるものではあるけど、
言語仕様の記述に用いられる抽象機械と実際の実行環境が完全にマッピングできるわけでもない
から volatile が具体的にどう影響するかってのは分からん。
言語仕様外のことをするときのために用意されていると考えてもいい。
つまり、ロックやアトミックまわりの仕様で規定されていることなら volatile を付けようが付けまいが
その通りになるし、既定されていないことなら volatile を付けても言語仕様として得られる保証は何もない。
処理系として言語仕様以上の保証を付けているということはあるだろうけど。
見かけ上の挙動が仕様通りだったらどうコンパイルしてもよいというのが言語としての基本的なルール。
https://timsong-cpp.github.io/cppwp/n3337/intro.execution
昔は並列実行に関する動作モデルの既定がなかったので、
既定にないことをするプログラムを書いたときに
最適化で除去されたり順序が入れ替わったりしてもそれは仕様通りだったんだよ。
volatile はプログラムとして書いてある通りのことを (たとえ観測できなくても) 実際の動作にも
反映させろというヒントをコンパイラに伝えるものではあるけど、
言語仕様の記述に用いられる抽象機械と実際の実行環境が完全にマッピングできるわけでもない
から volatile が具体的にどう影響するかってのは分からん。
言語仕様外のことをするときのために用意されていると考えてもいい。
つまり、ロックやアトミックまわりの仕様で規定されていることなら volatile を付けようが付けまいが
その通りになるし、既定されていないことなら volatile を付けても言語仕様として得られる保証は何もない。
処理系として言語仕様以上の保証を付けているということはあるだろうけど。
826デフォルトの名無しさん
2020/05/09(土) 18:58:03.61ID:KZFWOt7Z >>824
確かに、正しく排他制御しているのならばそれはいえそうです
確かに、正しく排他制御しているのならばそれはいえそうです
827デフォルトの名無しさん
2020/05/09(土) 19:14:29.09ID:TBKnesgm volatileは簡潔に言うとregisterの逆の作用だね
828デフォルトの名無しさん
2020/05/09(土) 22:27:01.93ID:IGvav/BT volatileはコンパイラに、コード通り読み書きを行うコードを吐けと指示するだけ
CPUが勝手に順番を変えたりしないようにCPUに指示をする命令は別途行わなければならない
x86の場合は何もしなくて良い場合が多く
ARMの場合は追加しなければならない場合が多い
CPUが勝手に順番を変えたりしないようにCPUに指示をする命令は別途行わなければならない
x86の場合は何もしなくて良い場合が多く
ARMの場合は追加しなければならない場合が多い
829デフォルトの名無しさん
2020/05/09(土) 22:31:00.74ID:TVkAIoUw いいえ、単に昔からGCCが糞なだけです。
830デフォルトの名無しさん
2020/05/09(土) 22:42:09.15ID:G+eyUkVB 最近日本式のやつが再注目されてるじゃないか。
それは欧州式のやつのことじゃないか?
それは欧州式のやつのことじゃないか?
831843
2020/05/09(土) 23:22:12.13ID:NXsGMAUL >>824
片方は書き出し、もう一方は読み出しだけなら排他制御しなくてもアトミックでありさえすれば大丈夫だし、そういう実装はそれなりにあるよ
片方は書き出し、もう一方は読み出しだけなら排他制御しなくてもアトミックでありさえすれば大丈夫だし、そういう実装はそれなりにあるよ
832デフォルトの名無しさん
2020/05/10(日) 02:46:29.69ID:EdgxbLB4 可変長引数テンプレートから型の文字列を組み合わせて配列を定数化して取り出せるようにするために
以下のようなコードを書いたのですが、
template<typename ... ComponentsData> struct ComponentTypeGroup {
static constexpr std::size_t ComponentCount = sizeof...( ComponentsData );
static constexpr std::string_view TypeTexts[ComponentCount];
template<typename Type> constexpr void TypeGroupText( std::size_t _uIndex ) {
TypeTexts[_uIndex] = Detail::Nameof<Type>(); // 定数文字列を生成する関数です。
}
template<typename First, typename Second, typename ... ArgTypes> constexpr void TypeGroupText( std::size_t _uIndex ) {
TypeGroupText<First>( _uIndex );
TypeGroupText<Second, ArgTypes...>( _uIndex + 1 );
}
constexpr ComponentGroup(){ TypeGroupText<ComponentsData...>( 0 ); }
};
constexpr ComponentGroup()で「型指定子がありません」と出てコンパイルエラーが取れません。
何故このエラーが出ているのかがいまいちわからず、途方に暮れています。
誰かご教授いただけないでしょうか?
以下のようなコードを書いたのですが、
template<typename ... ComponentsData> struct ComponentTypeGroup {
static constexpr std::size_t ComponentCount = sizeof...( ComponentsData );
static constexpr std::string_view TypeTexts[ComponentCount];
template<typename Type> constexpr void TypeGroupText( std::size_t _uIndex ) {
TypeTexts[_uIndex] = Detail::Nameof<Type>(); // 定数文字列を生成する関数です。
}
template<typename First, typename Second, typename ... ArgTypes> constexpr void TypeGroupText( std::size_t _uIndex ) {
TypeGroupText<First>( _uIndex );
TypeGroupText<Second, ArgTypes...>( _uIndex + 1 );
}
constexpr ComponentGroup(){ TypeGroupText<ComponentsData...>( 0 ); }
};
constexpr ComponentGroup()で「型指定子がありません」と出てコンパイルエラーが取れません。
何故このエラーが出ているのかがいまいちわからず、途方に暮れています。
誰かご教授いただけないでしょうか?
833デフォルトの名無しさん
2020/05/10(日) 02:51:01.26ID:KxiPn0ce ComponentTypeGroupのtypoでなくて?
834デフォルトの名無しさん
2020/05/10(日) 03:20:50.69ID:s7BT3+bq まずそのインターコンチネンタルホテルみたいな長ったらしい名前やめろ
835デフォルトの名無しさん
2020/05/10(日) 03:25:28.56ID:wE52EU/R 古いコードの一時的メンテのため、stdとstd::tr1をC++11で混在させて使う話なんですが、
元々C++11以前のコンパイラ用に書かれた
using namespace std;
using std::tr1::shared_ptr;
shared_ptr<Hoge> hoge = ...
みたいなコードをC++11でビルドすると、C++11には std::shared_ptr があり ambiguous エラーになりますよね。
最初 share_ptr を std::shared_ptr ということにしてビルドしようかと思ったら、ところどころ std::tr1::shared_ptr と
フル宣言してあり面倒なことが判明。なので shared_ptr は std::str1::shared_ptr とみなす方針に戻りました。
なので using namepace std; を保持しつつ shared_ptr を std::tr1::shared_ptr としてビルドしたいんですが、
それって可能でしょうか? 例えば using namespace std; で std::shared_ptr を除外するようなことってできます?
古いコードを出来るだけいじらずビルドしたい、というのが一番のポイントですw
元々C++11以前のコンパイラ用に書かれた
using namespace std;
using std::tr1::shared_ptr;
shared_ptr<Hoge> hoge = ...
みたいなコードをC++11でビルドすると、C++11には std::shared_ptr があり ambiguous エラーになりますよね。
最初 share_ptr を std::shared_ptr ということにしてビルドしようかと思ったら、ところどころ std::tr1::shared_ptr と
フル宣言してあり面倒なことが判明。なので shared_ptr は std::str1::shared_ptr とみなす方針に戻りました。
なので using namepace std; を保持しつつ shared_ptr を std::tr1::shared_ptr としてビルドしたいんですが、
それって可能でしょうか? 例えば using namespace std; で std::shared_ptr を除外するようなことってできます?
古いコードを出来るだけいじらずビルドしたい、というのが一番のポイントですw
836デフォルトの名無しさん
2020/05/10(日) 03:46:29.57ID:oMXEUzlE 単に#include<tr1/memory>してstd::tr1::shared_ptrのusingを消すんではあかんの?
新しいコンパイラではstd::shared_ptrとstd::tr1::shared_ptrって同じものでしょ
新しいコンパイラではstd::shared_ptrとstd::tr1::shared_ptrって同じものでしょ
837デフォルトの名無しさん
2020/05/10(日) 05:06:37.17ID:wE52EU/R >>836
using std::tr1::shared_ptrを取るとただのshared_ptrはstd::shared_ptrになります (using namespace std)。
すると今回の場合、
std::tr1::shared_ptr<Hoge> boge; // たまにちゃんと名前空間を使ってる宣言がある
boge = shared_ptr<Hoge>(new Hoge);
みたいなコードが駄目になるようですが。
std::tr1::shared_ptrとstd::shared_ptrはとりあえず名前としては違うんじゃないですか? 違うとコンパイラー
が認識しているように見えますが。
using std::tr1::shared_ptrを取るとただのshared_ptrはstd::shared_ptrになります (using namespace std)。
すると今回の場合、
std::tr1::shared_ptr<Hoge> boge; // たまにちゃんと名前空間を使ってる宣言がある
boge = shared_ptr<Hoge>(new Hoge);
みたいなコードが駄目になるようですが。
std::tr1::shared_ptrとstd::shared_ptrはとりあえず名前としては違うんじゃないですか? 違うとコンパイラー
が認識しているように見えますが。
838デフォルトの名無しさん
2020/05/10(日) 11:05:22.30ID:sYQDYC6t 淫乱チンポメンタルヘルス?
>>838
それ、面白いと思ったのですか?
それ、面白いと思ったのですか?
840デフォルトの名無しさん
2020/05/10(日) 11:25:22.96ID:5OK5MvZd841デフォルトの名無しさん
2020/05/10(日) 11:49:35.32ID:sYQDYC6t インサートチンポレンタルホテル!
842デフォルトの名無しさん
2020/05/10(日) 12:12:32.27ID:6Ru0pW3/ >>840
> namespace std { namespace tr1 = ::std; }
おお、これで std名前空間の中に tr1 のエイリアスを定義できる感じですか?
結果 std::tr1 は ::std -> std を指す、と。
> namespace std { namespace tr1 = ::std; }
おお、これで std名前空間の中に tr1 のエイリアスを定義できる感じですか?
結果 std::tr1 は ::std -> std を指す、と。
843デフォルトの名無しさん
2020/05/10(日) 12:19:21.29ID:KGOVLWXM844デフォルトの名無しさん
2020/05/10(日) 12:49:31.40ID:uBqrUzQt コンストラクタの綴り間違えているんじゃね?
何れにしろconstexpr static memberをコンストラクタやメンバ関数内で初期化は出来ないと思うが。
やるならstatic constexpr member関数の戻り値で初期化するとかしないと
何れにしろconstexpr static memberをコンストラクタやメンバ関数内で初期化は出来ないと思うが。
やるならstatic constexpr member関数の戻り値で初期化するとかしないと
845デフォルトの名無しさん
2020/05/10(日) 13:27:57.96ID:EdgxbLB4846デフォルトの名無しさん
2020/05/10(日) 17:58:29.32ID:Pcmn53iK namespace std { inline namespace tr1 {} }
#include <memory>
#include <memory>
847デフォルトの名無しさん
2020/05/10(日) 18:02:33.35ID:LV0wbaaG std名前空間に何かするのは基本的に未定義動作に繋がるのでやめようね
848デフォルトの名無しさん
2020/05/10(日) 18:15:05.57ID:3khm8gAC カラオケで自分が歌いながら録音したカセットテープを爆音でドライブしながら女に聞かすようなものだな
これどう?オレが歌ってんだけど?的な
これどう?オレが歌ってんだけど?的な
849デフォルトの名無しさん
2020/05/10(日) 18:53:54.11ID:0gvZuU03 >>848
それ良くやる
それ良くやる
850デフォルトの名無しさん
2020/05/10(日) 19:05:46.41ID:m91+LxrO 女「さむっ・・・オープンカーかと思ったわ」
851デフォルトの名無しさん
2020/05/10(日) 19:30:31.12ID:657zsB50 >>846
どうもです、しかし自分の環境だとうまくいかないですね。gcc 5.4.0 です。
error: ‘shared_ptr’ is not a member of ‘std::tr1’
std::tr1::shared_ptr<Hoge> hoge;
^
とりあえず>>840を試してみたんですが、やってみるとインクルードファイルが意外と多く、そのほとんどに
#include <tr1/なんちゃら> があり、これらを全て tr1無しにする必要が。
コンパイラーのフラグ等でtr1無しをインクルードするようなことってできましたっけ? うわーさらに脇道。
とりあえず上記を書き直すとした場合、変更量が増えるにつれ、やっぱ全部のファイルで素直にtr1を
全部置換したほうがいいんじゃないかという気が徐々に... っておい > 自分
>>847
御意。ちなみにstdは普通の名前空間とは違うということですか?
しかし namespace の使い方の勉強になりました。いやあ色々思い付かれてすごいです。
どうもです、しかし自分の環境だとうまくいかないですね。gcc 5.4.0 です。
error: ‘shared_ptr’ is not a member of ‘std::tr1’
std::tr1::shared_ptr<Hoge> hoge;
^
とりあえず>>840を試してみたんですが、やってみるとインクルードファイルが意外と多く、そのほとんどに
#include <tr1/なんちゃら> があり、これらを全て tr1無しにする必要が。
コンパイラーのフラグ等でtr1無しをインクルードするようなことってできましたっけ? うわーさらに脇道。
とりあえず上記を書き直すとした場合、変更量が増えるにつれ、やっぱ全部のファイルで素直にtr1を
全部置換したほうがいいんじゃないかという気が徐々に... っておい > 自分
>>847
御意。ちなみにstdは普通の名前空間とは違うということですか?
しかし namespace の使い方の勉強になりました。いやあ色々思い付かれてすごいです。
852デフォルトの名無しさん
2020/05/10(日) 19:41:27.78ID:5OK5MvZd853デフォルトの名無しさん
2020/05/10(日) 21:40:19.38ID:LV0wbaaG854デフォルトの名無しさん
2020/05/11(月) 06:44:06.91ID:WjiQACf7 使われないけど標準なんです。
855デフォルトの名無しさん
2020/05/11(月) 10:06:29.78ID:ihiMo4aq 関数内で宣言した変数を途中でconst化したいときってどうやったらいいですか?
関数というのはこんな感じです
void func() {
int a;
〜aの値を設定する百行くらいの処理〜
〜aを用いたメイン処理。途中で誤ってaを変更しないようにしたい〜
}
aをconstで宣言しておいてaを設定するところはconst_castするというのはやりたくないです。
初期化用関数initializeを作って const int a = initialize(〜); とするしか方法はないですか?
できればそれもしたくないのですが
関数というのはこんな感じです
void func() {
int a;
〜aの値を設定する百行くらいの処理〜
〜aを用いたメイン処理。途中で誤ってaを変更しないようにしたい〜
}
aをconstで宣言しておいてaを設定するところはconst_castするというのはやりたくないです。
初期化用関数initializeを作って const int a = initialize(〜); とするしか方法はないですか?
できればそれもしたくないのですが
856デフォルトの名無しさん
2020/05/11(月) 10:09:55.63ID:MhpqGE2N &a にアクセスする権限を readonly にするとか
環境依存だろうけど
環境依存だろうけど
857デフォルトの名無しさん
2020/05/11(月) 10:13:30.52ID:vLTbwMZ+ >>855
a に設定する値を求める処理を関数化して、その戻り値でconstのaを初期化する。
a に設定する値を求める処理を関数化して、その戻り値でconstのaを初期化する。
858デフォルトの名無しさん
2020/05/11(月) 10:14:29.69ID:vLTbwMZ+ あ、したくないって書いてあったね
859デフォルトの名無しさん
2020/05/11(月) 10:18:49.75ID:m+8/4tPw860デフォルトの名無しさん
2020/05/11(月) 10:53:26.16ID:ihiMo4aq861デフォルトの名無しさん
2020/05/11(月) 11:22:30.96ID:rmb+jfMY どうしてもなら、こうだな
int a_;
//a_で初期化処理をする
int const& a = a_;
//aはconst
int a_;
//a_で初期化処理をする
int const& a = a_;
//aはconst
862デフォルトの名無しさん
2020/05/11(月) 11:26:38.90ID:rmb+jfMY アホらしいけど、こんな手も考えられる
struct sample
{
int a;
void func() {
//初期化処理
std::as_const(*this).func();
}
void func() const {
//aをconst扱い
}
};
struct sample
{
int a;
void func() {
//初期化処理
std::as_const(*this).func();
}
void func() const {
//aをconst扱い
}
};
863デフォルトの名無しさん
2020/05/11(月) 11:30:27.88ID:tShYcoYg 後半をlambda化すれば
aをコピーキャプチャしてmutableにしなければconstになる
aをコピーキャプチャしてmutableにしなければconstになる
864はちみつ餃子 ◆8X2XSCHEME
2020/05/11(月) 11:37:55.81ID:pGzfxkdL GCC や Clang の拡張を使ってよいならこういう書き方は出来る。
void func() {
const int a = ({int a; a=1; a;}); // ブロック内で初期化処理を書いて値を返す
std::cout << a << std::endl; // メイン処理
}
たぶん >>855 が考えている用途だとこれが一番楽なんじゃなかろうかと思うんだけど、
標準ではないってのはやっぱりネックになってくるな。
void func() {
const int a = ({int a; a=1; a;}); // ブロック内で初期化処理を書いて値を返す
std::cout << a << std::endl; // メイン処理
}
たぶん >>855 が考えている用途だとこれが一番楽なんじゃなかろうかと思うんだけど、
標準ではないってのはやっぱりネックになってくるな。
865デフォルトの名無しさん
2020/05/11(月) 11:54:09.12ID:WjiQACf7 constウイルスw
866デフォルトの名無しさん
2020/05/11(月) 12:17:38.26ID:oXH9qZIA ポインタ使えばいいのに
const付きのポインタを宣言だけしといて初期化のスコープ内でアドレス渡せばいい
const付きのポインタを宣言だけしといて初期化のスコープ内でアドレス渡せばいい
867デフォルトの名無しさん
2020/05/11(月) 12:21:06.88ID:vUv7mwxB >>860
RAII教に入信しておとなしく初期化ラムダ関数を使うがよい
RAII教に入信しておとなしく初期化ラムダ関数を使うがよい
868デフォルトの名無しさん
2020/05/11(月) 14:54:10.97ID:NX9zuntd IT掲示板群 ttp://x0000.net/forum.aspx?id=15
学術の巨大掲示板群 - アルファ・ラボ ttp://x0000.net
数学 物理学 化学 生物学 天文学 地理地学
IT 電子 工学 言語学 国語 方言 など
simulationライブラリで純粋な関数式プログラミングをする
ttp://x0000.net/topic.aspx?id=3631-0
UIライブラリ (C#, 2D) を作ったよ
ttp://x0000.net/topic.aspx?id=3688-0
連続と離散を統一した!
ttp://x0000.net/topic.aspx?id=3709-0
4Dエンジン
ttp://x0000.net/topic.aspx?id=3677-0
matrixのライブラリ
ttp://x0000.net/topic.aspx?id=3711-0
ある強力なFor関数
ttp://x0000.net/topic.aspx?id=3630-0
SQLライブラリ
ttp://x0000.net/topic.aspx?id=3675-0
学術の巨大掲示板群 - アルファ・ラボ ttp://x0000.net
数学 物理学 化学 生物学 天文学 地理地学
IT 電子 工学 言語学 国語 方言 など
simulationライブラリで純粋な関数式プログラミングをする
ttp://x0000.net/topic.aspx?id=3631-0
UIライブラリ (C#, 2D) を作ったよ
ttp://x0000.net/topic.aspx?id=3688-0
連続と離散を統一した!
ttp://x0000.net/topic.aspx?id=3709-0
4Dエンジン
ttp://x0000.net/topic.aspx?id=3677-0
matrixのライブラリ
ttp://x0000.net/topic.aspx?id=3711-0
ある強力なFor関数
ttp://x0000.net/topic.aspx?id=3630-0
SQLライブラリ
ttp://x0000.net/topic.aspx?id=3675-0
869デフォルトの名無しさん
2020/05/11(月) 14:54:11.07ID:NX9zuntd IT掲示板群 ttp://x0000.net/forum.aspx?id=15
学術の巨大掲示板群 - アルファ・ラボ ttp://x0000.net
数学 物理学 化学 生物学 天文学 地理地学
IT 電子 工学 言語学 国語 方言 など
simulationライブラリで純粋な関数式プログラミングをする
ttp://x0000.net/topic.aspx?id=3631-0
UIライブラリ (C#, 2D) を作ったよ
ttp://x0000.net/topic.aspx?id=3688-0
連続と離散を統一した!
ttp://x0000.net/topic.aspx?id=3709-0
4Dエンジン
ttp://x0000.net/topic.aspx?id=3677-0
matrixのライブラリ
ttp://x0000.net/topic.aspx?id=3711-0
ある強力なFor関数
ttp://x0000.net/topic.aspx?id=3630-0
SQLライブラリ
ttp://x0000.net/topic.aspx?id=3675-0
学術の巨大掲示板群 - アルファ・ラボ ttp://x0000.net
数学 物理学 化学 生物学 天文学 地理地学
IT 電子 工学 言語学 国語 方言 など
simulationライブラリで純粋な関数式プログラミングをする
ttp://x0000.net/topic.aspx?id=3631-0
UIライブラリ (C#, 2D) を作ったよ
ttp://x0000.net/topic.aspx?id=3688-0
連続と離散を統一した!
ttp://x0000.net/topic.aspx?id=3709-0
4Dエンジン
ttp://x0000.net/topic.aspx?id=3677-0
matrixのライブラリ
ttp://x0000.net/topic.aspx?id=3711-0
ある強力なFor関数
ttp://x0000.net/topic.aspx?id=3630-0
SQLライブラリ
ttp://x0000.net/topic.aspx?id=3675-0
870デフォルトの名無しさん
2020/05/11(月) 14:58:27.84ID:vIusnhzf871デフォルトの名無しさん
2020/05/11(月) 15:01:13.87ID:vIusnhzf 変数名として灰化の用にすればわかりやすいかもしれない。
物理学では、a0 は、a の初期値を意味することが多いので、学術的にも分かり易い。
int a0;
(a0 に対する初期化処理);
const int &a = a0;
(a を読み取るだけの処理);
物理学では、a0 は、a の初期値を意味することが多いので、学術的にも分かり易い。
int a0;
(a0 に対する初期化処理);
const int &a = a0;
(a を読み取るだけの処理);
872デフォルトの名無しさん
2020/05/11(月) 15:02:26.79ID:rdm6Cg4w873デフォルトの名無しさん
2020/05/11(月) 15:28:25.94ID:ZT/W926b a0がスコープから消えないのは片手落ち
どのみちトリッキーなことして読み手を混乱させることしない方がいい
単純にスコープを一画面に収まるぐらいに短くしろ
どのみちトリッキーなことして読み手を混乱させることしない方がいい
単純にスコープを一画面に収まるぐらいに短くしろ
874デフォルトの名無しさん
2020/05/11(月) 15:33:11.51ID:rmb+jfMY キモい個人サイトの宣伝をNG登録っと
875デフォルトの名無しさん
2020/05/11(月) 16:16:12.98ID:rdm6Cg4w876デフォルトの名無しさん
2020/05/11(月) 16:35:15.76ID:gZOsi0FN 処理を途中で止めて、変数とかvectorの中身を確認したりするソフト知らない?
877デフォルトの名無しさん
2020/05/11(月) 16:37:43.30ID:rdm6Cg4w >>873
以下のようにすればその問題も一応は解決する。
int a;
(a に対する初期化処理);
{
const int &a0 = a;
const int &a = a0; // 外の a とは別の a を宣言。
(a を読み取るだけの処理);
}
さらに
#define XXX(_x_) const int &_x_##0 = _x_; const int &_x_ = _x_##0
というマクロを導入すれば、
int a;
(a に対する初期化処理);
{
XXX(a);
(a を読み取るだけの処理);
}
でいける。
以下のようにすればその問題も一応は解決する。
int a;
(a に対する初期化処理);
{
const int &a0 = a;
const int &a = a0; // 外の a とは別の a を宣言。
(a を読み取るだけの処理);
}
さらに
#define XXX(_x_) const int &_x_##0 = _x_; const int &_x_ = _x_##0
というマクロを導入すれば、
int a;
(a に対する初期化処理);
{
XXX(a);
(a を読み取るだけの処理);
}
でいける。
878デフォルトの名無しさん
2020/05/11(月) 16:38:36.67ID:rdm6Cg4w879デフォルトの名無しさん
2020/05/11(月) 16:59:50.23ID:rmb+jfMY >>876
Visual Studioに標準で入ってるよ
Visual Studioに標準で入ってるよ
880デフォルトの名無しさん
2020/05/11(月) 17:54:34.39ID:ihiMo4aq やはり大人しく初期化関数使います
いろいろとアドバイスありがとうございました
いろいろとアドバイスありがとうございました
■ このスレッドは過去ログ倉庫に格納されています
