C++相談室 part166

1sage (ワッチョイ 8732-NXaD)
垢版 |
2025/04/26(土) 10:34:58.41ID:pbPDl6lv0
!extend:checked:vvvvv:1000:512
!extend:checked:vvvvv:1000:512
↑同じ内容を3行貼り付けること

次スレは>>980が立てること
無理なら細かく安価指定

※前スレ
C++相談室 part165
https://mevius.5ch.net/test/read.cgi/tech/1698705458/
VIPQ2_EXTDAT: checked:vvvvv:1000:512:: EXT was configured
2025/09/08(月) 07:59:15.17ID:It1Ffdlu0
>>618
これわ別問題じゃないのですか。
にしても、おとろしい
push_backされた時点で再構築されて、新規作成のオブジェクトの要素を保持してしまったで合ってますか?
2025/09/08(月) 10:27:54.64ID:bx3qX9/R0
状況を一から説明すると……
これは fifth が古い無効になった場所を参照する可能性があることが問題。

std::vector の各要素は連続した空間に配置されることが保証されている。
要素の増減でその場所の都合が悪くなれば再配置される可能性があり、
再配置が起こったときは要素を指していたイテレータや参照は無効になるというルール。
無効なイテレータや参照を通じてアクセスしたら何が起こるかわからない。

再配置が起こる可能性がある操作については個々に仕様に書かれているけれど、
キャパシティを変更する (可能性がある) ような操作はどれも再配置が起こりえると覚えておけばいい。

そんでもってこれのややこしいところは「可能性がある」ってところで、
キャパシティをどれくらい拡大するか実装によって差があるし、
状況によっては場所を移動せずに大きさを伸ばせるかもしれない。
つまり問題が顕在化しないかもしれない。

一般論として倍々に延ばす実装がよく知られているからこの例では最初に要素を 8 個にして
顕在化しやすいようにしたんだろう。
2025/09/08(月) 10:47:28.92ID:It1Ffdlu0
>>620
どもです。要素数8ってのもさすがって感じでした。
2025/09/08(月) 22:24:25.56ID:EA0JjXQaM
>>620
今回の問題に限ればその通り
ただし問題の本質は二つの参照(変数fifthとpush_back呼び出し時の参照)を使ったこと
今回はダングリング参照で問題を分かりやすく示したがメモリ問題もvectorも本質ではなく任意のデータに対する参照で問題が起きる

