C++相談室 part163
レス数が1000を超えています。これ以上書き込みはできません。
!extend:checked:vvvvv:1000:512
!extend:checked:vvvvv:1000:512
↑同じ内容を3行貼り付けること
次スレは>>980が立てること
無理なら細かく安価指定
※前スレ
C++相談室 part162
https://mevius.5ch.net/test/read.cgi/tech/1667194175/
VIPQ2_EXTDAT: checked:vvvvv:1000:512:: EXT was configured 皆さまあけましておめでとうございます
今年もよろしくお願いします
今日も今日とて相談がございます
基底クラスのポインタを格納できるコンテナに押し込んだ派生クラスへのポインタから、その派生クラスのインスタンスをユニークポインタで生成し、それを規定クラスのユニークポインタに押し込んで使いたいです
std::vector<Base*> BaseCnt;
Driv1 Driv1_;
Driv2 Driv2_;
Driv3 Driv3_;
BaseCnt.push_back(&Driv1_);
BaseCnt.push_back(&Driv2_);
BaseCnt.push_back(&Driv3_);
~数々の名誉ある処理を挟んで……~
std::unique_ptr<Base> BaseUni;
BaseUni=どうにかして実体をユニポで生成する関数(BaseCnt.back());
BaseUni->Update();//ここで望んでいる挙動はDriv3のオーバーライドでございます
上記の、どうにかして実体をユニポで生成する関数、が実現できなくて困っています
template<typename T>
std::unique_ptr<Base>&& theFunc(T*t)
{
return std::make_unique<T>();
}
で行けるのかなと思いましたがいけませんでした(^^)……
そもそも基底クラスに押し込んであるため、T型で受けると基底型になってしまいます(^_^)……
どうにかして派生クラスにメモリを確保し、かつそれを規定クラスのユニークポインタに押し込めないものでしょうか?
このままでは年が越せない……
どうかおしえてください
私はc++プリミティブの混乱予約型言語でございます…… うだうだ長文書かんとコード全体をwandboxなりideoneなりに書いてくれや
Updateにvirtualついてないとかだったら張っ倒すぞ 確かに問題点が複数ある&想定する挙動が曖昧で分からないから、コメントのしようがない。
最小限の再現コードと期待する挙動をwandboxなりideoneなりに書いてからの話だな。 >>3 こんなこと?
class Base;
using Base_Ptr = std::unique_ptr <Base>;
struct Base {
virtual ~Base () = default;
virtual Base_Ptr construct () const = 0;
};
struct Driv3: Base {
virtual Base_Ptr construct () const
{
return std::make_unique <Driv3> ();
}
};
int main () {
std::vector<Base*> BaseCnt;
Driv3 Driv3_;
BaseCnt.push_back(&Driv3_);
std::unique_ptr<Base> BaseUni;
BaseUni=BaseCnt.back()->construct ();
return 0;
} コメントは対応するコードの前後どちらに書く?
// 別行なら前だが
int i = 0;
int i = 0; // 同じ行なら後?
同じ行に書いてたものが変更で長くなって別行に移したら前後が入れ替わるの気持ち悪くない? エディタの都合に合わせてたら人間向けのメモでなくなる grepなどによるキーワード検索がやりやすくなるよう意識したら良い
ctagsや統合開発環境みたいな高性能な検索機能がなくても探しやすいのが理想 >>7
> 同じ行に書いてたものが変更で長くなって別行に移したら前後が入れ替わるの気持ち悪くない?
修正が面倒だとは思うけど気持ち悪くはないな 気持ち悪いつか、気になるものは後で見ても気になるから
そりゃ気持ちよく直すでしょ 気持ちはわかるよ
差分ツールで見たとき差分として出ちゃうからな コメントの移動だけが (一回分のコミットとして) 差分に出るのだったらちょっと嫌な感じだけど、
周辺のコードを修正した結果として行が長くなりすぎないようにコメントの位置も変えるという話なんだから
差分ツールで見たらどうせそこらへん一帯が出るわけでしょ。
その中にコメントのちょっとした移動が含まれるかどうかなんて気にするようなもんじゃないと思うけどなぁ。 書くべきものは横着しないで書け
書かなくてよいもので油売るな
これだけのこと ところで私がよく使う言語に Scheme があって Scheme ではセミコロンから改行までがコメントになるんだけど、
Scheme の (というか主な LISP 系言語の) 習慣では状況によってセミコロンの数を変えるし
フォーマッタはセミコロンの数に基づいてインデントを変える。
https://www.gnu.org/software/emacs/manual/html_node/elisp/Comment-Tips.html
便利な習慣だと思うんだけど他の言語ではこういうのを見ないなぁ。 何なら、本文の途中で折り返して、行末コメントにするわ コメントを同じ行に書くことはほとんどないかなあ
そもそも1行コメントで済む処理っどんなの? コメント必要なのかな?
俺は処理の塊の前に意図など含めて長文コメントを書いてる 行内コメントはどこまで下げるのかと言う問題が、
foo(); // xxxとyyyを更新
assertIm(xxx) + Im(yyy) == 0); // 変換結果は共役のはず
--------->| 40 カラム?
-------------->| 56 カラム?
オートフォーマッター任せにしたいが定説が無さげ
perltidyだとなんか隣接する行コメは64カラム目か、それを超える場合は一番長いのに合わせてくれるが
コードの長さがかなり不ぞろいなとき罪悪感みある、
a(); // (aのコメント)
b(); // (bのコメント)
very_long_long_long_name_function_call_to_baz(long_long_name_param, 1234567); // (←のコメント) あとif文の行内コメントも悩む、
if (a==b)
{
}else ・コメントは41桁目から
・一行は95桁迄
が俺のマイルール あとif文の行内コメントも悩む、
if (a==b) // ここには分岐条件のコメントを書くべき?
{ // ここにはthen節のコメントを書くべき?
...
}
else // else節のコメントはここでええのか?
{ // それともここか?
....
}
どう書くかによってブレーススタイルやオートコードフォーマッタとの
共存具合が変わってくるので行内コメントはいろいろ問題が多いシステム、 >>21
// a と b が等しいなら...
if (a==b){
// 等しい時の処理
...
// 等しくないなら...
} else {
// 等しくない時の処理
}
が俺のマイルール
※ いないと思うけどコメントの内容にはツッコミ厳禁ね >>23
ありゃ行内コメントか...
if (a==b){ // a と b が等しいなら...
... //. 等しい時の処理
} else { // 等しくないなら...
... // 等しくない時の処理
}
確かに通常のコメントと行内コメントが混在するとモヤモヤするのはある >>26
手癖で使えるなじんだ言語ってひとつくらいはあるもんだろ。
俺はそれが Scheme だってだけで、やってることは自動でネットを巡回したりだとか
ファイルを条件別にフォルダに仕分けしたりだとかとかいった普段のちょっとした自動化とかだよ。 新しいパソコンのメリットを特に感じていなかったけど、大物をビルドすると圧倒的に速いな。 何か間違えたのかと思ったわ。
あまりにも早すぎて。 >>16
/** */ や /// を普通のコメントとは区別してドキュメンテーションに使うでしょ?
c++だったらDoxygenとか >>32
へー。
そういうツールを使ったことなかった。 >>16
フォーマッタと相性悪すぎん?
Python といい見た目の違いに意味持たせるのカスでしかない >>34
意味によってセミコロンの個数を変えるとそれをフォーマッタが見た目 (インデント) に反映するという話なんだけど 自分が理解できないものは使えない奴とか言ういつもの人でしょ
スルーでいいかと >>36
すまん Scheme には普通の文末にセミコロン付ける訳では無いのね、そこ知らなくて勘違いしたわ
C++ に取り入れるならセミコロン以外の記法にする訳ね >>37
必要性を感じていないものをいらんというだけだ
スルーしてもらえるならこっちも助かる
いらんつーてるものをしつこくすすめてくるな 忘れてもらっちゃ困るのは
C++界は新しい機能に前向きだ
待ってましたという新機能にはみんな飛びつく
凝り固まろうとしてるのと違う
特にC++11以後は断じて違う 誰もお前に勧めてなんてないし自意識過剰すぎるだろw C++11でshared_ptrが導入されて、C++に対するJava・C#の優位性がひとつ消滅したよな 10年以上も前のことを何を今更って感じもするし
std::shared_ptr以前からスマートポインタは
一般的だったから事実誤認のような気もする
特にC#が登場した2000年にはスマートポインタの利用は一般的だった
Java登場の1995年当時を知る人はいるかな? >>44
> 一般的だったから事実誤認のような気もする
C++スレに書き込む人にとってはもちろんそうだろうけど、C++やらないプログラマにとってはそうではなかった
理解が広まるのに時間がかかる モノとしては誰でも知ってたけど、標準に入ってるかどうかってやっぱりだいぶ違うんだよな
プロダクトでの使いやすさとか >>44
1995年にはまだスマポは一般的でなかったと思う
デストラクタにdelete書きまくってた記憶がある >>44 47
c++で言うなら前身のboost::shared_ptrの初出が1998年。
その前身のcounted_ptrの最初の提案は1994年だって。(rejectされたけど) 標準ライブラリのみで外部依存ありませんは結構な強みになるからな 以下の記事、プログラマ脳なら神様の定義の変化を重視するよなあ。あるか、ないかじゃなくて。
【神様はいる? いない?】古代の人々は神をどう考えたのか?(ダイヤモンド・オンライン) - Yahoo!ニュース
https://news.yahoo.co.jp/articles/621899c69768ec530aa5377fed89908dc3eef8d4 懐かしいなboost
みんな直接WG21へ提案持っていくようになってすっかり立ち位置が微妙になっちゃった そうか? 言語機能に改定が必要なことならともかく
ライブラリは実績があるほうが通しやすいし、
標準に取り込まれなくても細かな便利機能がある Boost が衰退したとは感じないな。
サードパーティのライブラリを導入する手続きが面倒というのはよくある話だから
そういう面でもカバー範囲が広い Boost の出番は多いんじゃないの。 単純に必要な便利機能はあらかたC++標準の方に取り込まれてて
もうマイナーやマニアックな機能かゴミしか残ってないから使う機会なくなったわ
なんかこれ今でも便利だよってのある? >>53
他の言語ではとっくの昔に標準化されているXMLやJSONのパーサーが標準化されたら便利になると思うよ >>53
asioとか標準には入ってないんじゃない?
serializationもたまに使う >>53
小物だとlexical_castは便利だけどこれも標準にないのでは?
統計検定するのにMath Libraryの分布関数もちょこちょこ使う うっかり標準化して負の遺産になってしまったiostreamでの失敗の知見のうえに今のC++があるってのはわかる ところでiostreamに変わるioを作って
標準に入れようという動きはないんですか? さすがに入出力の書式化を標準ライブラリとして用意しないわけにもいかんからな。
良いのが出来るまで先送りとは言えないんだからそのとき出来たものを入れるのはしょうがないんじゃないの。 >>60
私が把握してないけかもしれないけれどストリームの基本構造を変えようという大きな動きはない。
C++20 から書式化 (オブジェクトを文字列表現にする) は std::format として切り出されて、
書式の情報は std::formatter 型で扱うのでグローバルな状態に影響を与えるマニピュレータを使う必要はなくなった。 「作業ディレクトリ」という概念はプロセス全体でひとつでしたっけ。これはOS依存ですかね。
スレッド処理実行中に作業ディレクトリが変わるのは許容範囲かな >>62
へーstd::formatなんてのもあるんですね
ちょっと眺めてみたけどcstdioとも
boost::formantともまた違うようですね std::format の設計は Rust の std::fmt::Display と似てる感じがするね。 iostream はよくあんなもん公開する勇気が有ったな 当時はC with Classesなんて研究をしてる人が珍しくて
やってる人のところへ見物に来る人がぞろぞろいたんだよ
禿にとって味方をつくることも大事な仕事で
先行きがまだ見えない試みも怯まず果敢に攻める必要があった
その当時の作品を今さら未来人がドヤ顔で揶揄しても
聞いてるのは当時の人じゃなく同じ未来人だぞ
おまえ自身がどんな批判に晒されるのか怖くないの?
・・・だから匿名掲示板なのか 失笑 いや、発表当時から微妙な反応だったよ
ユーザーが求めてたのはオブジェクト指向で、
あんな実装じゃない そういう手前味噌なおも鋳込みが激しいのもこの界隈だわな
おまえさんのようなシュトロハイム型のやつの受け流し方もみんな憶えてる そんなに不満なら何で自分で作らんの?
皆不満なら公開したら支持を集められるよ PowerShellのパイプに似たコレジャナイ感でしょうかね
なお、PowerShellのリダイレクトはさらなる魔改造のために温存されている模様 std::formatは整数が%d、浮動小数点が%f、文字列が%sのprintfに近い書式でよかったのに… >>72
PowerShell のパイプって特に変じゃ無いような気がするが... パイプで渡すものがオブジェクトの配列なだけならまだしも、
要素数が0と1の時だけ特別な処理がかかるのは使い勝手を損ねてるだけだぞ >>75
> 要素数が0と1の時だけ特別な処理がかかる
なにそれ? 何を今更と思ったけど iostream 叩いとけばわかってる感出るってことなんですかね >>80
それはある
実用上困ってないくせに叩いてるバカ多い 実用上困ったことがない程度しかio使ってないのに養護するバカが他人をバカ呼ばわりして笑える 実用上どう困るのかを強い説得力で話すやつを見かけないな >>83
そりゃ実用上は困らんよ
iostreamなんて使わずに普通にprintfとかでやるし... マジで不満なら作ったらどうだ? IOくらい余裕でできるやろ? printf は型システム的にガバガバすぎるだろ。
書式と実引数が食い違っててもコンパイル時に検出されないこともあるし。 はちみつはいつもprintfをdisってるが、printfには捨て難い便利さがある。 >>90
補足すれば、cout系はメンドクサイ。書くのが非効率。 仕方ないじゃん
当時はいいと思っちゃったんだから
何十年前ものアイデアを今の知見で考察しても仕方がない >>78
パイプに流したオブジェクトが
2つ以上なら配列
1つならオブジェクトそのまま
0個ならnull
になってパイプ先に渡る >>90
書きやすさは printf のほうがよいというのはわかる。
stream の文法がうっとうしいというのは俺だって思うよ。 それが良いとは思わん。 >>93
どんなコード書いてるの?
PS C:\> function x {
>> param([parameter(ValueFromPipeline=$true)]$p)
>> begin { Write-Host 'BEGIN' }
>> process { Write-Host "PROCESS: $p" }
>> end { Write-Host 'END'}
>> }
PS C:\> @() | x
BEGIN
END
PS C:\> @(1) | x
BEGIN
PROCESS: 1
END
PS C:\> @(1,2) | x
BEGIN
PROCESS: 1
PROCESS: 2
END
PS C:\>
普通に動いてるけど? iostreamは開発用ログの出力方法としては最適なんだけど、それ以上ではない感じ ログ出力用に<<をオーバーロードしたら
バイナリ出力は別の手段を考えることに……
namespaceでオーバーロード内容をさらに区分するとかはできるのかどうか知らんがやりたくない、、、 printfだと、見たいオブジェクトの型に気にすることなくログ関数に突っ込む、という他の言語で当たり前にできることができない。 formatのお陰でもう議論する意味なんてないんだが、
17以前は
誰かが状態を書き換えてるかもしれないからいちいち保存と復元が必要、
文字列とコードが入り乱れていて、i18n化できない&何が書かれているかひと目で分からないから
到底実用的じゃない
会社で20が使えるようになったらiostreamに戻るよ… >>97
いくつかやり方はあると思うけど……。
同じストリームにログ出力用の表現とバイナリ表現の両方を出力する可能性があるなら
適当なクラスに包むだけでいいと思う。
こんな感じで書ければ十分でしょ。
Foo bar;
std::cout << binary_style(bar) << std::endl;
std::cout << log_style(bar) << std::endl;
Haskell でこんな感じで処理を切り替えるのをよく見た気がする。
だいぶん前にちょっと遊んだだけなのであまり覚えてないけど。
出力先によって表現を変えるのならストリームクラスを定義してしまえばいいと思う。
直接的な入出力はストリームバッファがやっていて、
書式化を担当するストリームがストリームバッファを所有するという構造がある。
オブジェクトの表現形式が大きく変わるとしたら出力先ごとに変えるという用途だろうから
こっちのほうが使い勝手が良い場合も多いかもしれない。
雑な例だけどこんな感じ。
https://wandbox.org/permlink/3AaOGSXLNCw2aNJv はちみつは、何かに忖度しているように感じるな。
職人は自分の腕で食っていくので忖度しないが、就職先を探すサラリーマンは忖度する。 前にも書いたことがあるがワイはプログラミングは完全に趣味でやってるだけなので
プログラミングについて私が配慮すべき何者かなど存在せぇへんで。 なんか、何かにおべんちゃらしてるような感じを受ける。 >>103
職人でもないが、はちみつより餃子のほうが名前として大事なので
もしも職人という言葉を入れて改名するとしたら職人餃子にするわ。 >>95
@(...)は長さに関わらず強制的に配列にする書き方でしょ >>107
だからどんなコード書いてるのよ?
PS C:\> 1, 2 | x
BEGIN
PROCESS: 1
PROCESS: 2
END
PS C:\> 1 | x
BEGIN
PROCESS: 1
END
PS C:\> | x
発生場所 行:1 文字:1
+ | x
+ ~
空のパイプ要素は許可されていません。
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : EmptyPipeElement
@ なくても特に変な動きとは思えないけど? すみません拡張子についての質問ですけどここで聞いてもいいですか?
TeraPadでコードを入力し保存したらテキストドキュメントになってしまうのですが
どうやって拡張子を変えたらコマンドブロントと繋がるのでしょうか
すみません初心者なので分かりやすく教えてください
使ってるはwindows11です explorerの設定で拡張子を表示しろ
あとコマンドプロンプトのつもりで書いたんだろうけど「繋がる」なんて状況が想像できんので何をしたいか書け TeraPad は古いから、新し目の文字コードに対応していないので、サクラエディタを使え
プロは、VSCode, Windows Terminal などを使う >>110
繋がるってのがよく分からないけど、バッチを作りたいなら拡張子を表示してから .bat に変更。プログラムを組みたいなら .cp p に変更だけどmakeファイルを書くつもりはないだろうから、VisualStudioを入れよう >>110
他から指摘されているけど、初心者ならc++用の総合開発環境(IDE)をまずインストールして、IDEの初心者向けガイドをweb で検索して勉強するのが一番良い。
最近のWindowsだとVisual Studio Community Editionが初心者向きかね。 >>110
保存するときのファイル選択ダイアログで
[ファイルの種類]がテキスト文書になってるんじゃないか? C言語の重力付き4目並べです、ここのコードを簡略化したいです。
int SetXpos(int player) // コマの置き場所を入力または探して盤を更新,コマの置き場所(0-6)を返す
{
int xpos = 0; // コマの置き場所
if ((choice == 2 && player == 2) || (choice == 3 && player == 1)) // コンピュータとの対戦の場合に,コンピュータの手を計算
{
xpos = ComputeXpos(player);
printf("%sの番です\n", player == 1 ? "●" : "〇");
printf("コンピュータは%dに置きます\n", xpos);
}
else // 人間の手を選択
{
while (1)
{
printf("%sの番です\n", player == 1 ? "●" : "〇");
printf("どこに置きますか? 0-6の数字を半角で入力してください: ");
scanf_s("%d", &xpos);
if ((0 <= xpos && xpos < XMAX) && (num[xpos] < YMAX)) // 置ける場所かどうか判定
break;
printf("%dには置けません!\n", xpos);
}
}
board[xpos][num[xpos]++] = player;// コマをxpos列に置き,xpos列のコマ数を1増やす
return xpos;
} >>110
書いたコードをコンパイルしないとコマンドプロンプトには表示できないよ
その辺は入門書かサイトに書いてあると思う
あと繰り返す様で悪いがVisual Stdioを使うのが楽で良い 今後はWebフロントエンドの技術もできないと生きていけないよ @ if ((choice == 2 && player == 2) || (choice == 3 && player == 1))
A if (0 <= xpos && xpos < XMAX && num[xpos] < YMAX)
B board[xpos][num[xpos]++] = player;
C for (x = 0, y = ypos, n = 0; x < XMAX; x++)
D for (x = xpos, y = 0, n = 0; y <= ypos; y++)
E for (x = 0, y = ypos - xpos, n = 0; y < YMAX; x++, y++)
F for (x = xpos - ypos, y = 0, n = 0; x < XMAX; x++, y++)
G for (x = 0, y = xpos + ypos, n = 0; y >= 0; x++, y--)
H for (x = xpos + ypos - YMAX + 1, y = YMAX - 1, n = 0; x < XMAX; x++, y--)
の各条件文内でどーゆー計算、アルゴリズムがされてるか教えてくださる人いますか?? 宿題ならまず自分で考えてからどうしても分からない所だけ聞きに来い 例えば@だと、&&が論理積、||が論理和ということだと思うんですけど、演算子が分かってもその条件文内で何が行われているかとかが分からないので知りたい状態なんです。。 boostの存在意義ってことでいうと、マルチスレッドの並列ソートboost::sort::block_indirect_sort()が使えるのでLinuxなどは有益
Windowsの場合はVC++にconcurrency::parallel_buffered_sort()があるので使わないけど >>129
演算子の意味がわかっているなら分からない箇所なんてないでしょ。
そのような演算が必要になる意図のレベルで知りたいということなら式単体があっても読み取れない。 >126が宿題なら授業で演算子の評価順とか短絡評価とかやっているだろ。
ここで質問する前に授業ノートぐらい確認するなり先生に質問するなりしろよ。 普通に単にソートしたい場合はどんなコードになる?
方言なしで 質問なのですがintやdoubleといった単純な型のグローバル変数の初期化タイミングは
グローバルなオブジェクトの初期化タイミングより前であることが保証される?
多分 .dataセクションの初期化はグローバルなオブジェクトの初期化リストの実行より前だと思うんだけど
(そうでなければコンストラクタからC言語のライブラリを安心して呼べないということになる
規格的にそうなん? >>141
静的初期化と動的初期化に大別されている。
初期化子が定数 (定数式) のものは静的初期化で、
そうではないものが動的初期化。
静的初期化は動的初期化より先であることは言語仕様で保証される。 >>141
記憶が確かなら、c++の関数スコープのstatic変数は呼び出し時に初期化されることが保証されているので、初期化順を細かく決める必要がある場合は関数のstatic変数を使う。 >>142
レス㌧クスだいたいわかりた
この場合のconstexprの扱いがわからん……
ビルド時に定数に展開できたら静的初期化可能な範疇に含まれ得る気がするが
定数に展開で来なかったらどうするんじゃ、という気もする、
>>143
ガチで初期化順序を確実にしたい場合はシングルトンにすることを提唱する。
InterlockerCompareExchange()的なインターロック系の関数を使えばスレッドセーフにできる
(初期化済フラグがfalseならnewに進む、というのをアトミックにやる
関数スコープのstatic変数も似たような実装ではないかと予想、 訂正orz
×: (初期化済フラグがfalseならnewに進む、というのをアトミックにやる
○: (初期化済フラグがfalseならtrueにする、というのをアトミックにやって、false→trueに変化したときだけnewする とオモタがよく考えたら初期化済フラグがfalseならtrueに変化してからポインタpにnewされるまでの間に
別のスレッドが割り込んできてpを使おうとしたら破綻するからpを獲得できるまでスピンロック的に回ることが必要やったorz
ワイの答えはこれや……! 今さらだけどさ、以下Perlソースコードみたいに初期化以外の場所で複数の変数代入を一行で記述できたら楽だよね。
($a, $b) = (1, 2); >>144
c++11からブロックスコープを持つstatic変数初期化はスレッドセーフだから、手動でやる必要ないんじゃない? パターンマッチングとか単一化が欲しいという話じゃないの? 複数のことやってんだから複数行で書け
それかそんなにまとまり強いならラップしろ 俺もPerl使ってた頃に初期化で書いたことはあるけど、正直初期化以外での使い道ない気がする
rustのパターマッチは欲しい気がする >>147
Perl でできるかは忘れたけどこれで交換できるのは便利
($a, $b) = ($b, $a); int a, b;
tie(a, b) = tuple(1, 2);
tie(a, b) = tuple(b, a);
一応できなくはない。交換はswap(a, b)でいいけどね つauto [a, b] = tuple(1, 2) 解決方法を探しているんじゃなくて、言語仕様の変更提案なんだけど
改めてPerlだと以下のような感じ
use strict;
my ($a, $b) = ('AAA', 'BBB');
($a, $b) = ('YYY', 'ZZZ'); 戻り値が1個だけ
どれを戻り値にするかで迷う
この辺はC++の欠点だと思う >>159
構造体で戻せばいいですよ、KR2 から構造体の実体というかコピーが返ってきますから、それこそ3個でも4個でもお好きに 複数個の変数に対する初期化のワンライナー記述(本当は初期化なので代入ではないが)が許されるなら、再初期化もワンライナー記述できていいと思うんだ >>160
このためだけに構造体定義したりするとかアホの極みだろ... C++の新しい規格で複数個戻せるっての見た事あるが、気のせいか。 >>166
それは >>155 で言及 (?) されている構造化束縛 (structured bindings) のことでしょ。
返却値の数はあくまでもひとつ。
そのひとつを分割して初期値にすることが出来るのであって複数の返却値を返せるわけではない。 戻り値の型推論の規則が厳しいせいでtupleも微妙に使いづらい std::tie や std::tuple ってそんなに長い名前でもないし、
C++ のややこしい文法をもっとややこしくしてまで
専用の分割代入の構文が欲しいかな? 構造体のメンバ変数の再初期化を一行ですませたい需要、どうかな 要らないなぁ。
>>176
c++ならコンストラクタを定義するのが定石じゃない?
使い捨ての構造体ならtupleだし。 >>164
単に名前付きタプルが欲しくてもない、というか名前付きタプルは限りなく構造体に近いというだけですよ
新しいものに飛びつく前に K&R2 以来の伝統の重みを評価するべきでしょう、型推論を併用すれば記述量も抑えることができますよ
https://marycore.jp/prog/cpp/anonymous-struct-tuple/ >>184
今は >>159 の「複数の引数を返したい」要望に応える手段の話でしょ?
勝手に話題を広げないでね (^^) HOGE構造体インスタンス hogeのメンバfooとbarだけを再設定したい時に、hogeというインスタンス文字列を何度も書かずに済むような仕組みあればいいなあ
HOGE hoge = {0};
do_something(hoge);
hoge.[foo, bar] = [1, 2]; ClassName::enumElementという書き方で列挙体の要素を直接持ってこれるクラスを見かけたんですが
どうやってやってるんですか?
定義見てもよくわかりませんでした >>192
enum class と enum が別物だってのは知ってる? よくわからんがこれのことならenumは外のスコープに漏洩するから出来る
嫌ならenum classにする
class Foo{
public:
enum{HOGE, FUGA,};
};
int main(){
std::cout << Foo::HOGE;
} >>192
何を書いているのかいまいち分からん
struct ClassName {
enum {
enumElement
};
};
int main () {
std::cout << ClassName::enumElement << '\n';
return 0;
} 説明がへたくそですみません
ClassName::EnumName::elementと書かないといけないところを、
途中のEnumNameを省略して使えるようになってます
>>193
普通のenumでした 普通のenumならEnumName::つかないよ
トップレベルに置いたenumもEnumName::つかないでしょ >>196
だとしたら enum の列挙子のスコープはその列挙型のスコープと同じになるってだけ。
C のコードを持ってきて C++ でエラーにならないように配慮したんだと思う。 >>198
C の列挙子は C++ と違ってファイルスコープなので C で仕様に適合するものが C++ ではそうなない場合もあるけど……。
たとえばこういうのは C では通るが C++ ではエラー。
#include <stdio.h>
int main(void) {
struct foo { enum bar { baz } qux; };
int n = baz;
printf("%d\n", n);
} >>196
enumとenum classの違いは分かってるんだよね?
#include <iostream>
using namespace std;
struct ClassName {
enum enumElement {element};
enum class enumclassElement {element};
};
int main () {
cout << ClassName::element << '\n'
<< static_cast <int> (ClassName::enumclassElement::element) << '\n';
return 0;
} ああなるほど、何もしなくてもC形式のenumなら列挙名省略できるんですね
危険といわれている理由が分かりました
>>200
理解できてなかった😭 pythonのdecimalで2^256倍精度浮動小数点数の最大値を計算してみた。
https://ideone.com/aCP13Y
mpmathで検算もした。(桁数と先頭から千桁程度まで)
これらはC++だとどういうプログラムになるの?
メモリの容量から全桁の出力や検算は無理だと分かるが、できれば検算して戴きたい。 >>203
IEEE754準拠での値で計算してみた。
pythonのdecimalのlogでも検算したので多分合っていると思うが、
C++のプログラムだとどのように計算するのかな?という素朴な疑問です。
ideoneのc++だけでできる?
GMPあたりの任意精度パッケージとか必要になるのかな? C++標準ライブラリにはないから外部ライブラリに頼ることになる
ideoneがそれ用のライブラリを持ってるか知らんから頑張って探すしかない >>204
Boost Multiprecision Libraryあたりからお手軽かね。
他にあったっけ? C++って最初のバージョンはC言語で開発されましたか?
どこかその話のソースありませんか? cfrontはC++をCに翻訳するトランスレータ
というのはソースにならんか? C言語がC++から派生したというのは本当の話ですか? >>211
あなたがウソである証拠を示せばいいだけ。他者に証拠を求めてはいけない。 polymorphic_allocatorなんでコピーでresource伝播してくれないんだ・・・ >>211
C が始まったとき (1972 年) に C++ は無い。
C++ の前身である C with Classes の歴史の始まりは 1979 年で、そのときは
C のプリプロセッサとして書かれていたしあくまでも C の拡張と見なされていた。
後に C は C++ からかなり多くを取り入れることになるし
現在進行形で取り入れてもいるが、それを「派生」とは普通は呼ばない。
普通は呼ばないがそこらへんは言葉の定義の問題なので「派生」という言葉の
定義によっては無理すれば派生と呼べなくもないかもね。 >>209
>>210
CFrontなんてあったのですか
ヒントをありがとうございますた 名前付き引数標準化への動向って今どうなん
標準化はしないから各自勝手にやってねって感じ? class A{
public:
void operator () () {...}
};
class B : public A{
void func(){
ここでオペレータ()を呼びたいとき、(*this)()としたら呼べますが、this→()では呼べませんでした。
なぜでしょうか?
}
}; >>217
オペレータが左右にとるのは引数でthis->だけだと型が違うから? >>217
メソッド名でないから。
確認していないけど this->operator()() かと。 >>219様のやり方でできました皆様ありがとうございます すみませんもう一個質問させてください。
template<class T> class A{
public:
void f(){…}
};
template<class T> class B : public A<T>{
public:
void g(){f();}
};
というコードがあったとき、g 内の f が undeclared identifier だというエラーが出ますよね?
T が不明だからそうなるのだと説明されてるのを見たのですが、T はコンパイル時には確定してるのになぜダメなのでしょうか。 template<>class A<void>{};
のようにf()のない特殊化をされる
可能性があるってことさ >>224
void g(){A<T>::f();}
かね。理由は知らん。 >>226
*this→fとするにしてもA<T>::f()とするにしても長いなあと思ってしまいます
しかたがないので、Bはテンプレートじゃなくても良いように設計し直します this->f で済むだろうに、設計を変えるほどのことなのか。 >>226
それでは>>225のケースでコンパイルできない
void g(){typename f();}
では? >>226
それでは>>225のケースでコンパイルできない
void g(){typename f();}
では? すでに出てるけどA<T>が何者か確定してないので、
(B<int>とかの具体的な型が決まる時ではなく)テンプレート宣言時にエラーになる。
template<class T> class B : public A<T>{
using A<T>::f;
public:
void g(){f();}
};
のように親クラスA<T>にメンバーfがいることを宣言してやればテンプレート宣言自体は通る。 >>226,232も
>>225のケースで通るよな? テンプレート引数の取得ってどうやるんでしたっけ?
template<int N = 100> class A{
...
};
class B : public A<>{
ここから N (=100) が見えなくて困ってます。
}; Aの中にstatic const int nankanokosuu = N;とか定義しておく >>237
class B : public A<>{
template <template<int> class T, int N> int func(T<N>*) { return N; }
public:
void test()
{
cout << func(this);
}
}; >>238
templateって結局
template構文書くより
C言語で直で書いた方が
短くて性能も良いパターンが多い >>240
std::vectorユーザーが直書きとか不可能だろ。 小規模組み込みならそもそもnewやdeleteが使えない環境もある
Cより便利な記述が出来るからC++を使うというだけ >>240
>>237をC言語で直で書いたらどうなるの? >>240-241 テンプレートで性能やリソースを引き換えにすることなんか無いだろ。
・・・コンパイラの処理時間やメモリ消費の話ならあると思うけど、そういう話? マジレスすると C++ のテンプレで頑張るより
Nim 使った方が楽だし時間の節約になるよ >>246
組み込みのチープな環境のプログラムを組んで見ればわかるよ コードサイズは確かに増えるだろうが、性能は本当に測ったんか? >>248
「組み込みのチープな環境」で組んでたことあるけど、心当たり無いよ。
コードサイズだって手書きなりマクロなりでも必要量は同じになるだろうし。
何か例でも挙げてみてもらえる? >>246
テンプレート自体が実行性能の足を引っ張るってことはないが
個々の場面でより性能よく書けるはずのときに汎用部品で済ましてしまうってことはあるんじゃない?
そういうときでも個々の箇所をいじるよりは特殊化を足すだけで済むほうが楽だと思うが。 同じ結果になるように書けばそりゃ同じだろう
テンプレートで楽をすればコードは(一般的には)増える
memcpyで済む物が
型別にコードが発生したり
そういう所を気にすると結局楽が出来ない >>253
全て特殊化したら楽が出来ない
手間が増えるだけ 10種類のテンプレート引数で使うコードは
基本的には10個のバイナリが生成される
10種類手で書けば
当然コードの共通化を(人間が)考える >>255
必要なとき、効果があるときというのは当然の前提やが。
早すぎる最適化は諸悪の根源。 雑に書いて動くようになってから必要に応じてチューニングするもんやで。 >>257
リッチな環境前提の発想
初めから考えないといけないチープな環境もある 非力なハードで無理目なことをギリ勝負でやるときはアセンブラだろ 実際PC用コードの多くは組み込みでは全く使えず
ほとんどゼロからの開発になる >>260
もちろん必要ならアセンブラも使うが
CやC++による最適化が先 そういう環境ってそもそも標準ライブラリ揃ってなかったりしない?このスレで扱う必要ある? ぬるま湯環境しか知らないはちみつ
もう少し視野を広げた方が良いかと ワイは Z80 時代を生きたおじさんやぞ。
いまどきチープな組み込みでも最初からそんなカリカリにチューニングするのはそんなにないやろ。
無いとは言わんけど C++ の利用例としては例外的やわ。 カリカリチューンとぬるま湯コーディング
はちみつの頭の中はどっちかしか存在しないのかよ 人のことを小馬鹿にするだけなやつ出てけよ
プログラム技術の話の邪魔だ >>249が書いても説得力ゼロ
私は>>240でもないんだけど は? 俺は技術の話をしている
途中で根拠も挙げずに変なことを言うやつにチクリとやったが
貴様と違いそれだけじゃねえんだよボケ ないものは示せないもんな
せいぜいそんな言い訳にもなってないことを勝手にぬかしてろ
俺はこれから夕飯作らにゃならんし害虫が出てくのを待つ意味でもしばらく落ちる >>269
文脈見ろ。 それは >>265 に対して言ってんだぞ。 10種類とかで肥大するのはテンプレートなのにデカい関数作るからやろ
共通化できる部分は型に依存しない箇所だからテンプレートだろうと外に出せる 孤独のグルメじゃないけど「こういうのでいいんだよ」が最適解なこと多いよな、C/C++ C++20 のビューとやらを使ってみてるんだがデバッガで見づらすぎるのどうにかならん? >>237
template<int N = 100> class A{
static int nnn{N};
};
とすると、
A<123>::nnn が 123 になるはず。
static を付けない場合は、インタンスオブジェクトに対して取得できる。 >>286
ありがとう
誰も反応しなくてつまらんかった >>238
constexprの方が良いのかな?
static constexpr int nankanokosuu = N
>>285
constかconstexprかが必要
それはさておき初期化の位置に使っている中括弧 {N} はなに? 単に初期化で使ってるだけでしょ
今回はintであることが明白だから=でも()でも{}でも初期化できるけど
この手のコンパイル時に決まるやつはstatic constexpr一択だね
array<T, nankanokosuu> a;みたいに他のテンプレート引数に使える constexprにするとコンパイル時に解決出来ない項目は弾かれてしまうからconstのままでいい
知らないなら余計な修正は加えるな >>290
>>237のケースではtemplate引数のNを受けるのだから
コンパイル時に決まっているのでは?
コンパイル時に決まっていることが含意された
constexprの方が良いと思うけど? >>288
>それはさておき初期化の位置に使っている中括弧 {N} はなに?
C++11位から導入された初期化の一種。
a{N}は、a = N とほぼ同じだが、縮小変換をしないということや、
「どんな場所でも必ず使える」特徴があると言われており、Stroustrup氏
は、= よりも {} を推奨している。
また、{} による初期化は「直接初期化」と関係が深く、= による初期化は
「代入初期化」と関係が深い。 >>292
なるほどC++11以降なのね
「縮小変換」「直接初期化」「代入初期化」がよく分からんが >>293
「直接初期化(direct initialization)」とも関係しているが、
{}による初期化は、「一様初期化 (uniform initialization)」
で検索すると出て来やすい。
なお、ネットでdirect initializationを検索しても間違った定義が出てくるかも知れない。 C++17のcopy elisionでルール変わったね >>295
正しい定義かどうかは分からないが、一応、
「直接初期化」「コピー初期化」については、英語版の en.cppreference.com
をそれぞれ
「direct initialization」「copy initialization」
で検索すると「パターン」一覧が出てくるみたいだ。
ただし、一覧については「全てのパターン」かは定かではない。
例えば、direct initialization については、一覧には、new T(XXX) しか出てないが、
new T{XXX} でも良いハズ。 >>297
https://en.cppreference.com/w/cpp/language/direct_initialization
T object ( arg );
T object ( arg1, arg2, ... ); (1)
T object { arg }; (2) (since C++11)
T ( other )
T ( arg1, arg2, ... ) (3)
static_cast< T >( other ) (4)
new T(args, ...) (5)
Class::Class() : member(args, ...) { ... } (6)
[arg](){ ... } (7) (since C++11)
[説明]
* (5)は、() しか出てないが、{} でも可能 :
new T(args, ...) (5)
new T{args, ...} (5')
* (3) も、() しか出てないが、{} でも可能で恐らくother でなくてもいい筈だ(定かではない) :
T ( other )
T ( arg )
T ( arg1, arg2, ... ) (3)
T { other }
T { arg }
T { arg1, arg2, ... } (3’) >>295
>「縮小変換」と「代入初期化」が分からん
>「代入初期化」は=による初期化のことを言ってるのかな?
縮小変換は、検索すると出てくる。
「代入初期化」という言葉は、俺の記憶違いだったらしく、「コピー初期化」
が正しかったようだ。難しい。 >>299,300
なるほど「縮小変換をしない」とは
例えば以下でエラーになるってことね
int a {1.0};
「コピー初期化」ってのはコピーコンストラクタを呼ぶ初期化
あるいはコピーコンストラクタ自体のことで良いのかな? >>301
>「コピー初期化」ってのはコピーコンストラクタを呼ぶ初期化
>あるいはコピーコンストラクタ自体のことで良いのかな?
個人的には、
CPerson::CPerson( CPerson const &rPeson )
の形式のコンストラクタがコピーコンストラクタで、
それを使う初期化がコピー初期化、と思って今まで生きてきたが、
それだと、「直接初期化」の対比の意味のものとは違っているように思える。
どこかで、言葉の混乱が起きているかも。
分からない。 >>302
一部の例外を除いては、「コピー初期化」とは、= が書いてある初期化で、
「直接初期化」とは、= が書いて無い初期化、だといわれている。
但し、沢山例外があって、
T x = T(a);
などは、直接初期化なんだそうだ。
また、return a などは、コピー初期化、なんだそうだ。
記憶に頼っているので間違っているかも知れない。 >>302
コンストラクタはどれも直接初期化に使えるコンストラクタだけど
一定の形式を満たすものはコピー初期化の文脈「でも」使えるってだけ。
>>303
> T x = T(a);
> などは、直接初期化なんだそうだ。
これについて形式的にはあくまでもコピー初期化の一種ということになる。
https://timsong-cpp.github.io/cppwp/n4659/dcl.init#15
その上でコピーの省略が起きて結果的には直接初期化と同じ挙動になる。
https://timsong-cpp.github.io/cppwp/n4659/class.copy.elision#1 記憶に頼って書くけど、
1. 1つの引数を持つコンストラクタは、explicit修飾することが推奨されている。
2. explicit指定が無いと、そのつもりは無い「ひょんな場所」で勝手に変換コンストラクタとして
利用されてしまうことがある。特に関数に引数を渡す場合に起き易いらしい。
3. CPerson::CPerson( CPerson &rPerson ) は、同じ型を単純にコピーする
コンストラクタであるから、そもそも型の変換はしないので変換コンストラクタでなく、
「コピー・コンストラクタ」と言われる。
4. つまり、CPerson::CPerson( AAA &rAAA ) のような場合に >>306
[誤送信してしまった。スマソ]
4. つまり、CPerson::CPerson( AAA const &rAAA ) や CPerson::CPerson( int &rX )
のような場合に explicit 指定することが推奨されていたと思う。
T x = T(a);
の場合、「C++のからくり」のような昔の解説書だと、最適化に任されているのではなく、
特別処理されているようなニュアンス(?)で、T x(a) と同じだと書いてあった。
もし、特別処理されてないと考えた場合、= の部分だけに着目すれば、T::T( T const &rX ) という
コピーコンストラクタの呼び出しと意味論的には考えて考えられなくも無い。
そうするとそこは「変換コンストラクタ」ではなく「コピーコンストラクタ」が使われることになる。
コピーコンストラクタはいくら使っても速度が遅くなる以外は劣化やデータの変化が無いため
無害と言えば無害。なので、explicit が付いていてもいなくても余り関係が無いような気がする。 >>307
[補足]
void f(T x);
に対して、
U a;
f(a);
と書くと、実引数aが仮引数xに渡される時の動作は、「コピー(?)初期化」と考えられて
いる。もしかしたら言葉は正しく無いかもしれないが、少なくとも「直接初期化」には
分類されないということ。
そしてexplicitが付いて無いコンストラクタは、このような初期化に対しては用いられ
ないことが保証されると書いてあったと思う。 >>308
[訂正]
誤: そしてexplicitが付いて無いコンストラクタは、このような初期化に対しては用いられ
ないことが保証されると書いてあったと思う。
正: そしてexplicitが付いている無いコンストラクタは、このような初期化に対しては用いられ
ないことが保証されると書いてあったと思う。 >>309
[再訂正]
誤: そしてexplicitが付いている無いコンストラクタは、このような初期化に対しては用いられ
ないことが保証されると書いてあったと思う。
正: そしてexplicitが付いているコンストラクタは、このような初期化に対しては用いられ
ないことが保証されると書いてあったと思う。 >>304
explicit指定の主な役割は、変換コンストラクタにexplicit修飾しておくことで
「変換コンストラクタが知らず知らずのうちに勝手に使われてしまう事」
を防げる、ということだったと思う。 >>306
explicit を付けることは推奨されているわけじゃない。
推奨している人もいるけど普通は必要に応じて使い分けるよ。
明らかに変換を意味しないようなコンストラクタになっちゃうこともあるから気を付けろという程度の話。
たとえば vector は size_t を受け取るコンストラクタがある (指定サイズ分の大きさになる) がそれには当然 explicit が付いてる。
整数が vector に変換されるのは明らかにおかしいから。
char* から string への変換みたいな自然な変換では困らないし、あるほうが便利。
>>307
> 特別処理されているようなニュアンス
かつてはその場合はコピーの省略が許される (しなくてもよい) という仕様だった。 (今の仕様だとコピーの省略が必須。)
コピーコンストラクタは必ずしもコピーをするだけではなくなんらかの副作用を引き起こしても良いので
コピーの省略の有無によってプログラムの意味が変わってしまう。
プログラムの意味を変えない範囲で処理系が行う通常の「最適化」とは異なるという意味では特別扱いだ。 難しいなぁ。。。
ubuntu の g++って 11.1以降だから、c++23だったのね。
すご って思いました。 >>313
>たとえば vector は size_t を受け取るコンストラクタがある (指定サイズ分の大きさになる) がそれには当然 explicit が付いてる。
>整数が vector に変換されるのは明らかにおかしいから。
>char* から string への変換みたいな自然な変換では困らないし、あるほうが便利。
なるほど。そうだったのか。
勉強になりました。 C++やるとどんな言語も使えるとか言うけどNode.jsも数時間あれば使いこなせるの?
あれは言語じゃないでしょって言われそうだがjavascriptともhtmlとも違くて別言語に思えるんだけど C++出来ます‼ってのはC言語上がりのなんちゃってチャソも含まれるから一概には言えない >>317
C++ を使っていれば低レイヤの事情やシステム全体の関連を知る機会があるし、
言語処理系がどう実装されるのか (低レイヤの視線から見てどう動くのか) を知っていれば
常識的な言語デザインの感覚がわかる。 (言語仕様を類推しやすい。)
C++ を使いこなしている状況からなら色々と理解しやすいという効果がないとは言えない。
ただ、あくまでも C++ を使いこなせるようになる過程で言語自体以外にも身につくことがあるという部分が効いてくるので
C++ の言語仕様の知識はそれほど役に立つわけではないし、さすがに数時間で Node.js を使いこなせるということはない。 quoraとか知恵袋とかブログで「Cの次はC++をやればオブジェクト指向身について更にCから派生した言語が主流だからどんな言語も直ぐ理解できる」みたいなの多いよ
だからこのスレの人達ならNode.jsも余裕なのかなって
>>320
学ぶ過程の色んな経験が生きるって事か。そりゃそうだよね >>321
JavaScript は C 風の外観を持ってこそいるけど動的型、かつ、プロトタイプベースであるという点で
根本的に異なるメカニズムなわけでこういうのを「C から派生」と呼んでよいのかどうか……。 よく使う言語と比べて在るもの無いもの違うわけで
ちゃんと理解しようとしたらそれなりに時間がかかるでしょ
気軽に使いこなすとか言葉にしてると怖いおじさんに怒られるぞ vector<int>& a = c, b = c;
としたときに、bがcの参照になりませんでした。
&が後ろにかかるからかと思って
vector<int> &a = c, &b = c;
としても結果が変わりませんでした。
vector<int> &a = c;
vector<int> &b = c;
とすればやっと期待通りの動作になりました。
参照の宣言と初期化は複数をカンマで区切って一行で書くことは不可能なのでしょうか? え?コンパイラなに使ったの?
> vector<int> &a = c, &b = c;
> としても結果が変わりませんでした。
処理系ぶっ壊れてんのかな c言語スレで質問したのですが
スレ違いとのことでしたので
改めて質問致します。
c言語の標準入出力ストリームの
本当に基本的なことなんですが
わからずに困っています。
教えてください。
std::ofstream stream;
ostream << "ABCEFG";
この入力した文字列の"ABCEFG"を
右側3文字を削除して"ABC"にするには
どうすれば良いのでしょうか? カーソルをEのところに持ってきてDeleteキーを3回押す
またはカーソルをGの右の"の上に移動してBSキーを3回押す >>327
質問の意味が分かりにくい。
それだと入力ではなく出力になっている。
出力したものを取り消すのは基本的に難しい。 >>329
[補足]
std::string str = "文字列";
の場合、
str.substr(開始位置, 取り出す長さ);
で部分文字列を作れるので、
std::string str = "ABCEFG";
の場合、
std::string str2 = str.substr(0, 3);
で str2 に "ABC" が入る。 >>330
回答ありがとうございます。
あれから自分でも調べて
seekp()でファイル内位置を移動するなど
試してみたのですがうまくいきませんでした。
(修正の方向はあっていると思うのですが・・)
やはり>>330さんの言う通り、テキストの削除は難しくする
何かわかりませんがそういう思想があるみたいに感じました。
そこで自分も細かい編集は別に改めて行って
結果をまとめてstreamに出力する方法に切り替えました。
結果はOK、どうもありがとうございました。
tstring_t str = _T("ABCDEFG");
str.erase(str.size() - 3);
stream << str; >>331
それは環境依存の機能だと思う
UNIXだとmmapとか? >331
seekp seekg
tellp tellg
読み込み用と書き出し用でポインタが二つあるので
自分で思ってるのと違う場所になってるのかも
方向性はあってるはず
間違ってたらすまん子 >結果をまとめてstreamに出力する
これで済むなら、これこそが正道
必要のない出力をして後から切り詰めるなんて愚の骨頂
そうしなきゃならない理由があるならしょうがないけど >>331
テキストじゃなくてファイルの削除でしょ
そういう細かい言い間違いが多いから伝わりにくい文章になってると思う
ファイルに出力する前にメモリー上で編集済ますのは当たり前でファイルアクセスにはメモリよりも時間がかかるから
そういった基本を知ってたほうがいいプログラムを作れるよ >>335
いやファイルじゃなくてテキストですよ
右側3文字を削除って書いてるじゃないですか
何かの病気・・? >>336
ひょっとしてファイル上に出力した状態をテキストと呼んでるのか
メモリ上かファイル上かの区別でそんな呼び方はしない
思想とかじゃなくてメモリとファイルにはそういう性質があるってだけ
早とちりの激しい人のようだな お前も人に言い間違い云々とか言う前にファイルの削除とか書くなよ...
せめてファイルのテキストから削除とか書かないと意味わからんだろ >>338
いや全然違うよ、もっと基礎的な話で
C言語の標準入出力ストリームでのテキスト出力の話をしているの。
(C++の文字列クラス std::stringとはまた別)
>>327の
ostream << "ABCEFG";
はテキストの書き込み処理だけど、
これをやっても内部のバッファに書き込まれるだけで
HDDファイルなどの真の書き込み先には書き込まれないの。
//ostream << std::fflush;
仮に上の関数を呼ぶことで初めてHDDファイルなどに書き込まれるの。
んで、入力されてまだフラッシュされていない文字列"ABCEFG"を
右側3文字を削除して"ABC"にするには
どうすれば良いのでしょうか?
ってのが私の質問なんです。
OK? std::printってなんすか?鬱陶しいstream要らなくなりますか?? >>340
std::flushは呼び出し後にバッファがフラッシュされることを保証するだけで、書き込みをするタイミングは未規定(pstreamの勝手)
ostreamはoperator<<が呼ばれたそばから全部書き出してもいいし、バッファを半分ずつとか書き出してもいいしそれはostreamの自由
「入力されてまだフラッシュされていない」なんていう状態はostreamが教える義理はないし真っ当な方法では外からは観測できないしするべきでもない
ましてそれを弄くろうなんて考えるのがカプセル化を無視した間違った考え方だ なんだろね。std::formatだけでは効率が悪かったのかな? >>340
C++のSTLには、ファイルではないstreamの中に、そういう機能を持つものがあり、
atoi()の代わりに用いる例が出ていた。
それは入力と出力が可能なstreamで、文字列を出力しておいて、整数型として
入力することが出来る。
それが出来るということは、語尾を削除することも出来そう。 全く確認できてないが、。
stringstring s;
s << "ABCDEF";
string s2;
s >> setw(3) >> s2;
で s2 に "ABC" が読み込めるかもしれない。
誰か確認して候。 >>345
-stringstring s;
+stringstream s;
で読める >>345
[追加]
(2)
std::ofstream ostream;
ostream << setw(3) << "ABCEFG";
(3) C++ 20 以降限定になるが、
std::format() を使う。 >>340
>んで、入力されてまだフラッシュされていない文字列"ABCEFG"を
>右側3文字を削除して"ABC"にするには
>どうすれば良いのでしょうか?
"ABC"しか入力(ストリームに対する出力)されないようにするのが筋じゃねえの?
何がしたいのか そういう感じの質問こそAIに聞くと的確な答が返ってきそう ストリームの出力を後からいじれたらそれはストリームじゃない
ただのバッファだ JavaはStringBufferInputStreamとかいうのがあったけどdeprecatedされてるね >>346
そう、stringstreamのつもりだった。
書き間違えた。 >>340
どうでもいいけどostreamはC++だぞ >>353
レスにはostreamの定義なんて
書いてないんだから、
そりゃどうとでもとれるでしょ
定義がどうなんて
どうでもいい話だから
無視してるだけだよ💩 おかしいな、C言語の<<には左シフトの意味しかないはずだが そもそも、C++のSTLにstd::ostreamがある。 >>327
stdin から ABCDEF を入力して、stdout にABC を出力するらしい例。
なお、実際には全く確認してない。
[方法1]
// 文字列変数 a の段階で3文字に切り詰められ、ABC だけが入ってくるらしい。
string a;
cin >> setw(3) >> a;
cout << a;
[方法2]
// 文字列変数 a には、ABCDEF が入るが、出力は最初の 3 文字になるらしい。
string a;
cin >> a;
cout << setw(3) << a; とりあえず変数名をostreamにするのはやめなよ >>340
だから自前のバッファで操作してから書き込めばいいじゃんって話
ストリー厶の意味がわかってないんじゃない
サンプル例題ならともかくもっと実用的なアプリを使うようになったら当然そうなるしそんなとこほじくってるよりもメモリ上で操作すれば簡単だって話 ABCEFGのDが抜けてるのが気になって夜も眠れない 聞いてるのも答えてるのもいつもの天才くんだろ
お人形遊びなら他所でやってね この言語、constメンバ関数じゃなくてmutableメンバ関数だったらよかったのにと思いました。
あとnoexceptから普通に例外飛ばせるのなんとかしてください。 >>366
tryを使う場合、その関数の冒頭で、exception handler(←名前は忘れました)の
アドレスを fs:[xxx] 見たいな場所に退避したり、新しいアドレスを入れたりする
プロローグコードが挿入されるので、例外が全く発生しない場合でも、
少し遅くなる。 重いつーより設計の悪さが残念
C++11でC++98より「マシ」になったけど
まだまだ垢抜けてない そうか?
他の言語触るほど良く出来てるなと感心するけど >>367 それは昔のコンパイラの話でしょ。現行だというなら具体的なコンパイラを挙げてね。 >>370
テストしたのは数カ月前だが、使ったコンパイラは VS の大分古いバージョンだった。
だから現状どうなってるかと言われれば分からない。 >>372
[補足]
その時にネットで検索したら、(確か)IBMのコンパイラだけは、
例外処理を行なう関数でも、追加プロローグが必要なくて、例外が発生しない
ときには全くオーバーヘッドが無い、ということだった。
VC++だと、例外処理を使う関数には以下の様なプロローグとエピローグが追加されると
思う。記憶に頼っているので大体こんな感じだった、という程度で、本当は
間違っているかも知れない。
push fs:[xxxx]
mov fs:[xxxx],その関数の例外ハンドラのアドレス
・・・
pop fs:[xxxx] >>367
誤: アドレスを fs:[xxx] 見たいな場所に退避したり、新しいアドレスを入れたりする
プロローグコードが挿入されるので、
正: fs:[xxx]の中身をスタックに保存した後、fs:[xxx]に新しい例外ハンドラの
アドレスを入れるプロローグコードが挿入されるので その程度のコードが気になるほど小さな処理を例外で囲むのはおよし 実験もせずに聞くのもアレですが
std::array<short, 100> x;
に対して
*(unsigned long long*)&(x[0]) = 1ULL << 63;
とかやってもアライメント的に問題は無いの? 問題ありそうなのでこんな感じにしたわ;;;
const static int NECONV = (sizeof(uint64_t) - 1) / sizeof(short) + 1;
union LargeInt {
short m_small[NECONV];
uint64_t m_large;
};
static void writeLargeInt(const uint64_t x, std::array<short, NE>& arr) {
LargeInt u;
u.m_large = x;
for (int i = 0; i < NECONV; i++) {
arr[i] = u.m_small[i];
}
} >>379
アラインというか、言語仕様上の保証という意味では最後に書き込んだ供用体メンバ意外から読むのは未定義という解釈が一般的だよ。
未定義と直接に書いてあるところもないんだけど出来ると書いてあるところもないのでこういう場合は未定義と解される。
(ただしスタンダードレイアウトで初期シーケンスが共通している箇所については OK 。)
m_large に書き込んだなら m_small として読むべきではない。
大抵の処理系では拡張として OK にしているけど細かい制約は場合によるから問題があるかないかは
処理系の都合をきちんと検証しないとわからん。
特にハードウェア寄りの仕方のない状況を除けば避けれるものなら避けたほうがよくはある。 >エンディアンでググれ
えっ
>言語仕様上の保証という意味では最後に書き込んだ供用体メンバ意外から読むのは未定義
えっ;;;
LARGE_INTEGER共用体 (winnt.h)が使える環境でMicrosoft社製コンパイラでビルドする場合は未定義でないものとする、、、
LONGLONGとDWORDとLONG間でしか保証されないとか言われたら知らん、、、 >>382
未定義って言われたことに対して特定の処理系の仕様を挙げて何がしたいの? >>379
union定義しなくても
temp >>= (sizeof(short)*CHAR_BIT);
でループ回せばよくね 未定義な環境なんかないんだから
C++の規格的に未定義とかどうでもいいじゃん
どうせ特定の環境でしか動かさないコードだろうし 特定の環境を想定してるのに、それを書かずに環境依存の質問するってほとんど釣りだよな 自分の意見主張を伝えるのは自分の責任
伝わらないのを人のせいにしたり人格攻撃したからって伝わりはしない
無駄で愚かな行為だ CHAR_BITってC++でもレガシーじゃないの? 例えばnumeric_limits<double>::infinity()を使うべきところでHUGE_VALを使うと
このジジイは・・・てなるようなこと
CHAR_BITを使うとこのジジイは・・・ってなる人は何使ってるのかって numeric_limits<unsigned char>::digits なんだろうけど、圧倒的に記述が煩雑で
CHAR_BIT のほうが書きやすく読みやすいいから、「このジジイは・・・」と思う人が居ても
使えるところでは気にせず使えばいいかと。 #if で切り分けるのに使う定数はマクロで定義されていないといけないんで使いどころはある。 >>396
numeric_limits<unsigned char>::digitsか・・・何かやだな
1バイトのビット数は実行環境そのものが持つ特性なので
unsigned charと特定の型識別子を書きたくない
>>397
if constexprというのもあるね >>398
if constexpr は文を書けるところじゃないと使えないんで定義 (宣言) を切り替えるようなことができない。
この手の切り替えは割とごそっと切り替えることになると思うのでマクロは要るよ。 template <class T , unsigned int pos , unsigned int len = 1>
struct bit_mask{
static constexpr T mask = ~( ~static_cast<T>(0) << (len) ) << pos;
// その他の処理
}
特定のビットをマスクする処理がしたくて↑のようなテンプレートクラスを作成したのだけど
warning: left operand of shift expression '(-1 << 1)' is negative [-fpermissive]
の警告が出てしまう
この警告が符号あり整数型を左シフトしてはいけないというのは分かるので、Tが必ず符号なし整数型であることを明示したいのだけどどうしたらいいだろう?
特殊化すると符号なしのバイト幅毎に処理を描かないといけなくなるし、もっと簡便なほうほうがあったりするのでしょうか? >>400 ((static_cast<T>(1) << len) - 1) << pos じゃダメかな? Tをunsignedにするんだよね?
ぐぐったらstd::make_unsignedとかいうのがあった Tがunsignedの場合だけ許可したいならrequires std::is_unsigned_v<T>
C++17以下でコンセプト使えないならstd::enable_ifでも使おう
無理矢理signedにして問題握り潰せって奴だらけで震える この手の警告/エラーはテンプレートを実装しただけでは出なくて、
テンプレートの実体化をした時にテンプレート実装部に警告/エラーが出るからややこしいんだよな
unsignedしか受け付けない前提で書いたコードをsignedで実体化するからこうなる
黙って内部でunsignedにするか
(using U=std::make_unsigned_t<T>; で全部U型で演算する)
signedをそもそも受け付けないか
(>>405 みたいにrequiresで受け付けるTを制限する)
の2択 そもそも「符号なしであることを明示」とか書いてるけど
俺が試した限り符号ありで実体化しないと出ないんだよな>>400の警告は C++素人です
すみませんが、どなたか教えてください
こんなテンプレート関数があったとして、const を消す方法はないですか
const付いてても付いてなくても int* とか char* だけを判別したいので
毎回,余分にconst 判定入れるのだるいです
std::remove_const_t<T> とか試しても上手くいかないのでググってみたら、最上位じゃないので出来ないうんたらとか書いてあって...
最上位じゃないconstを外す方法があれば教えてください...
template<typename T>
auto function(T, t) {
if constexpr (std::is_same_v<T, int*> || std::is_same_v<T, const int*>) {
...
}
else if constexpr (std::is_same_v<T, char*> || std::is_same_v<T, const char*>) {
...
}
...以下、同パターン
} std::is_same_v<std::remove_const_t<std::remove_pointer_t<T>>, int> >>409
>std::remove_const_t<T> とか試しても上手くいかないので
std::remove_const<T>でできるけども? constexprなんだからどうやっても外せないだろ コンパイラバージョンの違いかな
remove_const<T> //C++11
remove_const_t<T> //C++14 template <class T>
using remove_const_t = typename remove_const<T>::type;
typenameと::typeを省略するためのただのエイリアスやで remove_const_tがコンパイラ通らなければremove_const<T>::typeと書けば良いと >>410
ありがとうございます
上手くconst int* は拾えましたが、それだとただのint も拾ってしまいました
ポインタ のみ拾いたいです
環境書いてなかったです
VisualStudio のVC++で、設定はC++最新版です !std::is_same_v<std::remove_const_t<std::remove_pointer_t<T>>,std::remove_const_t<T>> >>420
すごいです、出来ました
ありがとうございました!
自分は馬鹿すぎてこんなの思いつけないですが….勉強続けます、感謝 何がどう「出来ました」なのかよくわからないけど、 >409 を見る限りは
auto function(const int*), auto function(const char*) のオーバーロードで分けたほうがマシな
ものに見えるな。 そこまでして本当にテンプレートが必要か?って考える必要があると思うわw
殆どがテンプレートなんて必要ないだろw 関数外にテンプレート1つ置いてしまった方がシンプルになるがね
constを消すではなくなるが
template<class T, class TTarget>
constexpr bool pointer_or_constpointer_v =
std::is_same_v<T, TTarget*> ||
std::is_same_v<T, const TTarget*>;
template<class T>
auto func(T t){
if constexpr(pointer_or_constpointer_v<T, int>){
...
}
} 困っています.助けてください.
まず作りたいものを以下に記します.
クラスObjのオブジェクトが構築されると,
そのオブジェクト内でクラスObjのオブジェクトが0~2個生成される.
(生成されるオブジェクトの個数は一様乱数で決定される)
結果的に木構造のようなデータ構造になる.
クラスObjのオブジェクトはシリアルナンバと自分を作ったオブジェクト(親)へのポインタを持っている.
クラスObjは自分を作った親をたどることで,どのようにして(どのオブジェクトを親として)生成されたかを知ることができる.
で,作ってみたものを以下に張り付けておきます.
https://wandbox.org/permlink/lXq19mN1URMQhyh5
上記のプログラムで発生している問題を以下に記述します.
起点となるクラスObjのオブジェクトobjが生成された時点では,
各オブジェクトは自分自身を生成してくれた親オブジェクトへのポインタを正しく保持しているようなのですが,その後,メソッドrootsを呼んだときには親オブジェクトへのポインタが訳の分からないアドレスを指すことがあるようです.
なにがいけないのか,どうすれば意図した通りに動いてくれるのかご教授くださると助かります.
よろしくお願いいたします. >>426
警告が出ているのになぜ直さない? それがすべてじゃないの? >>427
>>>426
>警告が出ているのになぜ直さない? それがすべてじゃないの?
メンバ関数rootsの型をvoidにして、return文をコメントアウトすれば警告は消えます。
しかし発生している問題は解決しません‥
ご指摘の件は本質的問題ではないように思われます。
引き続きご教授をお願いいたします 55行目にchildObj.reserve(2);を入れろ
また、人にコードを示すなら本質的に関連のない警告が出ない状態のコードをまず貼れ 警告警察うざい
警告を消す為にバグを仕込むヤツを何度も見てきた 警告が出るかどうかは環境による
C++のルールに従っているなら警告は無視 >>428
そっちじゃないよ
戻り値型はそのままでよくて、elseの場合に値を返せてないから返す
あと42行目のイテレータループの終了条件の書き方も違う、!=を使え >>426
バグを調査するときの重要な考え方として「バグが確実に再現する条件/確実に発生しない条件を明確化する」というのがある。
この場合も、まずはバグ「メソッドrootsを呼んだときには親オブジェクトへのポインタが訳の分からないアドレスを指すことがある」の条件を明確化するために「訳の分からないアドレスはどの変数に入っているのか」「訳の分からないアドレスはどういうバケツリレーで渡されているのか」「訳の分からないアドレスは最初にどこにあるのか」あたりを明確化するのがよろしいかと。
そもそも>>426で「メソッドrootsを呼んだときには親オブジェクトへのポインタが訳の分からないアドレスを指すことがある」は再現するの? ああemplace_backしたときにchildObjが再確保されてparentが古いObjを指したままになってるのか
だから>>429が正解ですね >>426
> control reaches end of non-void function
voidじゃない関数がreturnせずに終わってる
この表現なら理解できるか? >>437
>こんなプログラム見ていると頭痛くなるw
誠に申し訳ない。
なんせ、近くにメンターがいないので自力でなんとかせにゃならんのです。
既にいくつか助言をいただいているので、もう少し頑張ってみます。
ゆるゆる見守ってくださると嬉しいです。
引き続きよろしくお願いいたします。 >>431
環境はvisual studio pro 2019で、皆様のご助言を仰ぐためにwandboxに貼りました。
警告に関しては、あまり気にせずコーディングしています‥
よくない癖、ですよね(汗) >>429
>>434
明日以降に試してみます。
まずはreserveを調べるところから。
ポンコツ過ぎで申し訳ないです。 >>430
> 警告警察うざい
未だにこんなやつが要るんだな...
> 警告を消す為にバグを仕込むヤツを何度も見てきた
それはお前の周りのレベルが低すぎるだけじゃね?w >>433
どうやら、再現性はあるようですが、私のスキルではどのような状況でバケツリレーが辿れなくなるのか、到底できないのです。
よいアイデアがあればご教示くださると大喜びします。 警告は潰さなければならない
警告が出たら検討しなければならない
今回の様に思いっ切りバグを示していることがあるから
検討した結果無視していいと判断しても、警告自体は消さなければならない
そのままじゃ次のビルドでまた出て、どんどん溜まって「これ検討したんだっけ??」ってなるから
この警告消しは#pragma warningでいい 警告消すのにバグ仕込むスキルの人なら機能追加してもバグ仕込むだろ ここは20年前のままで安心した。久しぶりにC++読んだけど、普通に読めたわ。
どうでもよい会話をして、ろくに進まない感じ流石です。 > この警告消しは#pragma warningでいい
警告警察の主張の本質がこれ >>443
こういうやつが居るから、管理側は「勝手に警告を無視できないRustにしよう」と言い始めるんだよねぇ。
実際、コードの精査の難しい大規模プロジェクトとかだと、無能が成果を出せないという意味で効果的だし。 設計がまともかどうか判断出来ない無能が警告を気にする >>451
> 検討した結果無視していいと判断
を無視する無能 >>456
それは
> 警告を消す為にバグを仕込むヤツを何度も見てきた
みたいな職場の話だろw >>444
まずは>>450。
あと「訳分からないアドレス」というレベルなら生ポインタは使わない方がいいので、すべてshared_ptrに置き替える。
というか、他人の古いライブラリを使わざるを得ない状況でもなければ、生ポインタは禁止にすべき。 別の環境に移植して警告が何千個も出て来たら
わざわざ全部消すの?
アホじゃね? 「検討しました」は解析ツールのコメントに残す物
わざわざコードを変えて消す物じゃない >>459
消すだろ
てか、何も見ずに警告無視するのかよw メモリがわからないままC++してもいずれ破綻するのは目に見えてるからな…
shared_ptrを使えば再確保によるポインタの無効化は回避できるかもしれんけど、
そしたら今度は循環参照にはまりそう >>445
>>446
まさにコレでした。
皆様の叡智に脱帽です。
感謝します。
C++って便利だけど難しい局面がすぐ横にある感じでスリリングですね。
そう感じるのは慣れないうちだけなのかもしれませんが。 >>458
>あと「訳分からないアドレス」というレベルなら生ポインタは使わない方がいいので、すべてshared_ptrに置き替える。
もともとC言語を触っていたので生ポの方が好きなんです。
でも、スマポに統一すべし、という意見には賛成なので、その様に直すつもりではおりますが、
enable_shared_from_thisを継承せよ
とか、一方で
コンストラクタ内でshared_from_this()は使うな
とか、色々クリアせねばならない問題もあり、解決には相当な勉強が必要そうで、時間がかかる見込みです。 自分の頭で考えることを放棄してるやつほど
偉そうにしてるやつの言うがままに洗脳されやすい >>464
スマートポインタ&参照を使わないならcで十分な気がするなぁ。
むしろcにスマートポインタと参照だけでも追加してほしい。 >>466
C++って何だかカッコいいじゃないですか。
noexceptとかC言語な人には無縁なキーワードが盛り沢山だし、いかにもアタマ良さそうな雰囲気がたまらんのです。
C言語でできることはC++でもできるようになりたいな、とゆるゆる独学している次第です。 人が書いた部分で警告大量に出るから無視してるんだが
お前ら一人で書いてんのか? >>468
大量に出る警告には何か原因がありそうなので
それをまず調べる >>464
そもそもコンストラクタで子供のインスタンスを作らないほうがいいんじゃね? 何のために警告出させてんだよ
端からガン無視する気なら、コンパイルオプションで警告止めちゃえよ あとchildObjから削除しないなら、ポインタを辿って探索せんでも、
シーケンシャルナンバーでランダムアクセスすればいいじゃんねぇ ああ、インスタンスデータなんか…すまん忘れてくれw >>466
「だけでも」っていってもそれに連なる諸々の概念がひっついてるから部分的にやるのは難しいんだよな。
C++ のスマートポインタはクラスとして実装されてるから C++ の型システム抜きに
スマートポインタだけ C に移植ってわけにはいかないし、
参照の振る舞いを説明するには値カテゴリを増やして場合分けしなきゃならんし。 ええと、最終的にはファイルから与えたデータに基づいて木構造を構成し、その木構造でナニかしようということを目論んでまして、そうなるとコンストラクタ内で子供のインスタンスを作ればいいんじゃないか、と考えた次第です。
データをあるオブジェクトに喰わせたら、勝手に木構造が出来上がるようにしたかったのです。
で、そのプロトタイプを作る段階でつまづいていた次第です。
とりあえず、皆様のご助言で動くようになったものについては明日以降にw
andboxに貼ります。
引き続きご指導をお願いいたします。 >>463
>C++って便利だけど難しい局面がすぐ横にある感じでスリリングですね。
>そう感じるのは慣れないうちだけなのかもしれませんが
君は C++ を使ってはいけないレベルと言わざるを得ない std::mapのinsert()すると、std::vectorみたいにキーや値のメモリ再配置って起きる? >>476
メモリ管理だけコンパイラ側でやるなら、クラスその他諸々は無くても大丈夫じゃない? >>480
回答どもです!そのようですね。
海外のサイトで調べたら、mapの場合はinsertしても
それ以前に挿入した要素のメモリは移動しないようですね。 最終的にはメモリ領域の所有権に行き着くはずだが
Cでどうやって所有権の貸し出し/譲渡を表現するんだよ
所有者が複数になる場合もあるんだぞ >>479
C++はmapはB木を赤黒木で実現しているから、アルゴリズム的には、既存の
ノードのアドレス自体は変えずに、ノードのつなぎ方だけを変えるはず。
ソースを見ないと分からないが。 >>482
shared_ptr 相当をコンパイラーが実装するだけでしょ? >>482
CでできないならC++でできない
対偶はC++でできるならCでできる >>477
まあ、子供をいくつか作るぐらいなら問題はないかな
ちなみに自分はコンストラクタであまりややこしいことはしないようにしてる
もし大きな処理の結果をもとにインスタンスを初期化したいときは、
全部コンストラクタでやるんじゃなくて、その処理だけを前もって実行してる std::mapのinsert、emplace、eraseは内部要素へのイテレータを無効化しないことが保証されてる(当然eraseで消した要素そのものは除く)
なおstd::unordered_mapの同名関数はrehashingが起きてイテレータが無効になることがある >>484
メモリの解放だけじゃなくてデストラクタも欲しくない?
ファイルを閉じたりしてほしい >>488
関数のデストラクタ(returnするときに必ず呼ぶ処理)が欲しくなることはあるね >>490
deferいいね
いわゆるfinallyみたいなもんかな
今でもやろうと思えば__cyg_profile_func_exitやdetourがあるけど環境依存で重くてめんどいね 数年前にawsの仕事したとき
g++のバージョンが古くて
unique_ptrを使ってたコードを泣きながら
生ポにしたことがある バカかw
自分でクラスを作ればいいだろ
スマポなんてめちゃ簡単な仕組みだぞ >>493
右辺値参照の仕組みがないと上手いこと表現できないよ。 そこはリファレンスカウンタを使ったトラディショナルな方法でやるのよ
速度は少し遅くなるけど 古いコンパイラで無理やり動かすなら#define unique_ptr auto_ptrという手も… すでに std::unique_ptr で正しく動いているコードであるという前提があるなら
たしかにそれでも致命的な矛盾は起きなさそうに思えるな。 g++なんだから新しいバージョンのをビルドすれば良いじゃん? >>461
消す為の変更で再評価
アホらし
何も見ずに?
そんなこと誰か書いたか? warningだらけだとバグに繋がる重要なwarningを見逃す可能性があるから、可能な限り消した方が良いと思う
どうでもいいやつはコンパイルオプションで消しても良いし >>499
元々は警告無しで移植で警告になったんだろ?
何千個あろうが見直すのは当たり前だし、いずれにせよ評価は必要
まさか警告出まくってるのに評価無しでOkとかしてるんか? 「C/C++ warning一万個全部消してみた」
てタイトルで動画アップして欲しい >>502
警告が1万種類あるなら大変だけどたいてい種類は限られるだろ
ほんとにコード書いてるのか? 「符号付きと符号なしの比較がされました」
分かっとるわ! それはオーバーフロー起きないかちゃんと確認しないとダメだろ
C++使っててそこルーズなの信じられんわ 文字列の長さの比較がintの上限に達することはないし負になることもないのよ だったら本当にそうであることを確認しないといけないし、そんなものにsignedの変数使ってるのがおかしいかもしれない
その値は本当に文字列の長さか?途中でエラーが起きたら-1とかが入ってる可能性はないのか?
そういう危険なバグの兆候を知らせるためにまともなコンパイラは警告するんだよ 一応言っとくと自分が言ってるのはプロダクトコードの話で
本人がその場でしか使わない書き捨てのオモチャなら勝手にすればいいと思う >>505
わかってたら直せよw
そもそもそんな警告が大量に出るほうがおかしいし delphiから移植された関数の殆どが文字数をintで返す仕様でな
それ一々符号なしに変換するのが面倒でな 使ってないパラメーターがあります
使ってない関数があります
警告が出ないようにわざわざ使う
ただのアホ ほとんどなのね
「全部が必ず」正の値を返すことが保証されてるんじゃなければますますチェックコードが必要だな
実にバグが出やすそうな所に見えるね >>512
使う必要がないなら消せよ
なんかの理由でどうしても残すなら[[maybe_unused]]付けろよ
アホはお前 新入り「使ってないから消しました
古株「ちょ・・・おま(汗 え?コンパイラが警告出した変数や関数だろ?使ってないローカル変数や非公開関数なんだろ?
それを消して挙動が変わるってことは何か恐ろしいメモリ破壊系バグが顕在化したってことだ
新人君お手柄やね ド素人丸出しwww
警告警察の中身はこんなレベルのアホ そうか
お前みたいな自称ド玄人が人命やインフラに関わるコードを書いてないことを願うわ ソフトの品質をコンパイラの警告に頼る方がヤバいと思うよ シートベルトしてるだけで安全運転だと思ってる奴はヤバい←正しい
だからシートベルトしなくていい←絶対運転しちゃいけないアホ >>477
一応の完成版を以下に貼りました。
https://wandbox.org/permlink/lXq19mN1URMQhyh5
生ポをスマポへ変えるのは一旦棚上げしています。
ありがとうございました。 何も変わってなくね?と思ったら>>426とリンク同じだった
wandboxは共有済みのソースを後から編集できないので
更新するにはもう一回共有して新しくpermalinkを生成する必要がありますよん 対処はしてるぞ
内容を読んだうえでの決定なんだから >>524
シートベルトは法律で決まってる
警告を消すのがルールで決まってる職場なら
警告かルールいずれかを消せ
そうじゃないならどうでもいい
ソフトの品質を担保するなら
警告の中身を見ずに単に隠すのが一番悪い
また
全ての警告を無条件で検証しろというなら
全ての演算も無条件で検証しろ
C++の演算はオーバーフローする可能性があるんだから
無意味な警告は出す方が悪い
コンパイラの設定で無効にしろ
コードを変えて隠す物じゃない >>530
流し読んだ感じだけど
1.
void roots( unsigned );
> // 自らがどのようにして生まれたかを調べるメソッド
> // 第 serialNo 番のインスタンスを探索する.
自分の親を探索するのか指定serialNoが子供にいるのかどっちだよ
あと検索なのでメンバを上書きしないはず。関数自体をconstにするべき
2.
engineは親のengineを参照すればいいのでわざわざ引数で受け取る必要はない
コンストラクタは親を受け取るのとengineを受け取る2種類用意したほうがいいんじゃない?
3.
numberフィールドはいらん(名前もchildCountに変えるべきだが)
childObj.size()を見ればいい
getter関数作ったほうがいい
4.
isLeafフィールドもchildObj().size()==0見れば判断できる もう解決してんだからアドバイス気取りでがんばって蛇足を加えんでもいいよ >>531
そこで図々しいお願いですが、そのように改造してくださると私にとって大いに勉強になります。
一肌脱いではいただけませんでしょうか?
生ポをスマポに直すのすら頭を抱えているヘタレなので、ここに棲まう先輩方のご鞭撻を是非に賜りたいです。 >>528
分かってんじゃん
C++の整数演算は無条件で全て検証が必要だよ
おっしゃる通りオーバーフローするかもしれないし、それが大きなセキュリティ問題につながった例もたくさんあるからね
特にナイーブにsigned/unsigned間比較や縮小変換をしてる所は危険だし、それを知らせてくれるコンパイラ警告は実に有用なものだ
もちろんプロダクトコードの話ね 縮小変換が警告されるかどうかと問題が起きないようにロジック組んであるかどうかは別問題だね それはそう
コンパイラが知らせてくれるのは一番基本的な所だけだからな
逆に言えばそれすら対処してないようじゃ0点 >>534
警告に惑わされずに全部見ろ
>>536
警告を隠すのと問題が無いことを確認するのをごちゃ混ぜにするアホ >>512
> 警告が出ないようにわざわざ使う
えっ、そんなレベルなのw
そりゃそんな職場なら
> 警告を消す為にバグを仕込むヤツを何度も見てきた
とかもあるんだろうな...
なんか可哀想になってきたわ >>467
> std::unordered_mapの同名関数はrehashingが起きてイテレータが無効になることがある
その場合でもvalue側のメモリは固定でしょうか? >>540
警告を消すためにわざわざ使うマクロを知らんのか ◯◯のコンパイラや◯◯のチェックツールで警告が出るから直しとけ
って言われたら何の疑問も持たずに直すの?
◯◯はバグの元だから直せって言われたら
何の疑問も持たずに直すの?
思考停止? >>543
なんのマクロのことを言ってるのか知らんけどそんなの処理系によって違うだろ
最近の流れは>>514のような属性指定 ぶっちゃけテストしてるなら警告放置でもいいけど、
テストするような人は警告にも対処するからな >>544
指摘されてるんだからなぜその指摘が出てるのか調べて直すなり警告抑止するなりするだろ
なぜなんの疑問も持たずにとか出てくるのか不思議だけど君の職場ではそうなんだろうねw 見も知らん第三者にwell-formedなコードにケチつけられたら
言いなりにしろと押しつけてくるやつ、自分の姿をビデオでも鏡でもいいから見てみたら? 多分「直す」を「何も考えずに警告抑止なりキャストなりで握り潰す」の意味で言ってるから噛み合ってないんだと思う
警告無視マンセー君以外はもちろんバグがないか確認した上で範囲チェックやクランプや(問題ないことを確認して)キャストなどを加えてプログラムを改良する意味で言ってる >>541
value のアドレスは変更になるが、valueが構造多やクラスで、中にポインタが
有るような場合は、そのポインタの値は変更されない。 >>550
間違いました。unorderd_map の rehashingについて、こう有ります:
https://cplusplus.com/reference/unordered_map/unordered_map/rehash/
>Iterator validity
>If a rehash happens, all iterators are invalidated, but references and pointers to individual elements remain valid.
>If no actual rehash happens, no changes.
なので、iteratorは無効化されるが、個々の要素への参照やポインタは有効なまま残ります。 >>551
ソース読まないとはっきりしないけど、恐らく、イテレーターが指している
オブジェクトのポインタを取得すると以前と同じ値になっている。
しかし、イテレーターには ++ で直後の要素に移動する機能が有る。
恐らくその機能が正しく働かない場合があるということらしい。
ゴミレスでごめん。 >>549
いろんな方法で検証は当然行う
コードを変えてわざわざ警告を隠す作業はしない キャストして警告を隠す事がプログラムの改良だと思ってるアホとは会話しても無駄だな >>548
それだと多分うっとりしておしまいになるやつ > キャストして警告を隠す事がプログラムの改良だと思ってるアホ
>>554 のことだなw まだ直すと隠すの区別ついてないアホのためによくある例書いとくね
std::vector<Foo> foos = /* なんか入ってる */
for(int i = 0; i < GetLegacyLength(); ++i){
Hoge* item = GetLegacyItem(i);
if (i < foos.size()) // WARNING: signedとunsigned比較してんぞ
{ hoge(foos[i], item); }
else
{ fuga(item); }
}
アホの隠し方(1):脳死でif文のiかfoos.size()をキャストして隠蔽
アホの隠し方(2):脳死でiの型をsize_tに変更、そしてi < GetLegacyLength()でまた同じ警告が出て激怒「コンパイラの警告なんて無意味だ!」
正しい直し方:
なぜ長さを返すのに戻り値型がintなのか、GetLegacyLength()のマニュアルを見て仕様を確認する。
するとある条件でエラー値として-1を返すことがあると判明したので、
forループの前にGetLegacyLength()を取得するようにして、負の場合のエラー処理を追加した。
/*略*/
int len = GetLegacyLength();
if (len < 0) { /* エラー処理 */ }
else {
for(size_t i = 0; i < static_cast<size_t>(len); ++i) { //lenは0以上と確認済みなので安全にキャストできる
/*略*/ >>558
そもそもforの条件判定の部分で関数を呼ぶのは間違いだ そこは間違いコード例だから意図的にそうしたんだけど
元がfor(int i = 0, len = GetLegacyLength(); i < len; ++i)だとしても話の本旨には関係ないよね?
お前が警告無視する時みたいに脳死で食いつくからそうなる >>559
それこそ脳死だろw
ループ毎に異なる値を返すかも知れないぞ
(もちろんそんな設計する奴は漏れ無くアホだが)
ちゃんと仕様なりソースを確認しろ >>551,552
いえいえ、わざわざ調べてもらってありがとうございます!
vectorのメモリ再配置によるアボート障害が発生したので、ハッシュのときも
同様のことがないか気になっていました。
とりあえずハッシュの場合はアボートすることはなさそうですね。 >>562
そういうおまえさん自身は
GetLegacyLengthとやらの仕様なりソースを確認しているのか? >>558
BOOL GetMessage のことですね判ります >>564
自分が改修する立場ならな
当たり前だろ
もうそのレスがアホすぎる >>566
確認してないんだな?
じゃあ一般論としてあんな変なコードをいつも書いているのか?
話の本旨に関係ないのにわざわざあんな書き方するのは日常の勢いか? なんかおまえさんの話し方なのか口癖なのかわからんが鼻につくんだよ
well-formedなコードに対する警告をどうするかなんて
おまえさんが感情的に喚いたからって誰も考えは変えないぞ
技術的な議論で誰も分かったと言って来ない現実を
おまえさんはDQN口調でどうかしようとしているようだが恥を知れ 諭されて反論できなくなったから重箱の隅突き始めたよ
ダッサ あのforに違和感を覚えないセンスのやつに
上から目線でご高説いただいても
自分はああはなりたくないと思うだけだからな そうだな
悪い例として出されたコード例に向かって粗探ししてハイセンス気取るような恥ずかしいアホにはなりたくないものだ ああいうダメコードを見つけ出すヒントとしてコンパイラ警告は使えるんだよっていう例を出したつもりだったんだけど難しかった? たまーに実在するからな、ああいうfor書くやつ
そういう手合いの言い訳はどいつが言っても同じ雑音でしかない >>567
> 確認してないんだな?
> じゃあ一般論としてあんな変なコードをいつも書いているのか?
たった2行でよくこんなアホさが滲み出る文章書けるもんだな...
1行目もアホだと思うが2行目は脈絡もないのに「じゃあ」とかアホすぎる
こういう奴があの手のクソコードを書くんだろうなw >>574
頭冷やせよ
特定の関数の仕様が理由でなくて
あんなコード書いたのかと言っている
おまえさんこそあの手のクソコードとやらはどれのことで
それをなぜ俺が書いていることになったのか説明できるか? 低能警察に糞コードで反駁しようとしたら
収集がつかなくなったでござるの巻
警告を回避するためのコード変更がそんなに嫌ならコンパイラのオプションで警告を出さなくしたら良い…… 警告どころかコンパイラのバグを回避することだってある
むろん思い切り処理系に依存する内容となるが嫌とか好きとか言ってらんない
必要が出ればやるだけで感情の入る余地はない
どっかの思い上がった坊やの俺様節が五月蠅いだけ
黙ってくれれば俺にそれ以上の望みはない 警告をOFFにしたら警告を回避しようとしてバグを仕込んでしまう事故は確実に防げる
ていうか本質論としてはそもそも警告に頼らねばプログラミングもできない程度の低能はそもそもプログラミングをすべきではないという話、
これは反駁のしようが無い >>576
> あんなコード書いたのかと言っている
そもそもあのコード書いたの俺じゃないことぐらい
>>562 > (もちろんそんな設計する奴は漏れ無くアホだが)
って書いてる見たらわかるだろ...
> それをなぜ俺が書いていることになったのか説明できるか?
誰もお前が書いたなんて書いてないけど頭大丈夫か?
脳死で
> for(int i = 0, len = GetLegacyLength(); i < len; ++i)
みたいな修正したらバグるかもよって話だぞ はいはい「俺じゃない」のね
IDコロコロする人とは話にならないな なんかすまんな
何気なく書いたダメコードのそれっぽいfor文がこんなにキチガイの琴線を刺激するとは思わなかった 559の指摘にあの返事だからな
うわー香ばしいと思ったのよ >>583
すまんと思うならもうROMっててくれ
これに返信も不要だからな forやwhileの条件でstring::sizeを呼んでるけどダメ? >>588
意図したものならまぁいいけど、後々のことも考えると普通は禁止 ループ内で変更しないstd::stringのstd::string::size()なら
コンパイラが頑張ってギリ括り出し最適化をしてくれるかもしれんがコンパイラに優しくない……
ていうか以降値が変化しないことがわかっているメンバ変数やグローバル変数は
intやsize_tみたいな単純型ならさっさとローカル変数にコピーした方がメモリからのロード命令削減のために良い
実体(メンバ変数やグローバル変数)と同じ値を保持するローカル変数(エイリアス)があったら混乱するというのは
そんな関数が(担当者の脳のキャパに比べて)デカすぐる…… >>582
IDコロコロ?
ちょっと回線切って頭冷やせw だから他人に指図すんな
警告をどうしようが回線をどうしようが
おまえさんに言われる筋合いはない
依頼心の強い甘ったれ野郎か? 依頼心の塊はこんなゴミ溜めでイキリ倒さないと自分を保てないお前さんの方だろ
for文警察出来て楽しかったでちゅか? こんなゴミ溜めでイキリ倒さないと自分を保てない → 依頼心が強い
全くつながらなくて説得力ないね
子供言葉にお似合いのしょーもない言い返しだなw j「コンパイラの警告は全てゴミだから無視するべき、なぜなら>>558のfor文がダサいから」なんて主張をしてる奴への罵倒になぜ論理性が求められるのか分からない
バカアホマヌケ依頼心野郎で充分だろお前もそうなんだし へー、この流れをそう読んでいたのか
我ながらひどく買い被りすぎてたもんだ
そりゃー話になるわけないよな 警告は内容によっては無視する場合があると言ったのを
全て無視すると改変してまで言い返さないと気が済まないのか
子供言葉にry そのうち惰性で内容を吟味せずに無視するようになりそうなので
がんばって警告は消してくスタイル 無視してたらコンパイラのバージョンが上がって警告しなくなったやつもあるな なるほど558は警告を無視する場合な訳ね、理由はfor文がダサいからw
やっぱこのチンパンジーオモロイわ
何か言い返してくるだろうけど、畜生の鳴き声に論理性なんて求めないから本能剥き出してくれていいよ
かわいいね for文の話で脳死が出てくる自己紹介な人だから
for文についての指摘が警告の話に短絡してしまったわけか
治してあげんの面倒臭いから放置するぜ 凄い、>>602が何一つ意味が分からない
本当に猿がランダムな日本語もどき書いてたんだな感動した 忘れてるかも知れんがここは全世界から閲覧かのうな掲示板だよ
おまえさんの発言見てんの俺だけじゃないからね
第三者にクスクスされる文面には気をつけたら? 顔真っ赤な人はクスクスどころかドン引きされてるみたいだけどねw >>563
unorderd_map のテストプログラムを作り、デバッガのステップ実行で、
ソースを調査することを進めます。デバッガを併用すると、単純にテキスト
エディタでソースを眺めるより楽です。
わざとrehashされる条件を作っておいて、*it が返すポインタが変化してないことを
確認したりもしてみてください。 >>608
誤: ソースを調査することを進めます。
正: ソースを調査することを薦めます。
誤: わざとrehashされる条件を作っておいて、*it が返すポインタが変化してないことを
正: わざとrehashされる条件を作っておいて、&*it が返すポインタが変化してないことを
unorderd_map<K,V>::iterator it に対して *it が V 型、&*it が V* 型ですね、確か。 本題から逸れた細かいことばかり言う人って他人から相談されなくなるよね
とりあえず本題に触れてあげたほうがいいと思う >>610
じじい世代はここで
西部警察
がでてくる >>613
セーブ警察(定期的に保存しない者を取り締まる人)ですね >>616
西部警察が東部を取り締まるみたいなロジック何それ…… まともなエディタなら自動セーブ機能くらいあるだろ
メモ帳で開発してんの? 池袋駅は東口に西武デパートあるから問題ない
そして西口に東武 質問なのですが<random>の疑似乱数クラス(いっぱいある)って共通の基底クラスとかインターフェースとか無
いの?
乱数のseedをプログラムの中で1回だけ与えて初期化した疑似乱数オブジェクトを
関数foo()に渡したりして使いまわしたいのだけどfoo()は特定の疑似乱数クラスに依存させたくないという場合、
foo()を疑似乱数クラスTを受け取るテンプレートで実装するとか自作のインターフェースで疑似乱数クラスをwrapする以外に他無し?
それともそもそもそういうことはすべきではない(関数の中で都度乱数のseedをプログラムの中で1回だけ与えて初期化した疑似乱数オブジェクトを作れ
と神はお命じなのやろうか…… 訂正orz、
誤: 自作のインターフェースで疑似乱数クラスをwrapする
正: 自作のインターフェースで疑似乱数クラスとDistributionクラスをセットでwrapする
<random>はテンプレート全振りすぎてオブジェクト指向的でない
ヤヴァイ…… >>621
そもそも何がしたいのか
seedの異なるものが同時に必要ならそうするしかない >>620
>関数foo()に渡したりして使いまわしたいのだけど
>foo()は特定の疑似乱数クラスに依存させたくないという場合、
foo()を関数テンプレートにし疑似乱数クラスをテンプレート引数とする
じゃだめなの? >foo()を関数テンプレートにし疑似乱数クラスをテンプレート引数とする
>じゃだめなの?
通常はそれでも良いが
foo()が1万行ある関数だったとしてヘッダファイルに書くのかっていうか、
なんで疑似乱数を使うことと、書き方がテンプレートに制限されてしまうことが相関されねばならないのか
疑問に思わないのかそうか、、、 んまー現実解としてはどうせstd::mt19937をstd::random_deviceで初期化するような使い方しかしないのだろうから
using rand_t = std::random_device;
using psrand_t = std::mt19937;
class FooTest : public ::testing::Test {
protected:
psrand_t m_psrand;
public:
FooTest() : m_psrand(rand_t()()) { }
};
ぐらいで過度の抽象化はやめておいた方が良いのかもしれん……
(別名にする、程度にしておけば疑似乱数クラスの選択とDistributionクラスの選択を分離できる 標準ライブラリのテンプレートもみんなヘッダに書いてるんだしいらない疑問だと思うが……
使ったことは無いけど、気にするならC++20モジュールとして書いてみるといいかもしれない >>624
疑似乱数クラスは限定されているので
俺ならfooの実装はcppに書いて明示的インスタンス化をする >>620
result_typeが違うと、乱数のサイズが変わって、それに処理も合わせないといけないからな
素直にラップすればいいんじゃね >>619
近い将来西武デパートがなくなる可能性もあるので
コンピュータ技術同様、未来永劫変わらないものなんてないんだ >>620
randomてoperator()持っていなかったっけ?
std::functionに入れるとなんか問題あったっけ? >>620
ないけど_enjineがつくやつは使い方が統一されているから
普通にテンプレート引数にするだけでいい
テンプレートに渡せるクラスを限定したいならconceptという手がある 会議で「テレメトリーの結果、オートコレクトをオフにしているユーザーさんが多い、どうしたら良いか」ということを話し合った。
「小文字にする方法」を解説するページを作っておけば儲かるぞ。 stdexceptの各例外の使い分けがわかりません
まず
・エラーは「実行時エラー (runtime error) 」と「論理エラー (logic error) 」との2つに大別される。
とのことでinvalid_argumentはlogic_errorの派生クラスみたいなのですが
foo()に不正な引数が渡る状況はたいてい呼び出し元bar()の実行時エラーなわけじゃん?
しかしそれだと論理エラーの出る幕が一切なくなるので、
foo()視点でfoo()に不正な引数が渡る状況は論理エラーである、とみなす立場が考えられるますが、
しかしfoo()が投げた例外を補足する箇所はfoo()の外なわけで、そんなローカル視点知ったことか、となるわけじゃん?
もうstdexceptのうちでユザープログラムから投げるのはruntime_error(<適当なメッセージ>)だけで良い? だいたい自己解決しましたサーセン、
1. cassertにおけるassert()条件に書くような、設計上絶対起こり得ないやつ(起きたらバグ)はlogic_error
2. 上記以外(設計上起き得ないことを保証しかねる不整合)はruntime_error
で、さらに細分化可能な場合(明らかに派生クラスにあてはまるやつ)は派生クラスにする
例外を補足する個所では、logic_error& eかruntime_error& eで捕捉する(そうすれば派生クラスも捕捉できうる
でFA? ソケットプログラミングがマジ解らん。
コネクトするコード書いてもエラー起こすし、バインドしてみたらエラー返してきてどうしようもないし
どうすればインだー。 >>643
まずはサンプルを動かすところから始めよう 解決する気があるなら書いたコードと返ってくるエラーぐらい貼ろうぜ このスレ見て久しぶりにC++やったら今まで丸暗記してたことが
他の言語にも適用できる感じ理解できてしまったわ >>642
分類としてはそんな感じでいいと思うけど、型でcatchし分けるのはお勧めしない。 >>645 そうです。コネクトしてメッセージ出るまでできました。
>>464 いえすさー
サンプルのサーバーも自分で書かされた結果。
サーバーがアクセプトするまでクライアントは何してもほぼ無駄という事でした。 最後の「ばインだー」はバインドとかけてるのか?いや、まさかな… fork自体あまり良い設計ではないから、マネしなかったのは良いことだと思うよ NTの構造上、forkをWin32サブシステムに入れる筋合いはどこにもないからな Unixの構造上ならどう筋合いがあるんじゃ……
親プロセスから子プロセスになんか引き継ぎたいとき便利(そういうのが多いときコピーオンライトで高速化も可能)だというのはわかるが
そもそも親プロセスから子プロセスに引き継がれるべき情報ってそんなに重大で大容量なのがなんかあるっけ、、、 そもそもプロセスって並列処理のためのもので、並列処理って同じ仕事する奴をたくさん用意するものなんだからforkは自然な設計
現代のPCやデバイスと噛み合ってないのはその通り 俺の使い方だとshellのビルトインコマンドをパイプで繋げるときと、PS1に色々仕込むぐらいしか恩恵ないかな
Windows(cygwin)でパイプ使いまくるとクソ重い
他はネットワークサーバーでaccept→forkのサンプルコードをよく見る >>657
筋合いって、それはunixだからだろ
windowsならwslでやればいい forkはそのままではメモリ共有できないので並列処理の定石とは言い難い if (auto result = Hoge())
{
}
else
{
}
て書いたときelseブロックでもresult参照できるのめっちゃ違和感あるんですけど、こうなってる理由ってどこかに書いてありますか? 違和感? 何で?
ブレースは必須じゃねえだろ
if (auto result = Hoge()) ; else /* ここでresultが使えるのおかしいか? */ ;
{
else /* これはできないわけで、elseはifの続きだぞ */
} try で宣言した変数を catch や finally で参照できるようにして欲しいと思ったことが 5億回はある >>669
出来たとしても catch したときには解体済み (または構築していない) なはずなのでだめぽ。 うん、ダメな理由は分かる
でもみんな try に書いてた変数を catch や finally で必要になってから外出しした経験あるよね >>667
C with Classes が C++ になる頃にそこに宣言を書けることにした話はD&E に言及がある。
Algol68 の真似をしたつもりだったが
実は設計者の勘違いで Algol68 にそんな仕様はなかったということも書かれている。
スコープのことまでは書かれていなかったが、
たぶんそれも当時の設計者の脳内 Algol68 ではそうだったってだけなんだろう。
まあ else も if 文の一部なので自然に考えれば全体がスコープになるほうが
理屈に合うように思えるし、私は疑問に感じたことは無かったな。 >>672
ありがとうございます。
ifでの宣言は初期化とテストが一緒にされるわけで、テストに失敗した結果実行されるelseブロックでそれが使えることがちょっと納得できませんでした。
言われてみれば、中身がnullptrとは限らないし、エラーハンドリングとかで使ってるんですかね それよか
int outlierCnt; // ←これのスコープのが問題
do {
outlierCnt = 0;
for (int j = 0; j < n; j++) {
if (...) {
outlierCnt++;
}
}
} while (outlierCnt > 0);
// ループを出たらoutlierCntは用済み 見えてほしい範囲とか見えてほしくない範囲があんならブロック使って任意にスコープ作ればいいんでは >>675
bool bUniqueList; // ← constにできない
{
bUniqueList = true;
std::set<T> dupChk;
foreach (auto it = vec.begin(); it != vec.end(); it++) {
auto result = dupChk.insert(*it);
if (!result.second) {
bUniqueList = false;
break;
}
}
}
if (bUniqueList) { ... } >>676
const bool bUniqueList
{
[&]
{
bool bUniqueList = true;
std::set<T> dupChk;
for (auto it = vec.begin(); it != vec.end(); it++) {
auto result = dupChk.insert(*it);
if (!result.second) {
bUniqueList = false;
break;
}
}
return bUniqueList;
} ()
};
if (bUniqueList) { /* ... */ } do while が一番パフォーマンス的に有利なんだから
もう少し使いやすくしてほしかったなあ // みんなこうやってんの
{
int outlierCnt; // ←これのスコープのが問題
do {
outlierCnt = 0;
for (int j = 0; j < n; j++) {
if (...) {
outlierCnt++;
}
}
} while (outlierCnt > 0);
} for (A;B;C){
} while (D);
こんなのがあれば万能 for (A;B;C){
if(!D) break;
}
解決した ループの条件が2箇所になってるのは
構造化プログラミングのパラダイムからは外れる形だね
俺は教条主義者ではないが、あんまり気が乗らない 見やすさや行数を無視するなら
for、while、do while なんかいらない
gotoで良い doとかいう貴重な2文字キーワードをこんなとこで無駄遣いしてるのは正直ダサい {
A
if(!B)goto L0002;
{
}
C
if (D) goto L0001;
L0002:;
} >>681
do {} while (!D) は,ループの事後条件として,Dが条件として成立することを保証している。
(until D として欲しかったが)
for (a;b;c) {} while (D) じゃ,ループの事後条件として何が成立してるのかわからないので
こんなコードは却下だな 逆に, B | D が成立してほしいなら
A; do { C } while (!(B|D)) と書くべき こんなので
dowhile(int cnt; cnt > 0)
{
cnt=0
cnt++;
} for (int cnt=0; cnt>0;) {
cnt++
}
でいいんじゃないの? do{}while(){}
セミコロン最後に付けるならスコープでいいよな ループ終了条件を,ループ制御変数以外で書きたいということ?
別に書いてもいいけど,わかりにくと思うんだ
for (int i=0; i<0 || D ; ++i) { … }
で良いんでは? do(int i=0){}for(i<n;i++);
こんな感じか for を前に書こうが、後ろに書こうが,for ループを抜けた時は,
for ループの終了条件が成立しているので,前に書いたら良い for (A; B||D; C,D) { … } じゃダメなの? >>680
なるほどforeachではなくてforなのですね
わかりました inline 指定子って前方宣言と定義の少なくとも一方に付ければ良いんですかね?
普通は inline 関数を宣言と定義分けて書くことはあまりしないと思いますが inlineの元々の意味はもう存在感なくなってきてるな
今はODRに違反するものを通して貰ったり
namespaceのアレとかで使う 本来の意味では、コンパイラ依存になっちゃうけどalways_inlineとか__forceinlineっていうのがあったりするな
これもちゃんと規格化した方が良いよね モジュールだとinlineは元の意味になる、forceではないけど enum class Fooの項目数を取得するにはどうすれば良いですの?
昔ながらに
enum class Foo { A = 0, B, C, D, E, NELEMS };
みたいに要素数NELEMSを定義しないと駄目? >>711
現在の言語仕様の範囲内でやるならそれがたぶん一番に簡単な方法。
magic_enum を活用するのもいいけど処理系の拡張を利用しているのでもしもメンテが
滞ることがあったら処理系の変化について行けなくて破綻するかも? (余計な心配かも?)
要素数を数えるためだけに導入するならちょっと大げさという感じがする。
将来の C++ にリフレクション系の機能を追加しようとする提案はある。
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/n4818.pdf
試験的に GCC に追加したブランチもあって、
オンラインコンパイラで試せるところがあったはずなんだがどこだったか思い出せない。 すまぬ……。 std::vectorを初期化せず要素数を変更する方法が存在しないそうですが、どうにかなりませんか? >>717
初期化しないことを指定するフラグをメンバ変数に追加し、resize(n,c)の二番目の引数でそのフラグを立てたインスタンスcを渡す。
コピーコンストラクタが呼び出されるので、渡されてきたインスタンスcの該当フラグを見て、初期化するかどうか判定して分岐させる。 >>717
vector が要素のデフォルトコンストラクタを呼ぶことは保証されるが
デフォルトコンストラクタが初期化しないようにしておけば初期化されない。
https://wandbox.org/permlink/8SepeggcI18hio7W >>711
列挙型を定義するときには要素の数は分かっているのだから要素数を書いた定義も書いておけば十分かもしれない。
#include <type_traits>
// プライマリテンプレート (実際にはこれが使われたらエラー)
template <class T>
class enum_count {
template <class U>
class helper : public std::integral_constant<bool, false> {};
static_assert(helper<T>::value, "expected known enum.");
};
// 列挙型を定義
enum class Foo {A, B, C, D, E};
// 列挙型 Foo の要素数が 5 であることは分かっているので 5 で定義しておく
template <> class enum_count<Foo> : public std::integral_constant<std::size_t, 5> {};
int main(void) {
// 列挙型の要素数をカウントしたかのように見える
static_assert(enum_count<Foo>::value == 5);
}
列挙型の定義と要素数の定義を同時にするようなマクロでも作っておけばなおよいと思う。
Boost にそんな感じのライブラリがあった気がするが使ったことが無いのでよく知らない。 >>717
vectorが連続した領域を確保するので仕方ないかと。
vector のreserveで十分な領域を予約する
vectorにインスタンスじゃなくてsmart pointerを格納する
vectorじゃなくてlistかdequeを使う
クラスを弄くれるなら、move constructorでどうにかならんかね? >>720
レス㌧クスしかし……
enum class FooはFoo::AとかFoo::Bとかいう形でしか使われないのだから個数を返す専用のテンプレートの特ちゅ化を行うよりは
Fooという名前のを何らかの手段でwrapしてやってcountメンバを持たせる方が自然なような、
enum class Foo0 { A = 0, B, C, D, E };
だとして現状class Foo : public Foo0 { ... }みたいなことは書けないから、手段としては次の2つ……
(1) クラスれwrap
struct Foo {
enum { A, B, C, D, E }; // 古き良きenum、
static size_t count() { return 5; }
};
(2) namespaceでwrap
namespace Foo {
enum { A, B, C, D, E }; // 古き良きenum、
inline size_t count() { return 5; }
};
規格委員会が斜め上の行動に出なければこういう方向性が自然に感じる…… >>717
std::vector<T>をとったら初期化が来る ほんとに早いわ
初期化さえ無かったなら チューリングマシンは楽しいとこ
初期化はきらいだった 私
夢ばかりみていたのよ 私
でもデフォルトコンストラクタとコピコンと代入演算しだけでも
まじめにしておけば
今頃私はかっこいいC++er
初期化はしないよりも しておいたほうがいいわ 必要があれば初期化するし
必要なければ余計なことはしない
判断できましぇ~んなアホにはなりたくない >>726
初期化は必要だっつの;;;;
で、std::vector<T>を取るのが高速化されたとしても
要素使用時に初期化が必要なのだから時間短縮にならないという
ていうか通常は(大概のクラスは)初期化時間とかstd::vector<T>が運悪くOSにsbrk()してしまうケースに比べればゴミみがいなもんじゃろ……
という辺りの事情を考えたことも無い>>726、、、 いやすまん>>720について:
>>720の処置にすると使うコードの字面上はFoo::AやFoo::Bがそのまま使えるが、中身が古いenumなので
Foo x;
x=2; // 禁止されない
int y = x; // キャストを忘れても何も言われない
という問題があったorz
(他にも列挙子の型がint以外にできないとか
やっぱ現状はenum classを活かしつつ>>720にするか、enum classの定義ごとマクロでwrapするしかないのかも|||。n_ >>727
うん、vectorでは必要だね
そんくらい判断してるよ
マウント取りたさに目がくらんで頓珍漢こくな >>729
別に……
std::vector<T>の要素がC言語レベルの構造体なら初期化は後回し(最初の代入時)でいい…… なんにせよ未初期化(メモリ内容不定)というのはチューリングマシンのプログラミングモデルでは絶対悪
であることは街行く人100人に聞いたら100人全員がそう答えるので
マウントをとろうとして無駄にあがいているかさもなくば無知なのは>>729の方ででケテーイ…… 捏造データ使うやつの相手はしとれん
俺はどっかの大臣みたいに寛大ではない どこが捏造データなのかkwsk、
街行く人を引き合いに出したのは統計の結果という誤解を与えたのかもしれんが
チューリングマシンのプログラミングモデルにおいて、初期化を行わないまま次のステップに進めない(やったら動作が不定になる)のは
覆りようが無い真実、、、 循環バッファ作るときの配列なんかいちいちゼロクリアせんだろ
学校で習いたての未消化の知識で思い込んでんなよ
アホくせ
俺は夕飯の買い物に行くぜ >>734
そりゃーその配列は最初のデータのencueueがあるまで使われないからな
しかし循環バッファを使う前に、encueカウンタとdecueueカウンタの初期化は必須であるから
その例では>>733を覆したことにはならない
物事の道理が徹頭徹尾わかっていないのに突っかかってくる>>734…… ちと訂正orz、
循環バッファに入れるのが、STLのクラスをメンバに持つような高級なクラスだったとしよう、
すると循環バッファ作るときの配列を未初期化のままとすると、最初のencueueでいきなり代入から始まるから
(代入演算子が呼ばれる)から、未初期化オブジェクトに対する代入演算子が機能したとしてもそれはたまたまという話になる……
よって
>循環バッファ作るときの配列なんかいちいちゼロクリアせんだろ
これの主張は偽。ハイ論破、 >>723
メンバを持てない型にメンバっぽいものを結び付けたい場合 (たとえば char_traits や numeric_limits) だとか、
既存の型をいじらずに拡張できる余地を用意したい場合 (allocator_traits) 、
メタプログラミング用のメタ関数 (type_traits) といったものはトレイトの形にすることもそんなに珍しくはない。
ところで Godbolt でリフレクション (N4818) 実装版の clang が使えた。
列挙子の数を数えるメタ関数を簡易的に書いたらこんな感じ。
https://godbolt.org/z/G4jf65j8f
将来的にはこういう機能が C++ に入るかもしれない。 >>737
get_size_v<get_enumerators_t<reflexpr(Enum)>> でよい。
標準で enum_count みたいなの用意しといて欲しいよね。誰が書いても同じになるんだから。 >>738
おっ、そんな便利なのを見落としておったわ……。
将来的には enum_count みたいなのは入ると思う。
現時点では基礎になるスコープの広い部分を検討中だから
おそらくその上に実装されるであろう部分をどうこういうのは時期尚早ってことなんだろう。 >>735
覆したかどうかジャッジは衆目に任せようや 初期化の必要はないけど、しても負荷はないに等しいという状況もよくあるからなんとも 形式的には初期化をしてても最適化を通ると消えてるってこともあるし……。 必要ないことはしないってだけなのに何か悪いのかよ
見も知らん馬の骨のご機嫌取るのも必要ないかんな >>734
未初期化メモリのアクセスが未定義じゃなくてエラーだったら良かったんだけどな。
エラーにするの大変なのかね。 例えばプログラムでアドレスを計算してる場合に、そのアドレスのメモリが
初期化されてるかどうかをコンパイラが判断するのは難しいだろうね
他にもライブラリとか別のプログラムで初期化されてもわからない >>746
昔はそういうアーキテクチャの計算機もあったらしいよ
今はデバッグツールでそういうことも含めて大抵のことは検出できる vectorに対してcopyとかtransform使うとき、あらかじめコピー元とコピー先のサイズを揃えますけど
この時ほぼほぼ初期化省かれてるなっての分かるじゃないですか
それなら最初から初期化を省くメソッド用意してくれてもいいんじゃないか?と思うわけです まあ、要素がPODの場合にvector::resizeで初期化しないでほしいと思うことはあるけど、
それで仕方なく不要な初期化をして遅くなった試しがないからなぁ・・・ >>749
そのためにサイズとは別にキャパシティの概念があるんじゃないの。
書き込む順序が変な場合だったりすると上手くいかんかもしれんが
copy や transform を使う分には事前にキャパシティを調整した上で
値の書き込みは back_inserter を使えば無駄な初期化も再配置も起こらない。 >>749
insert_iterator は嫌なの? 初期化が重いならコンストラクタと初期化を分ければ良いし
微妙なコピーによるパフォーマンスを気にするなら自作すれば良い
無い物ねだりは時間の無駄 >>755
アロケータはメモリアロケーションに関する制御しか出来ない。
std::vector に与えるアロケータをどう実装しても
要素のコンストラクタの起動を制御することは出来ないと思う。 int a = 0; //こうしないとエラーな環境なんてイラネーヨ
if(cin >> a) cout << a; >>751
そうすると一々サイズとキャパシティ比較するif文挟むから結局オーバーヘッドあるやん
まあstd::vector使うなというのはもっともでこういうときのためにstd::make_XXX_for_overwriteがある >>760
vector::reserveをご存知でない? >>761
back_insert_iterator での値の追加は push_back するのに等しい。
https://timsong-cpp.github.io/cppwp/n3337/back.insert.iter.op=
push_back するときはキャパシティが足りるかどうかで動作が異なる。
https://timsong-cpp.github.io/cppwp/n3337/vector.modifiers
結果的にキャパシティが足りていてもキャパシティが足りているかどうかのチェックはおこなわれる。
そのことを >>760 は言ってる。 STLコンテナのうちvectorだけがC言語やシステムコールで使う配列との互換性を保証するのだから「vector使うな」とか噴飯ものだよ >>760
いわれてみれば確かにゼロコストというわけではないね。
現代的な CPU だと分岐予測が効く場合だと思うので実行時間的には小さいと思うが……。
スマートポインタに for_overwrite 版が入ったなら vector でもやろうという提案は
絶対に出るだろうと思って検索してみたら vector については見つけられなかったが
basic_string::resize_and_overwrite を足す提案はあったわ。
http://wg21.link/P1072R10 >>765
の何がダメなのかちゃんと言えますか
分かってないくせにstd::vector<bool>貶してる奴見ると腹立つわ >>766
文脈的に >>765 は >>763 を受けてのものなんだから配列との互換性の話なのは自明やん。 極限チューンしたいならvectorなんか使うな
vector使うなら多少のオーバーヘッドは気にするな 極限チューンしたいならC++なんか使うな
C++使うなら多少のオーバーヘッドは気にするな
とか言っちゃうのかねこういう人は。 >最速チューン
>極限チューン
特にしたくありせん 極限とか感情的バイアスで話すやつはマトモに相手しとれん 昔は煽って情報引き出そうとする輩もおったけど、今はAIに聞けば全部教えてくれるんだよな AIねえ・・ライダハンて何って聞くとキムチ臭いことを「教えてくれる」けど
おまえはそれを何だ? 神様のお告げとか思ってるの?
アホなの? それともバカなの? 今すぐ首吊って死ねよ 機械と人間の違いがわからねーやつは人類全ての敵だ
機械は言われたとおりにやってるだけ
そこにポリシーも夢もひとかけもない
呆れ果てたスーパー情弱のために教えておいてやるが
機械にできるのは演繹だけで帰納はできないって根本的な問題があるんだよ
教わったことが絶対でどんなにおかしい答えも平然と言ってのける
日教組に洗脳されたおまえとそっくりだなwww 代わりに辞書を引いてくれるだけでも大したもんだよ
引き方によってはちょっとした会話にもなるしな 根本的な話をすると脳のニューロン組織とAIプログラムのニューラルネットワークは動作原理は同じ
生体細胞の圧倒的物量による並列処理能力の高さと半導体素子の圧倒的記憶演算能力による方向性の違いだけ
いずれ学習が飛躍的に進めば機械が脳を超える時が来る 脳内でバックプロパゲーションとか起こってると思ってるならあまりにももの知らんねキミ まあ中枢神経でも逆行性の情報伝達は起きてるけどな
そんなことより改行の後スペースは何回打つのがメジャーなんか?
なおタブ派の意見は聞かない なんか上から目線でえばってるくせに帰納の意味がわかってなさそうなのがいるなksks >>777
私?私?
今でも炎上学習法は通用するのかな? 人が作った焼き物に手を合わせて神のご加護をってやつだろwww priority_queueに渡す比較関数って、functionでインライン的に書くより
別途ラムダを書いてそれをdecltype()で渡す方がいいんですかね?
後者と同等なインライン的な書き方はあります? >>790
ラムダ式は視認性を改善する目的で使うものなので、ラムダ式のせいでかえって視認性が悪くなるようであればあきらめ時 >>790
インライン的な書き方ってどんな書き方? 例えばfunctionを使って比較関数をインライン的に書くとこうですよね
priority_queue<int, vector<int>, function<bool(int a, int b)>> pq([](int a, int b){return a > b;});
一方ラムダを使った場合は例えばこんなですよね
auto comp = [](int a, int b) { return a > b; };
priority_queue<int, vector<int>, decltype(comp)> pq(comp);
で疑問に思ったのが
- 上記の例で後者の場合もインライン的に書ける? まソース的には1行目と2行目を改行なしで
書けばいいのかもしれないけどw
- function を使う場合と decltype を使う場合の違いに何が違う?
ということです う、二番目の質問がおかしい
- function と delctype で単に書き方が違うという以上の違いはありますか? function と decltype は単にシンタックスが違うだけというなら、これからは一番最初の
function を使った書き方で行こうかなと思います C++17以降ならdeduction guideが使える
priority_queue pq { [](int a, int b){return a > b;}, vector<int>{} }; メモリ確保と同時に初期化、
これをしないことによる顕著なメリットの説明がそろそろあってしかるべき……
初期化をしないことによってメモリ確保はメモリ確保1回あたり(デフォルトコンストラクタにもよるが)数千~数万クロックサイクルぐらい早くなるかもしれないが
プログラムの実行速度を追求したいならそもそもメモリ確保とかいっぱい回るループの中ですべきではないし、
そもそも領域を確保しておいて初期化を後回しにするとか、プログラミを不必要に複雑なピタゴラスイッチ化するだけ……
もっとも、毎秒1万回std::vector<T>を構築するとか、サイズ3TBのFIFOを作るとかなアフォ
構想時点で極めて特殊な設計なら話は別やが…… それよか一番危険なのは、
>必要があれば初期化するし
>必要なければ余計なことはしない
>
>判断できましぇ~んなアホにはなりたくない (キリ
とのたまう人が、encueカウンタやdecueueカウンタが未初期かなFIFO、みたいな
益体も無い例を持ち出してみたり、冒す必要のない危険を冒してまでリリースしてしまうことや…… >>784
教師信号はどこから来るというんじゃ…… まず、えんきゅーできゅーのスペル確認ぐらいしてくれ。 >>801
>>800はアホなんから構うなよ
>>23とか>>674とか見りゃやべーヤツって分かんだろ char fifo[256] = 俺はここのことを言った
char* enq = ここの話に逸らした時点でアホの相手はやめた >>796
std::function は実行時に型を切り替える機能をもったクラスで、
後から切り替える可能性が無い場面では無駄になるから避けるのが普通だと思う。
#include <functional>
int foo(void) { return 1; }
int main() {
// 関数ポインタとクロージャは異なる型だが
// std::function は呼出しの形式が同じならどちらでも扱える
std::function<int(void)> bar = foo; // 関数ポインタを格納できる
bar = [](void) -> int { return 1; }; // クロージャも格納できる
} コンパイラと標準ライブラリによるんだろうけど、
std::functionはラップしてるぶんラムダに比べて遅いだろうね
でもラップしてるおかげで柔軟だから用途次第で使い分けるのがいいね anyみたいにRTTIを使っているわけじゃないけどね bool型を整数に変換した時、false -> 0, true -> 1 は保証される? ですか
何個条件が成り立っているかを数えるときに上記を使ってるっぽいコードがあったので WindowsのBOOLは保障されない点だけ気を付けよう
==TRUEとかやっちゃダメだからね TRUE==1 FALSE==0 は仕様で明確に保証されていたかは知らんが事実上変えようがないから実害はないな。
注意するのは「FALSEでない値」とTRUEは違うってことで。 #define True !Fales はもう昔の話か GetMessage() < 0 とかもうアボカド #define True !False
printf("%d", True);
# 1 c++の入門書のサンプルでは、整数を 42で初期化するケースが多い気がします
この 42(fooやbarを使うように)には意味があるのでしょうか constevalな関数の中でchar配列中からintを読み取る場合ってポインタ使えないから下記のようにするしかない?
arr[index] | ((int)arr[index + 1] << 8) | ((int)arr[index + 2] << 16) | ((int)arr[index + 3] << 24); >>823
constevalじゃなくても環境依存せずにその手の数値取り出しをしたければそうする他無い。
あと(int)は意味ないと思う。 32bit-little endianであることを前提になるがいいか?
あとこれarr[3]が0-127に収まってないとintの符号ビット壊しそうだし、
charが符号付きの環境だとシフト+bit orが意図通りにならなそう >>823
consteval使えるならbit_castも使えるのでは >>827
配列の一部だけを参照する方法がないから
bit_cast を使うなら bit_cast を使える状態にする必要があって
この場合はあまり楽にならない。 >>826
おもいっきり環境依存なコードに対して環境依存を心配するアホ >>826
おもいっきり環境依存なコードに対して環境依存を心配するアホ 右シフトはおもいっきり符号にひっぱられるけど左シフトならセーフだべ? (0x0ff & (int)a[i]) |
(0x0ff & (a[i+1] <<8)) |
(0x0ff & (a[i+2] <<16)) |
(0x0ff & (a[i+3] <<24))
これでよろしかですかの? >>834
そんなことしなくても (int)(unsigned char) でいいのでは? (unsigned int)arr[index] | ((unsigned int)arr[index + 1] << 8) | ((unsigned int)arr[index + 2] << 16) | ((unsigned int)arr[index + 3] << 24); いや、こうか
arr[index] | int((unsigned)arr[index + 1] << 8) | int((unsigned)arr[index + 2] << 16) | int((unsigned)arr[index + 3] << 24); 以下はTCP/IPのクライアントを作成する例なのですが、このコードにタイムアウト値を付けるにはどうしたら良いですか?
http://onishi-lab.jp/programming/tcp_win.html
// Windows の場合
WSADATA data;
WSAStartup(MAKEWORD(2,0), &data);
// 相手先アドレスの入力と送る文字の入力
printf("サーバーマシンのIPは?:");
scanf("%s", destination);
// sockaddr_in 構造体のセット
memset(&dstAddr, 0, sizeof(dstAddr));
dstAddr.sin_port = htons(PORT);
dstAddr.sin_family = AF_INET;
dstAddr.sin_addr.s_addr = inet_addr(destination);
// ソケットの生成
dstSocket = socket(AF_INET, SOCK_STREAM, 0);
//接続
if(connect(dstSocket, (struct sockaddr *) &dstAddr, sizeof(dstAddr))){
printf("%s に接続できませんでした\n",destination);
return(-1);
} >>842
ありがとうございます。
この記事のWindows版を参考にしてタイムアウトつき接続できたのですが
https://qiita.com/hidetaka0/items/501ad17b4c23c3adee03
これってちゃんとサーバーに接続できた場合、接続できたことをコード内のどこで判別すれば良いのでしょうか?
色んな箇所にprintを仕込んでみたのですがよくわかりませんでした。 ネットワークプログラミングスレってあったと思うんだけど
何でここで質問するのか理解できない >>844
そこにprint挟んでも通過しないんですよね
繋がってるのに >>846
ほんとにつながってるの?
そこ通らないと他はエラー(-1)しか返さないんじゃないの? >>846
あと、printfはメインスレッドからコールしないと遮断されること普通にあるぞ
ファイルにfprintfで書いてみれよ あと考えられる問題は、スレッドのスタックが足りなくてprintfがコールできていない可能性だな
いろいろと洗ってみれ >>847
以下のようにprintというかcoutを挟むと、接続前はずっと"1"が出力されるのに、接続後は何も出力されなくなります。
エラーも出ず、プログラムは動き続けます。
int sockNum = select(socket + 1, &readFd, &writeFd, &errFd, &timeout);
if(0 == sockNum)
{
//timeout
std::cout << "1" << std::endl;
return -1;
}
else if(FD_ISSET(socket, &readFd) || FD_ISSET(socket, &writeFd) )
{
std::cout << "2" << std::endl;
}
else
{
//error
std::cout << "3" << std::endl;
return -1;
}
std::cout << "4" << std::endl; そこ、コードが間違ってるな
selectのエラーは負の値返したときだよ だがしかし、エラーじゃなくてタイムアウト検査して0と比較しているからこのままでも問題はないか
timevalのタイムアウト値がまちがってんじゃねーの?とは思う socket + 1って何だっけ
おかしい原因これじゃないの?こういうもんだっけ? VisualStudio使ってるんならステップ実行したほうがはやいんじゃね
1行ずつ実行してどこでクラッシュ/待たされてるかすぐにわかるぞ >>855
コード内のどこでconnectを呼べば良いですか? 初心者なのですが、find()で結果がないときnposの場合と.hoge.end()の場合、
イテレータで hoge.begin()とする場合と begin(hoge)とする場合(end()も同様)、等
混乱しております。これは... nposってstd::basic_stringのか?
#include <algorithm>のfindとは別物だぞ
メンバ関数でfindを持っているオブジェクトならhoge.begin()
持っていないオブジェクトにはbegin(hoge) >>858
algorithm にある std::find と string にある std::string::find の違いのことかな?
それはまあ名前が同じだけの別物なんでそういうものと思うしか仕方がない。
begin については、
異なるものが共通のインターフェイスで扱えるとテンプレート内で扱いやすいだろうというのが基本的な事情。
でも配列とかポインタがメンバを持つことは出来ないからこれらも含めて共通の扱いをしたい場合は
メンバ関数の begin よりも非メンバ関数の std::begin を使う必要がある。
メンバに begin を持っている場合はそれを直接に呼んでも std::begin を使っても結果は同じだよ。
C++ には ADL という仕組みがあって引数に関連する名前空間も関数を探す探索対象になるというルールがある。
std::begin は ADL の仕組みと相性が悪いところがあって扱いづらいので
新しい仕様は std::ranges::begin が導入された。
ややこしいんだが全部を一貫して説明できるような統制された理屈があるわけではなくて
細々とした歴史的事情の積み重ねでグダグダになってるだけ。 intとsize_tって足し算したらsize_tになるんか・・・? 改めて書くと
std::vector<...> vec;
int neg = -15;
for(int x = neg ; x < neg + vec.size() ; x++){ ...
こんな感じのfor文の中になぜか入ってこず
for(int x = neg ; x < neg + (int)vec.size() ; x++){ ...
こう書き換えたらfor文の中にちゃんと入ってきたので
何事かと そりゃビット数の多いsize_tに自動的にキャストされるからな 32bit intが表現できる範囲(-21億〜+21億)と
size_tが表現できる範囲(32bit環境なら0〜42億、64bit環境なら1800京)が違うんだよね
直接キャストしたり比較演算した結果が一目で分からないし、
未規定の動作も紛れてるから
コンパイラによって結果が変わったりする ちなみに更に厳密なことを言うと std::vector::size() の返却値の型は std::vector::size_type であって、
一般的な実装では size_t の別名として定義されることが多いけどそうでないこともありうる。 移植性を気にする人ってtypename std::vector<hoge>::size_typeとか書いてるの? こんなかなあ
不用意にsize_t決め打ちはなるべくしない(せざるをえない場合もある)
auto N = v.size();
for(decltype(N) i = 0; i < N; ++i) { /**/ } 単にsize_tの型とイコールじゃなかったらエラーではねとけばいいんじゃね
想定外環境でも何でもかんでも通そううなんて思考はバグの元になるし なんでsize_tをunsigned にしたんだろうな… そりゃサイズに負数はあり得ないからでは?
-12バイトのファイルなんてありえないですし 数の概念が生まれた当初は負の数なんて想像つかなかったしな。
マイナス3個のリンゴとか存在しないし。 つまりマイナスの概念が存在しない時からsize_tは存在していた!? 負数があるならssize_tやptrdiff_tと使い分けなよ… for (size_t k = 999; k >= 0; k--) {
... for (size_t k = 999; k+1 > 0; k--) {
... size_t の変数を 0 との大小で比較しても
常に >= 0 だから変なことになる
for で -- してるときは特に注意な 符号無しループはグーグルだとコーディング規約違反だからな コーディング基準はあくまで特定案件での決めごとに過ぎず
井の外で何かを批判する根拠に使っても説得力はない 符号ありしかない言語もあるから、それなりに一般性あるかと 特定案件つーてるのに他の言語?
話通じないやつだな std::vector<T>::size()やstrlen()が符号無しで返してくるからそれらを使った汎用ライブラリ的なものを書く場合に仕方なくsize_tを使うこともあるだけでループ変数については符号有りで大して困らない希ガスだいたいOS記述言語であるところのC言語がアセンブラでは常識的に利用されるゼロフラグやキャリーフラグの概念を捨て去った設計した点をかみしめるべきや整数表現のMSBまで符号以外の意味で使わねばならないシチュエーションはマジ少ない多倍長演算であってさえ2のべき乗範囲に拘るのを捨てたらゼロフラグやキャリーフラグを駆使してビット幅全部使う記述と同等以上の効率にできうる スレチだと思うけどx86intrinsicsに詳しい人がいたらNonTemporal命令について教えてもらいたい
_mm_stream_load_si128や_mm_stream_si32はCPUキャッシュに対象範囲が無い場合はキャッシュスルーして確実にメモリを読み書きするということは分かったけど、
CPUキャッシュにある場合の挙動は一般的な命令同様にCPU内だけで完結してしまう? >>894
パフォーマンスを気にしてるなら実験、測定するべきだし
同期ならメモリバリア命令など適切な措置を取るべき 素人考えで悪いけどメモリへの書き込みがされずCPU内だけで終わると困ると思うけど
勝手なイメージ
書き込むアドレス内容がキャッシュに
ある
キャッシュのデータも書き換える → 通常の動作
ない
_mm_stream_si32の場合 キャッシュへデータを読み込まない → 速い
その他の場合 キャッシュへデータを読み込む → 遅い avx2でnon temporay loadの方を比較したけどほぼ変わらない
サイズが小さすぎたせいかもしれないけど >>896
目的はDMAとの整合性で既存の実装は勿論同期処理していたが
数日稼働させてみてTemporal命令混ぜた後にstreamストアしても今のところ不整合発生してないからもうちょい様子見てみる >>898
本来のnon temporal命令の利点はその命令自体の速度ではなくキャッシュ汚染防止だね
例えば離れたアドレスにあるであろうstatic変数にアクセスするとき、その付近のデータには一定期間内に一度しかアクセスしないと分かりきっているなら、CPUの親切心による近隣メモリのキャッシュへの先読みはどうせ使われないのでむしろペナルティでしかなく不要となる
あとはmemcpyにおいてキャッシュはソース側に集中させてディスト側へは_mm_streamでキャッシュ汚染を抑えてコピーをするというテクニックもあって多分メジャーどころのコンパイラ実装は大体そうなってる
IvyBridge以降であればsimdより強化版rep movsbの方が早いケースも多くて分岐によってそっちに行くこともあるだろうけど >>900
それなら納得
AMDでも試したけど変わらないな それとx86intrinsicsと書かれてるのはSystem.Runtime.Intrinsics.X86 名前空間で.netなんだ
コンパイラがキャッシュを気にしたIL吐いたりそこから最適化されたネイティブコードを吐くようにはできてないと思う これまでなんとなくinitializer_listを使ってきたのですが
このクラスって他のクラスと異なりコンパイラによって特別な解釈をされるのでしょうか?
以下のhoge::initializer_listはstdからコピペしてpublicメンバ以外を除外したものです
hoge::initializer_listを実体化するとコンパイルエラーとなります
コンパイラは g++ (Debian 10.2.1-6) 10.2.1 20210110 です
#include <initializer_list>
#include <cstddef>
namespace hoge {
template<class _E>
class initializer_list {
private: // 割愛
public:
typedef _E value_type;
typedef const _E& reference;
typedef const _E& const_reference;
typedef size_t size_type;
typedef const _E* iterator;
typedef const _E* const_iterator;
constexpr initializer_list() noexcept;
constexpr size_type size() const noexcept;
constexpr const_iterator begin() const noexcept;
constexpr const_iterator end() const noexcept;
};
}
int main () {
std::initializer_list <int> il0 = {10, 100, 1000};
hoge::initializer_list <int> il1 = {10, 100, 1000}; // <- コンパイルエラー
return 0;
}
エラーメッセージは
error: could not convert ‘{10, 100, 1000}’from ‘<brace-enclosed initializer list>’ to ‘hoge::initializer_list<int>’ エラーメッセージから考えると
1. { ..., ..., ..., }はstd::initializer_listと解釈される
2. std::initializer_listをhoge::initializer_listに変換しようとしてエラー
ということだと予想しますが
上記の1がstd::initializer_listを特殊なクラスとしている言語仕様と考えれば良い? >>903
constexpr initializer_list(std::initializer_list<_E> const&) noexcept { }
これを追加すると通る
コンパイラは { } で std::initializer_list を生じる、という意味で「特別な解釈」をする
似たような話で typeid() で std::type_info を生じるのと同様 継承も何もしてないのにhoge::で上手く行くワケないだろ せめて>>985みたいにstd::initializer_listを何かしらの形で受け入れ口としてコンストラクタに実装してやらないと通らないだろ 一般にstd名前空間のものは全部言語仕様と一体のものとしてあらゆる特別扱いが許されてるので
ヘッダからコピペして作った自作クラスが標準と同じように振る舞ってくれない可能性は常にある >>905-908
みなさん有難うございます
>>908
>一般にstd名前空間のものは全部言語仕様と一体のものとしてあらゆる特別扱いが許されてるので
これは最小限にして欲しいものですね
>>905
>似たような話で typeid() で std::type_info を生じるのと同様
なるほどー! 言われてみればこれも気持ち悪かったです
同種の気持ち悪さ 低レベルな質問ですが、よろしくお願いします
char str[10] = {0};
char str[10] = {0,};
この二つって違うんですか? 最後のカンマの次に項目を書かなくてもエラーにならなくなった名残だな >>911
最後のカンマに文法上の機能はなく、単に余計なカンマを許容するだけ。
どちらも 0 がひとつ与えられる初期化子であるという扱いになる。
コードジェネレータで生成するときに余計なカンマを許容したほうが便利だからそうなってる。
初期化子の数が配列の大きさに足りない場合は >>913 の解説の通り 0 が補われるので10個の要素全部がゼロになる。
なので全部をゼロにしたいときは char str[10] = {}; というように書いてもよい。
(新しい規格では改定されているが) C では波括弧の中に 1 個以上の値を必要としたので
それに合わせて必ずひとつは 0 を書くというスタイルで書く人もいる。 丁寧な解説ありがとうございました。
どちらとも10個ともに0になるんですね STLにある、k番目の要素を見つけるnth_element()は計算量がO(n)だそうですが、
これの中身が何をやっているかの日本語の(できるだけむずかしくない)解説ってどこかに
ありますかね? GPT-4の説明が分かりやすかった
std::nth_elementの説明として正しいかは分からんが
うまく動きそうではある
GPT-4に知らないことを聞くのはかなり危険だなぁ... >>920
C++で書きさえすれば速いとかは幻想
高速化のためのアイディアを考え甲斐があるのがC++ サブルーチン単位で見たらJavaやC#の方が早いこともあるけどそれはC++側のコードが糞なときだからな
マネージド言語はループ回すにしても強制的に一々長さチェック入ったりするので本気出したC++にはいずれにせよ敵わない 昔、JavaでもC++同等性能出せます(ただしメモリ使用量は10倍)
みたいなネット記事を見たのを思い出したわ そんなの実際はほぼないだろ
ありうるとしたらC++のコードは最適化がかからないでC#は最適化掛かってsimd使ってましたとかじゃないのか? メモリの管理やチェックもしてくれた上で条件によっては C++ を超えることもあるってくらいなら充分以上に速くはあるけどな。 >>926
C#の場合はコードジェネレーターが発達してきてるからC++はprintfで動的フォーマット、C#はprintfをジェネレーターで静的展開みたいなパターンで後者の方が早いという事があり得る
jsonのパースやシリアライズとか特に x86ターゲットでビルドしたC/C++プログラムをARMでx86エミュレーション実行すると遅い
Java/.NETは中間コードだからランタイムさえARM版になっていれば性能が出せるね C/C++はコンパイル時に命令が決まるから中間コードよりビルド済バイナリの長期運用では不利になるよね
ソースコードからリビルドできる環境があれば問題ないんだけどさ 環境なんて開発者それぞれでしょ
Macbook使ってるけどx86エミュレーションで動いてるアプリがいくつかあるんだよ
開発者さんがまだM1/M2を持ってなくてARMビルドがリリースできてないんだと思う(もしくは飽きて開発放棄してるのか) とにかく既存バイナリを異なるCPUアーキテクチャで動かす状況が現実にあるわけ
Macに限らずWindowsでもね
そのような状況では.NETアプリは軽快にどうさするのにC/C++アプリは遅いということになる めちやくちゃだな
C++の開発環境にハンデ付けたらそうなるわ Javaや.NETの中間コードにしてCPU命令セットに依存させないアプローチはポータビリティだけでなくランタイムごとの最適化を可能にするメリットがあるの
これC/C++では無理でしょ ランタイムが対応していない環境ではC++の勝ちだな C++のスレで「ネイティブなバイナリはエミュレータ上で遅い」って主張して何の意味があるのか?
場違いなこと言ってないか少し考えような >>935
Apple文化ではCPUが変更されるが、Windows/Intel文化ではデスクトップでは
変更されたことが無い。PC/AT互換機はずっとx86系。 「C++は速い」って盲目的に信じてるキッズの目を覚ます意味がある ターゲットを限定できる組み込み系開発ならともかく
一般消費者向けのアプリではC/C++が最速とは限らないという話だよ 仮想化やエミュレーションを何重にも重ねて実行するのが当たり前の現代的コンピューティングでは
「ネイティブで速い」なんて限定的な状況での一つの特長にすぎないんだよね >>940
マイクロソフトは異なるCPUアーキテクチャに挑戦し続けてきたよ
そもそもNTのマイクロカーネルアプローチは様々なCPUアーキテクチャに対応するためのものだった
Alpha、PowerPC、IA-64で動作するWindowsが過去には存在した
既存のx86バイナリを動かせなかったことから失敗してしまったけどね
今はARM Windowsに挑戦中
これはMac同様にx86エミュレーションで既存バイナリを動かせるようにしてる
アプリ開発者としてターゲット環境を1つに限定すると不利になっていく思うよ >>942
C言語はUnixをマルチターゲットで実現するするために作られた言語である件について:
プログラム作成にいくら手間がかかっても良いという話なら
#ifdef / #else / #endifの山でマルチターゲットに配慮しつつ高級アセンブラ的に使用したときのC言語が
中間言語実行または中間言語からのJITで巻けるシチュがわからん
説明できるんならkwsk、 そうではなくてプログラム作成の手間も込みの話なら
特定の応用においてErlangがC言語に勝った話は有名な話
https://ipsj.ixsq.nii.ac.jp/ej/?action=repository_uri&item_id=12&file_id=1&file_no=1
やが、C言語で書かれたオープンなErlangのVMでそのパフォーマンスをたたき出した場合、
何の言語が勝ったことになるんじゃ…… >>945
それは既に説明したよ
C/C++が想定したターゲットに対して最適なバイナリを出力できるのは事実
でも既存バイナリの長期運用では最適な速度を出せない状況に遭遇することがあるんだ
実際にM1/M2 MacやARM Windowsでそういう状況が生まれてる >>947
>C/C++が想定したターゲットに対して最適なバイナリを出力できるのは事実
>でも既存バイナリの長期運用では最適な速度を出せない状況に遭遇することがあるんだ
話が矛盾している
既存のVM(これも既存バイナリのうち)がなんで常に最適な速度を出せることになるんdai? >>948
個々のアプリをリビルドせずにVMだけリビルドすれば済むからエコシステムを維持しやすいの
たしかM1 Macが出てから半年も経たずにARM版JavaVMが登場したと思う
JavaアプリはIntel MacでもM1 Macでも同等の性能が出る
ネイティブアプリは各開発者がARMビルドをリリースするのを待たなければならなかった(まだIntel版しか存在しないアプリも多い) >>949
>個々のアプリをリビルドせずにVMだけリビルドすれば済むからエコシステムを維持しやすいの
>たしかM1 Macが出てから半年も経たずにARM版JavaVMが登場したと思う
>JavaアプリはIntel MacでもM1 Macでも同等の性能が出る
>ネイティブアプリは各開発者がARMビルドをリリースするのを待たなければならなかった(まだIntel版しか存在しないアプリも多い)
そのネイティブアプリとは一体……
およびそんな特定のケースを言語の優劣の一般論として展開してよい根拠とは一体……
および>>946はどうなるんじゃ……
さらに言うと、VMの改修による新規プラットフォームのトータルサポートが、特定の応用で#ifdef/#else/#endifを何個か追加して
ソースからビルドするより常に早いとする根拠は一体…… ごめんね
話が噛み合わないようだからこれで最後にする
一般論として言語の優劣を語ってるつもりはないです
ソースコードからのリビルドよりVMが速いとは言ってないです
開発者の事情でリビルドされない既存バイナリで性能が出ない状況が実際にあると言ってるだけです さっきも書いたけど常にc++の最適化が他の仕組みに勝つとは限らないから
他の言語でsimd化されてc++でsimd化されない場合もあるだろうと データベースでは長期運用でデータ数が変わるから、
統計情報を参考にして、使われるアルゴリズムも変わる
特に、IBM では全自動のみ。
自分で、使うアルゴリズムを指定できない C++はメモリーのフラグメンテーションを解消できないからJavaより遅いというエンジニアの意見は有名だと思う データベースでは独自のガベージコレクションくらい実装している Java仮想マシンとARM向けx64仮想マシンの比較ですか >>954
フラグメンテーションで遅くなるのは、キャッシュの影響だけ。
ソートだけはキャッシュが乱れまくるので、特殊。
それ以外は、ほとんどの場合は、遅くならない。 キャッシュの乱れによる速度低下を防ぎたいなら:
・ソートは本当に必要な場合だけ行なう。
・ソートする場合でも、要素数が少なければ特に問題ない。
すべてがキャッシュに載ってしまえば、キャッシュミスが起きないから。
・そもそも物理シミュレーターではソートは必要ないことが多い。
なぜなら自然の物理法則はソートの概念を用いていないから。
・レイトレーシングなども物理法則に基くので、基本的にソートを
余り使わないでよいアルゴリズムを作ることが出来る。 >開発者の事情でリビルドされない既存バイナリで性能が出ない状況が実際にあると言ってるだけです
そういう話ならそういう話で、
>既存バイナリの長期運用では最適な速度を出せない状況に遭遇することがあるんだ(>>947
と言ったときに、何と何の比較なのか(何なら「最適な」速度なのか)というレギュレーションを先に示して……
ソースコードからリビルドするだけで元より速くなるケースが本当にあるなら、そういうケースの提示をすっとばして
Javaや.NETの中間コードにしてCPU命令セットに依存させないアプローチの話なんてしないで……
一般的な速度比較ではなくて、他の言語でsimd化されてc++でsimd化されない場合の速度比較ならその話だけして……
アスペにill-definedなビミョーなネタ振りをしないで…… 補足、
>既存バイナリの長期運用では最適な速度を出せない状況に遭遇することがあるんだ(>>947
と言ったときに、最適な速度をたたき出すブツが発言者の脳内にしか無いのだとしたら
そんなの単なるお気持ちの表明やんけ……
自分は最初から正しい論理展開をしていたみたいな顔するのはやめて…… >>961
はじめから「中間コード」と「ビルド済バイナリの長期運用」って書いてあるぞ? 俺は産業用システムのフロントエンドUIをC#で組むことが多いんだが、とあるデバイスの制御APIがネイティブDLL(.NETアセンブリではない)で提供されていたんだ
そのデバイスメーカーはなぜか32ビット版のDLLしか提供してくれなかった
それでC#プログラムも32ビット版.NETランタイムで動かさなきゃならなくなった
C++が速いとかどうでもいいけどさ、せめて64ビットビルドできるようになってから言ってくれないかな? C++が速いとか関係なく、そのデバイスメーカーに言え 64ビット版.NETランタイムから32ビットDLL使う方法あるでしょ
NeeViewがそういうことしてる 最近のc++プログラマってプロセス間通信も知らないの? NeeViewもSusieプラグイン用の32bitプロセス起動してプロセス間通信してるだけやで 比較と称して対立煽りすればスレの勢いが伸びる
ただし意味のある議論はほぼ発生しない
技術板にアイデンティティを勝手に感じている技術力ゼロの雑魚だけがこういう話を振り、乗っかる >>964
>はじめから「中間コード」と「ビルド済バイナリの長期運用」って書いてあるぞ?
同じアプリの*実在する*中間コード版と
*実在する*長期運用されたビルド済バイナリとで比較しているのかっていうか、
その根拠こそ求められる
>>964はふいんきに飲まれて詐欺に遭いやすいタイプなのではないか…… >同じアプリである必要あるか?
ある
「中間コード」と「ビルド済バイナリの長期運用」の速度を比較しようとしているのだから、
それらの違い以外は同じに保たねば正しい比較にならない 0xの頃のように混とんとしてきたが、あの頃の熱さはないな 昔Windows上でJavaがエラー吐いたとき
VCのエラーを出力してたから
裏ではC++使ってるんだろ
つまりJavaもC++のパワー借りてんだから
C++のほうが速いって話にならない? C++はエンジン、Javaはターボという関係では? 命令を記述出来るかってこと
AVXやNEONはコンパイラじゃ性能出ない あー 自分で書きたいのか
Javaの場合はJEP417 Vector APIでAVX命令を扱えるよ >>894 >>895
自分で書けなきゃ性能出ないって言ってるのに
例えばvpshufbなんかコンパイラが使わんでしょ
Javaは遅いっていう流れで書いたわけで ???
JavaのVector APIはSIMDを扱うために新たに策定されたもの
C++の動的配列std::vectorとはまったくの別物よ? ごく一部の命令をごく一部の処理で使えたってダメだよ
1000個以上も命令あるんだし
コンパイラが使いこなせなそうな命令の具体例を上げてるのに
CやC++ならいろんな方法で使えるわけで
・ライブラリ経由
・Intrinsics
・インラインアセンブラ
・アセンブラ 意味の無い比較じゃなくて
目的に対して適切な言語を使うのが大事だよな
ところでrustはc++より速いの? >>991
煽りよるwww
>>992
C++ の一番のつらさはいつの間にか未定義を踏み抜いていることなので
そういうのでとけていく時間と天秤にかけたら結果的に Rust のほうが「早い」こともある。 処理系定義や未規定を未定義と誤認するやつ
理由がコンパイラに警告されたからとか
笑っちまうよな 未定義踏みぬくなんて高度なことをやってるんだなと書きながら
単純化すると
cout < i++ < i++ < i++;
みたいなコードを書いている うーん酔ってるな
<< << <<
おわかりいただけだろうか? このスレッドは1000を超えました。
新しいスレッドを立ててください。
life time: 132日 18時間 46分 42秒 5ちゃんねるの運営はプレミアム会員の皆さまに支えられています。
運営にご協力お願いいたします。
───────────────────
《プレミアム会員の主な特典》
★ 5ちゃんねる専用ブラウザからの広告除去
★ 5ちゃんねるの過去ログを取得
★ 書き込み規制の緩和
───────────────────
会員登録には個人情報は一切必要ありません。
月300円から匿名でご購入いただけます。
▼ プレミアム会員登録はこちら ▼
https://premium.5ch.net/
▼ 浪人ログインはこちら ▼
https://login.5ch.net/login.php レス数が1000を超えています。これ以上書き込みはできません。