既に参照fifthを持つ状況で同じデータを指す別の参照を関数push_backに渡してデータが書き換えられた
参照fifthが指す値は当初から値が変更されてしまったりダングリングで無効な値になる可能性がある
これが二つの参照の競合による問題で値がいつの間にか書き換わってしまっていることでバグも誘発する
両方の参照が書き換えを伴わないreadonlyの時のみ安全になる
片方もしくは両方の参照が書き換えを伴うと安全でなくなる
2025/09/08(月) 23:06:53.70ID:HoahUzIM0
再配置が行われるものに参照使って、その生存期間を超えてアクセスするのは未定義動作になるわな。C++に慣れてればそんなコードは書かないが、初級者向けではない。readonly より、lifetime の問題でしょう
2025/09/09(火) 00:29:11.16ID:TMUamLpP0
参照が無効になる条件は規定されてるし、先にcapacity設定するとか避ける方法も用意されてる
「問題の本質」とやらはただのライブラリ仕様の無理解だろ
分かりにくいとか間違えやすいとかの批判なら分かるけど
2025/09/09(火) 07:24:41.95ID:DVL1/TmTM
>>623 >>624
申し訳ないがcapacityや再配置の話はしていない
lifetimeや参照が無効になる話もしていない
まずそれらを頭の中から消し去って考えよう
元々の話である同一データに対して参照が二つ持った時の話のみをしている
もちろんvectorは登場してもしなくてもいい
2025/09/09(火) 07:29:27.85ID:DVL1/TmTM
元々の話とは>>610>>613でこれらが参照の競合の最も単純な例
様々な言語で発生してもちろんC++でも生じる
同一データに対して複数の参照を持つと他の参照によっていつの間にか指していたデータの値が書き換わってしまう
これがバグやコードのスパゲッティ化を引き起こす最も大きな原因の一つ
そのためreadonlyでない限り複数の参照を避けるのが好ましい
そのため競合する参照を禁止している言語もある
627デフォルトの名無しさん (スフッ Sdba-bj1o)
垢版 |
2025/09/09(火) 10:47:02.21ID:g327vfuJd
readonlyでない競合する参照を禁止している言語もある
2025/09/09(火) 12:16:08.28ID:iPWQv8Oa0
はいはい線型論理言いたいだけ
2025/09/10(水) 00:51:51.50ID:BnR46AnOa
>>618
これはvにpush_backしたところでキャパ超えて別の場所にリアロックされ、ともない元のvの領域が空になって、即座にwがスポンとそのvが元あった場所に配置されたってことなのですか?
2025/09/10(水) 02:12:52.51ID:IF/zSGeMd
そうだよ。
規格上は何の保証もないから、処理系とかによっては全然違う結果になるかもしれないけど。
2025/09/10(水) 10:07:49.21ID:3vsmg39oa
>>630
どうもありがとう
632デフォルトの名無しさん (ワッチョイ 4e1f-bj1o)
垢版 |
2025/09/10(水) 10:13:08.62ID:zTYInGVv0
>再構築されて新規の要素を保持してしまったで合ってますか
こう聴かれると「違う」と返事したくなる
2025/09/10(水) 18:40:20.64ID:Vv9EwJFH0
未定義動作だからな
たまたま鼻から悪魔が出る代わりにそうなっただけだ
2025/09/10(水) 22:18:27.54ID:RAO/BxQt0
参照の競合という用語に違和感。並行性に関わる競合状態 (race condition) の話をしようとしているのか?
2025/09/10(水) 22:31:03.50ID:BZTqerG60
してない
2025/09/22(月) 23:24:45.15ID:ZT49UQS30
でわ 簡単?な話題を。
int data{}; ってやります? int data{0}; ってやります?
2025/09/23(火) 06:55:15.77ID:S9rfzcfC0
int data = 0; ってやる
2025/09/23(火) 10:47:53.44ID:0b1Ncss10
auto data = 0;
とか、型が明示的なのが好みなら
auto data = int();
といった選択肢もある。

私は
int data = 0;
派だけど。
2025/09/23(火) 10:57:08.68ID:NP1ck5iL0
>>638

autoを使う理由は?
2025/09/23(火) 11:12:21.28ID:0b1Ncss10
>>639
暗黙的であれ明示的であれ初期化子に型があるのだからそれとは別にもう一度型を書くのは二度手間と言える場合がある。
どういう考え方をとるべきなのかは場合による。
2025/09/23(火) 11:17:00.61ID:NP1ck5iL0
>>640
autoは曖昧だから、ゆるいプログラム用だね
シビアなプログラムは無理
2025/09/23(火) 12:32:51.63ID:zwbfimRS0
>>638
イテレータの返しを受けるオブジェクトはauto使うと便利みたいな
2025/09/23(火) 14:23:55.04ID:SO+rqWsF0
>>641
テンプレート作るときには必須になる場合もある
ゆるいって理解は雑
2025/09/23(火) 14:48:06.92ID:0b1Ncss10
前提条件を変えると何でも言えてしまう。
とりあえずここでは発端は >>636 なのだから変数 data の型が int であり (多相にはしない) 内容はゼロで初期化するという狭い仮定を置いたほうがよかろう。
auto を持ち出したのは変に話題を曲げてしまったな。すまぬ。
2025/09/23(火) 20:34:08.12ID:3YWvMRZsr
今北

いまさら人に聞けない
auto って、右辺の型もそのまま左辺にコピーしてきてよ、って感じで使ってるんだけど
その認識で間違ってない? 落とし穴とかある?
2025/09/23(火) 20:39:56.49ID:7uroOMzl0
右辺が式の場合もあるし
その時自分が思ってた型とautoの型が一致するとは限らないところとか
2025/09/23(火) 21:26:37.10ID:qWXNEai60
autoで手抜きしすぎるとあとでソース追うときにエライ苦労することあるから気を付けろよ
2025/09/23(火) 21:34:42.79ID:NP1ck5iL0
>>647
Pythonとか、
型が書かれてないから追いづらいよね
2025/09/24(水) 02:24:38.07ID:hHyw0Adk0
>>645
その認識でおおよそ正しいが変則的な部分もある。
auto foo = { 1, 2, 3 };
みたいに書くと initializer_list に推論されたりするのは知らないとちょっとびっくりするかもしれない。

それと修飾子などを組み合わせで使うことも出来る。
const auto* bar = &baz;
みたいに。
2025/09/24(水) 07:20:39.19ID:tMR45KsJ0
>>649
何の目的であるの?
C#的にゆるくなるだけだな…
2025/09/24(水) 08:23:07.29ID:yL+cLVSS0
>>650
ゆるいというのがどういう意味で言ってるのかわからないからなんとも言えない。
特に有用なのはテンプレート内で、たとえば

template<class T>
void foo(T x) {
auto bar = baz(x); // baz は関数テンプレートだとする
// ここでなんやかんや
}

みたいなのがあるとき auto を使わずに型を合わせて書こうとすると

template<class T>
void foo(T x) {
decltype(baz(x)) bar = baz(x); // baz は関数テンプレートだとする
// ここでなんやかんや
}

みたいになってわずらわしい。
初期化子の型をそのまま持ってくれば良いときに型を明示しても可読性に貢献しないし、簡便な記法があると楽。
652デフォルトの名無しさん (JP 0Hc6-xemb)
垢版 |
2025/09/24(水) 12:48:43.78ID:4f1PT/5nH
std::make_sharedとか使うと行が長くなりがちだからauto便利
653デフォルトの名無しさん (ワッチョイ 4a4e-rfem)
垢版 |
2025/09/24(水) 23:18:51.30ID:OQUpbPvH0
autoでしか出来ないこともあるから奥が深い
2025/09/24(水) 23:47:45.55ID:wXWMV3aG0
罠仕様が仕込まれてるってだけでは
2025/09/25(木) 06:56:54.48ID:iHrblX0Rr
Rust派に言わせれば、C++が罠らしいぞw

でもそのC++が、今の俺を生んだ
2025/09/25(木) 16:58:42.68ID:tx4jrZ/E0
有用なときもあるけど、ライブラリ用のコードで乱発するとメンテナンスが大変
可読性メンテナンス性を考えるなら、冗長でない限りはちゃんと書いた方がいい

>>651
それもbaz(buz?)の戻り値の型はTから導出出来るんだから、よほどややこしくない限りはそれ(decltypeで手抜きせずに)を書いた方が可読性メンテナンス性の面では良い
2025/09/25(木) 17:00:57.66ID:/3f9OB3n0
>>656
お前テンプレートプログラミングの素人さんだよね
2025/09/25(木) 20:40:29.81ID:tx4jrZ/E0
>>657
自己紹介乙w
Expression Template使って線形代数のライブラリ作った人間だが、ETで利用者がauto使うとどういう問題が起きるか答えてみ
まさか分かりませんとか言わないよな?
テンプレート使ったライブラリ(てか標準ライブラリ)を"利用する"しかしたことのない人間が調子に乗るな
2025/09/25(木) 20:43:04.50ID:nRsNESWS0
なんか「その理論を作ったのは私ですが」みたいなものを感じる
技術発表の際の怖い質問とかなんとかのやつw
660デフォルトの名無しさん (ワッチョイ 4a4e-rfem)
垢版 |
2025/09/25(木) 20:43:46.25ID:ofoI5OnU0
言葉ならなんとでも言えるわな
2025/09/25(木) 20:44:29.25ID:hN2fGih80
>>651
ふーん
便利だね

でも、templete自体が何だか好きじゃないわ…
2025/09/25(木) 20:46:08.51ID:hN2fGih80
>>656
ちゃんとっって、型を?

型が書いてないと、パット見でわからないよね…
2025/09/25(木) 20:54:22.86ID:tx4jrZ/E0
>>662
そう&同感
ぱぱっと書いて何やってるかもすぐ分かるような場面(戻り値がイテレータとか)ではそりゃautoでいいと思うけどねぇ
2025/09/25(木) 21:36:33.99ID:SUv+BSiy0
今ならconceptを使うのが筋が良いんだろうな
他の言語みたいに型制約を書かずにジェネリクスを使えるけど、これは良くも悪くもだよね
楽と言えば楽だけど
2025/09/26(金) 01:34:47.37ID:aJA0eUoF0
>>658
リポジトリ晒して

まさか出せませんとか言わないよな?
テンプレート使ったライブラリ(てか標準ライブラリ)を"内製する"しかしたことのない人間が調子に乗るな
2025/09/26(金) 01:53:11.78ID:IAhZoqBcM
>>658
端的に言って

> それもbaz(buz?)の戻り値の型はTから導出出来るんだから、

ここだよ
関数テンプレートなんだから型が導出できるとは限らない
なぜお前は断言したのかな?
導出できない例にぶち当たったことがないからだよな
2025/09/26(金) 07:26:52.27ID:uQKo8FSG0
>>665 >>668
煽ればタダで教えてもらえると思ってるいつものアホか

>導出できない例
あるわけないだろどうやって実体化するんだよwwwwww
668デフォルトの名無しさん (ワッチョイ 8e02-C7mS)
垢版 |
2025/09/26(金) 08:15:01.31ID:FGFv/5hn0
conceptはテンプレートだけじゃなく普通の変数制約にも使えればなぁ。
継承がほとんどいらなくなる。
669デフォルトの名無しさん (アウアウウー Sacf-kv3/)
垢版 |
2025/09/26(金) 10:28:59.69ID:UkFmEBgMa
>>647
判ります
2025/09/26(金) 11:12:51.14ID:TfDLIQWg0
手抜きというか情報を重複させないためにはautoが必要
苦労するのは型情報を追えないツールが悪い
2025/09/26(金) 11:53:52.65ID:IRzSnzQy0
>>648
ああ、おそろしいあの言語は
素人にはササッと組めて楽チンだろうけど大掛かりなものは無理だろうな
想像しただけで脳が震えて耳から溶けて出てきそうだ
2025/09/26(金) 12:02:33.14ID:E9e6Z1Un0
expression template を auto で受けるとまずいってのは Eigen みたいな設計の話かな。
あれはムーブがない時代の設計だから一時オブジェクトの参照を保持してしまう (先に一時オブジェクトが解体されて寿命管理が破綻する) のが問題なのであって、解決のための仕組みが与えられたにもかかわらずそれを使ってない設計が悪い。
expression template の仕組み上でどうしても解決できないというわけではないし auto のせいでもない。

ムーブのコストすら許容できないだとか、古い C++ (C++03 以前) もサポートしなきゃならないみたいな事情があるなら「すまんけどこのライブラリを使うときは注意して」というべき筋合いの話で、「auto なんか使っとるからじゃ!」みたいな態度はおかしいだろ。
2025/09/26(金) 12:09:27.62ID:uQKo8FSG0
>>672
>のが問題なのであって
違う。ETの場合、関数(演算子オーバーロード含む)が返すのは、式の構造を表すオブジェクトなのでそれをautoで受けると式の展開が行われず、計算処理の無いコードになってしまう
それを逆手に取ってauto経由で展開のタイミング遅らせることもできるけどね

あとETの利点はムーブどうこうで解決できる問題だけではないし、
誰も「ETを万人が使うべき」だなどと言っとらんよ、何が気に入らんかったの?

で、はちみつお前いつも「知ったかぶりしていい加減なことを言う奴」に怒ってる割に、自分も同じ事してるよな
2025/09/26(金) 12:11:01.51ID:uQKo8FSG0
あと
>「auto なんか使っとるからじゃ!」
一言も言ってないんだが。流れ読み直しておいで
2025/09/26(金) 12:54:00.88ID:E9e6Z1Un0
>>672
> autoで受けると式の展開が行われず、計算処理の無いコードになってしまう

書いてなかったが評価タイミングは適当な関数で明示的にする前提を置いてた。
未定義を踏むのは他の何と比べても駄目だ。単に思ってた結果と違ったなんてのは重要じゃない。

> 誰も「ETを万人が使うべき」だなどと言っとらんよ、何が気に入らんかったの?

日常的には使わないケースだからこそだ。
それが auto の問題点のように挙げられてただろ?
ライブラリのほうが C++ の自然な習慣に合わせるのが筋なのにさ。
2025/09/26(金) 13:15:19.27ID:4po4sxfpp
>>657-658
2025/09/26(金) 13:19:26.24ID:4po4sxfpp
>>675
あと、ETで式の評価が発生するのは関数の呼び出し時ではない。どうでもいいけど
あと俺が作ったのは4次元まで(行列なら4x4まで。ゲーム用なので)だからヒープ使わんのでそもそもムーブどうこうは関係無いし、勝手によそのライブラリの未定義の話を持ってこられても困る
2025/09/26(金) 13:57:45.37ID:E9e6Z1Un0
>>677
eigen は例として話題に出したつもりだったが余計だったな。
端的に主旨を言えば expression template の原理的には auto で受けれるように作ることは可能、かつその方が親切な作りだろうという話をしてる。

お前がどんな設計をしたのかなんてそれこそ俺には知ったことじゃないし、知りようもない。
お前のライブラリで auto で受けれないのはお前がそう設計しただけの話なので、 それを根拠に auto がどうこう言ってもなんの足しにもならん。
2025/09/26(金) 14:04:20.28ID:4po4sxfpp
>>657-658
ETの話はここで出した。

で、俺のautoの使い方に関する意見は>>656

自分が何をやってるか良く考えてからレス書き直せ
2025/09/26(金) 14:08:11.66ID:E9e6Z1Un0
>>679
悪い設計のせいで利用者に不自然な書き方を強いるライブラリを作ったという話だということは理解してる。
2025/09/26(金) 14:13:42.65ID:4po4sxfpp
あといちいち知ったかぶってるバカに教えてやるのも腹が立つが、普通数値演算でET使うときは代入演算子やコンストラクタに式を渡した場所で初めて式を展開するんだよ
(autoでわざと評価を遅延させることも可能だと書いただろアホ)
Eigenでも多分そう
もちろんboost::spiritとかの構文解析ならパース処理の関数に渡すまで展開しないだろうが
2025/09/26(金) 14:14:19.90ID:4po4sxfpp
>>680
不自然なのはお前の、「スキルに見合わない自尊心」だと思うぞ
2025/09/26(金) 14:24:32.42ID:4po4sxfpp
バカが屁理屈書いてきそうだから再三言うが、>>658>>657を叩くために出した問いに過ぎない
「意図しないコードになる」という話

これだからお前には絡みたくないんだよマジ鬱陶しい
2025/09/26(金) 17:03:47.95ID:iKKvsVQ80
お前ってのははちみつのこと言ってるのかね?
自分から絡んどいて何言ってんだろうコイツとしか思えんけど
2025/09/26(金) 17:53:41.26ID:uQKo8FSG0
>>684
で、>>666の導出出来ない例って何?www
2025/09/26(金) 19:18:42.84ID:+hZbpaFa0
>>685
ラムダの型導出できないだろ?
なんでこんなのも知らんのにえらそうにしてんの?
あと

https://wandbox.org/permlink/q5sTF1hp76f7jpnq

とかな
この例でfooでもif constexprを使えばautoはなくせるがそんなことやって可読性とかほざけない
他にもパターンあるぞ
謝罪してお前が作ったらしいヘボライブラリ公開したら教えてやってもいいぞ
2025/09/26(金) 19:32:01.31ID:uQKo8FSG0
屁理屈にも程がある
導出出来なきゃどうやって実体化するんだよ、Tしかテンプレートパラメータが無い状況でT以外に依存するものがあるのか?
まさか結果がTに依存するテンプレートになったら「導出出来てない」とかほざくの?
Tに依存するコンテナのイテレータと何も変わらんよそれ
2025/09/26(金) 20:12:50.41ID:uQKo8FSG0
てかその例でauto使わずに戻り値格納するのにif constexpr使うしかないと思ってるとかどんだけ経験不足なんだ・・・(はっきり処理分けする必要がある場合を除く)
そんなクソみたいな例ならさすがにdecltypeかauto使いたくなるが(そもそも使うなと言ってないんだが)、conditionalも知らんのかお前は
必死に探してきてご苦労さん
2025/09/26(金) 20:41:40.17ID:aJA0eUoF0
あの…そろそろ言っとくが

おもろいこと書いたヤツが優勝な?
2ちゃん5ちゃんの原則だぞ
2025/09/26(金) 20:46:36.85ID:uQKo8FSG0
>>665はおもろいと自分で思ってんの?w
2025/09/26(金) 20:59:48.54ID:+hZbpaFa0
>>687
おじいちゃん、ラムダの例で詰んでんのわかる?
わかんない?
わかんないかぁ
2025/09/27(土) 00:06:32.90ID:ov4hhnsF0
やっぱautoはゆるいね
C#とかPython的な感じ…
2025/09/27(土) 05:08:15.66ID:rNLW6nkI0
C++は自由なんだよ

変な風にも使えるし、傍で見てたらめちゃくちゃにもなる
2025/09/27(土) 05:36:45.87ID:p3kzti810
自分が使った方がいいと思った時は使う。
しかないよ。後は規約や上司に従うぐらいか。
2025/09/27(土) 11:22:44.98ID:0x5FUGdK0
久々にC++スレらしくなってておっちゃん楽しいよ
2025/09/27(土) 17:37:01.17ID:nSvwU9re0
>>681
コンストラクタや代入演算子で実際の計算を起動する方式も支持があるのは知ってるよ。
だからその代表例として有名どころの Eigen を話題に出したのだし、そこに齟齬はない。
その上で唯一の方式ではないし悪い設計だと言ってる。

私に反論するならどうしてそんな方式を取るのか利点 (悪い設計ではない理由) を説明すべきだった。
「数値計算で expression template を使うときは普通」なんて情報量ゼロのことを書かれても何の意味も感じられない。

コンストラクタや代入演算子をトリガーにするのは expression template を最適化として使う考え方だ。
つまり見かけ上は普通に式を書いてるだけなのに実は高速化しているというのがキモで、普通の式である「かのように」見える抽象化に意味がある。

実際の型を意識せざるを得なくなった段階で抽象化は破綻してる。
auto を使ったら何が起こるかを意識しなければならないのはライブラリ設計の失敗なんだよ。
隠れていたりいなかったりする半端な抽象化層を悪い設計と呼ぶのは間違ってるか?

> 再三言うが、>>658>>657を叩くために出した問いに過ぎない
> 「意図しないコードになる」という話

そんなので意図しないコードになってしまうような作りのライブラリは出来が悪いという話なのはかわらん。
様々な事情に配慮してそうならざるを得ないということもあるというのならわかるが、
そうじゃなくて「それが普通なんだ」と思い込んだ狭い見識での判断なんだろ?

型を書くか auto にするかはスタイルの問題で、どちらを使うかで挙動が切り替わってしまうような設計のライブラリが本当にまともか?
2025/09/27(土) 17:54:13.79ID:iipvXy1W0
よほど悔しかったんか知らんが、恥の上塗りやめたら?
autoをC++に取り込んだ人達は、お前が調子に乗るために提案したわけでも採用したわけでもなかろうよ
698デフォルトの名無しさん (アウアウウー Sacf-kv3/)
垢版 |
2025/09/27(土) 19:49:03.02ID:k7oMySGea
>>696
八光さんに同意だけど
それだとC++が設計ミスと言う結論になりかねない
2025/09/27(土) 20:00:56.28ID:nSvwU9re0
C++ が設計ミスだらけなのは今更な話だろ。
2025/09/28(日) 18:27:48.51ID:MSQtxm6D0
解決しますた!
2025/09/28(日) 19:20:47.09ID:pjQge+jC0
そうか。
2025/09/29(月) 19:03:56.70ID:ALxfRd8b0
VSCode(WSL)のclang-tidyで質問です
関数にconst付けるのを警告する「readability-make-member-function-const」って奴ですがDoSave()関数にも警告が出ます
可能ならgetterのみに付けたいのですが皆さんこれはどうされてますか?
無効にしてるか、無視してるか、const付けてるか、その他何かやってますか?

C++の環境構築は初めてなので助言をいただけるとありがたいです
よろしくお願いします
2025/09/29(月) 19:56:30.29ID:BDszbKFL0
こういうこと?
要はconst性を「セーブさせたくない」という符丁に使いたいのかな

class Hoge; // DoSave()持ち

void foo(Hoge& h1, const Hoge& ch2)
{
  h1.DoSave(); //ゆるす
  ch2.DoSave(); //ゆるさない
}

そんな変なことやめとけとしか思わないけど、どうしてもそうしたい理由があるなら言ってみ
2025/09/29(月) 20:49:50.37ID:Qgirjd9Z0
const_cast<Hoge*>(&ch2)->DoSave();
2025/09/29(月) 22:22:15.60ID:ALxfRd8b0
>> 703-704
すみませんサンプルを載せるべきでした

ソース:
double Point::X(){return x;}
void Point::X(double value){ x=value;}
ヘッダ:
static Point {
public:
double X();
void X(double value);
private :
double x=0;
};
clang-tidy を実行すると「double Point::X()」のX部分で「Method 'X' can be made const (readability-make-member-function-const)」という警告が出ます
調べてみると「constを追加して、内容が変更されないことを明確にすべき」らしいです
ソース:double Point::X() const {return x;}
ヘッダ:double X() const;

上記だけなら問題無いのですが、下記のような関数にも同じ警告が出てしまいます
ソース:void Sample::DoSave(){ ファイルの保存処理 }
ヘッダ:void DoSave();
この場合、getterではなく処理なので、const は付けるべきでは無いと考えてます

そこで質問ですが、clang-tidy で静的チェックを行う場合「readability-make-member-function-const」の扱いはどうすべきなのか気になった次第です
「無効にすればいいのか」と思いながらも、C#のプロパティではないので、「C++は変更されないことを明示した方が分かりやすいのか?」とどのように設定すべきか悩んでいます
よろしくお願いします
環境は下記:VSCode、ubuntu 22.04 (WSL)、C++ 17、clang-tidy-15
2025/09/29(月) 23:01:05.35ID:jk3QzjEU0
NOLINT
2025/09/29(月) 23:04:57.63ID:rfIMSjI90
>>705
その場合const付けたほうが良い理由は「変更されないことを明示」することより
constのインスタンスに対してその関数を呼べなくなることでは?
↓はエラーか警告(どっちかは忘れた)になると思う(constオブジェクトの非constメンバ関数は呼び出せない)

void SaveData(const Sample sample)
{
sample.DoSave();
}

void Sample::DoSave() const { ファイルの保存処理 }
にしておけば、DoSaveは呼び出せる
2025/09/30(火) 01:33:12.30ID:Xmjd+d/v0
処理だからconst付けないんじゃなくて、そのメンバ関数がPointクラスの中身を書き変えないことを保証するためにメンバ関数の後ろにconstは付ける
つまり、Save処理はPointクラスを特段変更するメソッドではないだろ?
だったらconstは付けるべき
2025/09/30(火) 07:07:46.33ID:NaKN2pJV0
>>705
つまり、constを本来の意味(中身を変更するかどうか)ではなく「getterであるかどうか」を示すラベルとして使いたいってことでしょ?
で、何を持って「getterであるかどうか」はあなたの頭の中にしかない定義であって、そのlintはもちろんコンパイラもエディタも世のライブラリも知ったことではない
それらをオレオレconstラベルに適合させるためにどうしたらいいか?というのがあなたの問うていることだ
やっぱりどうしてそんなことがしたいのか全く理解できない
2025/09/30(火) 08:58:44.76ID:0fqHawiZ0
>>705
オブジェクトがなんらかのストレージを抽象化したものであると考えたらそのオブジェクトが const であるときはセーブ機能を使えないようにしたいというのはわからんでもない。
実際の管理は他の場所でやっていて窓口に過ぎないならメンバ関数に const を付加可能 (だがそうしたくない) なこともあるだろう。

それが良い設計かどうかは脇に置いてそうすることに決めたときに clang-tidy の警告はどうすればいいのかということなら、
例外的な状況なので例外的なものとして無視してもらうしか仕方ないんじゃないか。
NOLINT コメントを書いておくと clang-tidy はその箇所については警告を抑制してくれるよ。
2025/09/30(火) 10:38:19.22ID:Dzyyn8xKd
>>706-710
御返事がおそくなりすみません
ご意見ありがとうございます
自分の理解不足と設計思想が間違ってるまたはずれてるんだと理解しました

・「readability-make-member-function-const」の指示にしたがってconstを付けるのが良い
・更に言うと-fixオプションで自動付与するレベルの内容
・だけどNOLINTで無視もできるよ(無視してるとは言ってない)

ってことで理解しました
勉強になりました
ありがとうございます
712デフォルトの名無しさん (ワッチョイ 2596-TDpG)
垢版 |
2025/09/30(火) 21:38:35.37ID:bXNPhBlr0
VC++20のテンプレート制約で不可思議なことが起きるのだけど、以下の二つは同じ意味だよね?
1だと目的通りTParentに該当static関数<T>があれば適用、なければスルーという挙動になるのだけど、
2だと無くても適用されちゃって他を探しに行かずにオーバーロード未解決に陥るんだけどどういうことだろう?

1
template<typename T, typename TParent> concept HasSizeGetter = requires { (size_t)TParent::template get_size<T>(); };
template<HasSizeGetter<TParent> T> static consteval size_t get_require_space() { return TParent::get_size<T>(); }

2
template<typename T> requires requires { (size_t)TParent::template get_size<T>(); } static consteval size_t get_size() { return TParent::get_size<T>(); }
713デフォルトの名無しさん (ワッチョイ 2596-TDpG)
垢版 |
2025/09/30(火) 21:40:50.61ID:bXNPhBlr0
ちょっと書き間違えてたけど1はget_require_spaceじゃなくてちゃんと2と同じくget_sizeね
2025/09/30(火) 23:39:48.15ID:0fqHawiZ0
>>712
オーバーロード未解決という形で現れるのはよくわからないけど
この場合はその関数テンプレートを使わなくても (呼び出さなくても) エラーになるのが正しい挙動だと思う。

get_size は依存名ではないのでテンプレートの定義時 (テンプレート実引数を当てはめる前) に名前のルックアップが試みられて失敗する。
requires 節はテンプレート引数の妥当性を検証する仕組みなのでテンプレート引数をあてはめなくても式が不成立になるようなのはエラー。

というのが私の理解なんだけどあんまり自信はない……。
2025/09/30(火) 23:47:38.26ID:0fqHawiZ0
>>714
これは TParent::get_size が存在しない場合の話で、
TParent::get_size が存在するけど TParent::get_size<T> の展開に失敗する場合はちゃんと次の候補が選ばれるはず。
(手元に MSVC がないんだけどオンラインコンパイラで一応の動作確認はした。)
2025/10/01(水) 06:54:56.10ID:O1Ml42XO0
>>715
そう、2の場合でもTParent::get_sizeはあるけど<T>とはマッチしない場合にはちゃんと1と同じ挙動になるんだよね
TParentにstaticなget_sizeが全くない場合だと1と2で挙動が変わってしまう
でも2って1をインラインに直接書いたものであって同じ意味だよね?
だからrequiresがどういう意味を持つかとか以前に挙動変わってくる時点で不可思議なんだよね
2025/10/01(水) 07:43:33.30ID:XKqCU3PC0
>>716
1 の場合は get_size は依存名だ。
そこで解釈が違うよ。
718デフォルトの名無しさん (ワッチョイ faa6-/eJP)
垢版 |
2025/10/22(水) 12:58:32.68ID:6nuMV8zc0
C++26から入るらしい^^と[::]という二つの演算子はどういう用途に使うものなのでしょうか?
2025/10/22(水) 13:31:13.53ID:/iXiQCcE0
>>718
リフレクションで検索したら色々な例がみつかるよ。
構文要素を値として取り扱う、本物のマクロだ。
レスを投稿する

5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

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