C++相談室 part146
レス数が950を超えています。1000を超えると書き込みができなくなります。
ん? 俺は江添じゃねえぞ
奴なら標準会員だから言ってみるのもいいが >>854
>診断メッセージをよく見ろよ
見た上で言ってます(つまりgccまたはVC, clangのバグではないかということ
>いいか、constexprは翻訳時定数だぞ
それ以前にテンプレートなんですが 誰でも閲覧できる規格ドラフト見ればすぐにわかることをこんな掃きだめで聞いても >>862
なんかとんがってんな
コンパイラのバグとまで言う根拠は何だ?
相場では規格票の条文だが
テンプレートなのは見ればわかるさ
だから何なのか説明をやめないでくれ >相場では規格票の条文
通産省の癖の抜けない老人はご退場いただきたい >>772
>x86系CPUで普通のメモリへの読み書きで順番が入れ替わる可能性があるのは write => read だけ
別に。
コアAの読み書きをコアA自身が見る分にはそうかもわからんが
コアAの読み書きを異なるコアBから見たらwrite同士やread同士でも順番が入れ替わり得る
(アウトオブオーダー実行の影響で
安全に動かすには適切にメモリバリアで順序化する必要がある >>868
read ==> read
read ==> write
は入れ替わらない といってもロックレス何ちゃらぐらいの制御であればInterlockedCompareExchange()で済むから
スレッド間の通信なら普通メモリバリアとか直接触る必要は無いが リードキューやコマンドキューにコマンドが入るのはアウトオブオーダープロセスの事後であるため
そのような保証は無い x86系は
シングルコアのマルチスレッドアプリ
の多くがそのまま動くように出来てる
シングルコア時代が長かったから >>865
>テンプレートなのは見ればわかるさ
>だから何なのか
普通に考えて、実体化がまだなのに定義(初期化)を強制される妥当な理由はない、ということ 確かにリンク先のインテルのマニュアルの
>8.2.3.2 Neither Loads Nor Stores Are Reordered with Like Operations
>Example 8-2. Stores Are Not Reordered with Older Loads
に
>Initially x = y = 0r1 = 1 and r2 = 1 is not allowed
と書いてあって>>875と同じことが書いてあるが疑わしい
マニュアルが間違っているのではないか、
ちな
>8byteのデータはアドレスが8の倍数のときにアライメントされている。
から安全に読み書きできるというのはi486みたいな古いプロセッサーだとかえって危険らしい
>8.1.1 Guaranteed Atomic Operations
を見たらワカル、 つか上のインテルのマニュアルには「投機的実行時中のメモリアクセスではメモリアクセス例外は発生しない」
旨が2箇所ぐらいに書かれているが、
ということはつまりアセンブリコード上A→BまたはA→Cというメモリアクセスが条件によってどちら片方だけ実行されることを意図したコードであっても
A→B→Cというメモリアクセス順に成り得ることを意味し、他コアからもそう見えてしまうはずだが、
これをメモリアクセス順がreorderされていないうちに入れてしまうのはどうなのか、、、
マニュアル執筆者の国語の再教育が必要なのではないか >>877
おまえさん、もしかして
テンプレートの宣言と定義と
オブジェクトの宣言と定義を
ごっちゃにしてないか?
int test;
int test = 5;
これは宣言と定義じゃなく定義の重複だぞ お前なぁ
x86のこと大して詳しくないのにしゃしゃり出てくるからそういう情けないこと言うはめになるんだよ
x86でstd::atomicのmemory_orderを変えてバリア付きがどういうインストラクションになるか見てみな
storeのseq_cst以外は素のmovだから(コンパイラ依存だから絶対ではない) そりゃー間違ったマニュアルにしたがって実装したら間違った実装になり得る(キリ
ていうかアウトオブオーダー実行の影響がマルチコアCPUにおいても透過的だと認めやっても良いが、
>>879の投機的実行の件はどうなんじゃ?
あるコアが投機的実行中に他のコアをストップさせるのでは何のための投機的実行かわからん… >>877
× 普通に考えて
〇 俺の頭の中で
× 妥当な理由はない
〇 妥当な理由は思い当たらない
テンプレートなら初期化は不要という主張なら、
constexpr 変数の宣言と定義を分離できないことは納得してるのかな?
そうだとして、それをテンプレートの時だけ可能とすることに意義があると思うの?
特別ルールを設ければコンパイラ実装やプログラムの読み取りにコストがかかるから、
明確が意義がなければ特別ルールは無いのが妥当だと思うよ。 >>880, >>883
マウント取るのが最優先でまともな回答できない(するつもりも無い)んなら黙っててくれ
>これは宣言と定義じゃなく定義の重複だぞ
externつけたら?
>それをテンプレートの時だけ可能とすることに意義があると思うの?
テンプレート実引数に使われる型が不完全型であっても、実体化まで評価を遅らせられる
さて、
>× 普通に考えて
>〇 俺の頭の中で
>× 妥当な理由はない
>〇 妥当な理由は思い当たらない
こんなゴミみたいな煽り入れてきたからには逃げるなよ >>884
おまえさんの元の質問はこうだったな
template <typename T> constexpr inline T value;
template <typename T> constexpr inline T value = (T)0;
どこにexternなんて書いてある?
マウントがどうたら気にするあまり後出しなんかしてるのはそっちだぞ
こっちはそんなこと微塵も考えちゃいねえよ失敬な
最初の口調に戻れよ 間違えた
Xテンプレート実引数に使われる型が不完全型であっても、実体化まで評価を遅らせられる
○初期化に使われる定数式の評価を遅らせられる
言い換えれば、宣言と定義を分離できないならconstな変数テンプレートの宣言時には
それに使う定数式内のすべての型が完全型であることを強制されてしまう
=std::is_integral_v = std::is_integral<T>::valueでいえば
is_integral構造体の方が取り回しがいい、ということ
なんのために変数テンプレートが導入されたのか・・・・ >>885
自分が失敬だからこうなってるとは考えられないんだな
何様だよ、そもそも質問に答えてないだろうが >>887
template <typename T> constexpr inline T value;
template <typename T> constexpr inline T value = (T)0;
を例示しての質問に対して
int test;
int test = 5;
という答えをしているぞ
valueがtestになったのは悪かったが
余計な飾りをとって問題の核心を指摘したんだよ 規格でそうなってる(テンプレートゆえの特例は無い)のが”わかってるなら”
最初からそう言ってくれれば済むんじゃないの?
>>854を読み直せよ、テンプレートのことが完全にすっぽぬけた上に失礼な回答だろ
>コンパイラのバグとまで言う根拠は何だ?
とまで、って・・・・普通にありえるだろ、動作が違うんだから(未定義とかいう屁理屈は無しで)
で、>>883は逃げたの? >>886
やっぱり constexpr 変数の宣言と定義を分離して何がしたいのか、
何ができるようになるのか、が見えてこない。ごめんね。
宣言だけ見える constexpr 変数への参照やポインタだけはとれるようになるけど、
それだともう constexpr である必要なくて const 変数でよさそうで、それならふつうに
宣言と定義は分けられるし。
ちなみにテンプレート実体化までテンプレート引数依存箇所の評価はされないから、
宣言と定義を分ける話を「評価を遅らせられる」と言い表しているのも何か間違ってそう。
「記述を遅らせられる」の間違い? だめだこいつ
絶望的に人に者を尋ねる態度がわかってない
「言ってくれれば済む」とか図々しすぎ
技術的な議論がしたいがこいつ相手では
不必要にイラついちまって無理だわ
俺そんなに人間できてない >>891
すまん、
>テンプレート実体化までテンプレート引数依存箇所の評価はされない
これ検証してみたらたしかにそうだった
手元のコードで完全型を要求されたから、初期化時に不完全型を使えないと思い込んでた
(おそらくconstexprな変数テンプレートの実体化が、必要な型の実体化より先に来てたっぽい
多分構造体か何かでワンクッション置けば解決できると思う)
これなら確かに分けられなくて問題無いね
>>892
>いいか、constexprは翻訳時定数だぞ
>それを翻訳段階9まで未解決のままにできると思うか?
>なんかとんがってんな
>後出しなんかしてるのはそっちだ
>余計な飾りをとって問題の核心を指摘したんだよ
さらには
>最初の口調に戻れよ
の上で
>技術的な議論がしたいがこいつ相手では
>不必要にイラついちまって無理だわ
よくそんなセリフが言えたもんだ
自己評価高すぎじゃない?wwww 意見が合うとか合わないとか以前の問題
根底的なメンタリティに欠陥がある相手とは話にならない FYI
>>846
Bug 68012: g++ incorrectly accepts forward declaration of constexpr variable template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68012
>>848
One definition rule
https://timsong-cpp.github.io/cppwp/n4659/basic.def.odr#1
> No translation unit shall contain more than one definition of any variable, function, class type, enumeration type, or template. >>895
わざわざありがとう、やっぱgccのバグだったのね >>837
オーバーロード=多態性じゃないんで…
オーバーライドのことなら当然cで実現できる >>898
どうやって?
いや、ディスパッチの方法はいろいろあると思うが 禿もそんなことを言いながら
virtualの導入には当初反対から出発したんだよな >>899
その話題QZ相手にやったばかりなんで自分で調べて >>898
overload は、同じ関数名で仮引数の型が違う関数を作れるという多態性のことですよ。 ツリーのイテレータがあるとして、イテレータが返すのはノードじゃなくて、ノードの持つ値ですよね?
すると、イテレータは立体機動出来ないといけなくなるけど、begin().begin()とか変ですよね?
begin().parent()とか。 イテレータが返すじゃなくて、イテレータの逆参照が返すかな。 コレクションとしては子孫ノード全部を列挙できればよくて、ツリー構造に沿った操作が行いたいなら
それに加えて直接の子ノードのみを列挙するイテレータが用意できればいいだろう。 何が子ノードのみを列挙するイテレータを返すかがよくわからない。
ノードの値がイテレータを返すことはできないので、ノードが子ノードを指すイテレータを返すとすると、イテレータの逆参照はノードを返すことになる。
これは意味論的にちょっと違うかなって。
コレクションにおいて位置はイテレータで示されるので、立体的な位置を持つツリーでは、イテレータ自身が立体機動出来て、巡回能力を持つイテレータは、reverse_iteratorのように外部に用意されれば良いのかなと思ったんだけど。
たとえば、レベルオーダーや深さ優先の巡回イテレータがあるとすると、普通に考えるとスタックやキューが内部に必要にある。
というわけでコピーのコストがあるので、これを標準には出来ないんじゃないかなって。 子ノードを指すイテレータの逆参照が子ノードを返すとすると、*node.begin()は子ノードを返す。
**node.begin()は最初の子ノードの値を返すことになるんだけども。
イテレータの逆参照がノードを返す場合、初期化子リストが素直に実装出来てイイんだけども、イテレータの逆参照が値を返さないのが腑に落ちない感じ。 >>903
こらこらoverloadは多態じゃない多重定義だ
多態はpolymorphism間違えるな イテレータは演算子の実装を求められてるわけではなく、その演算子を呼び出した時の効果を求められてるだけなので、++(int)はスタックをコピーしない方法を考えた。 そこは値じゃなくてノードを返すイテレータでいいんじゃね?
必要ならイテレータ自体を拡張してもいいだろうけど、この場合はあまり応用できそうもないし。 まずイテレータで何を抽象化したいかを明確にしなよ
ノードを意識させたいのか? STL風ツリーって検索しても絶対出てこないし、CIAが絡んでるような気がしてきた。 そこがわかんないんだよねえ。
禿4とか読んでると、イテレータは位置を意味してるように思うんだけど。 ツリー構造
範囲が広すぎて
汎用化すると使い勝手が悪くなるからしない
ってだけかと recursive_directory_iteratorとかね いや立体がどうたら言ってるから
じゃあrecursive_directory_iteratorを使うユーザーのコードは
いちいち多重ループだの再帰だのといった処理になるのかって
思ってさ ツリーは、あるノードの親が知りたいときもあるはず。 ごちゃごちゃ考える前にイテレータの本分を決めなよ
begin()からend()まで++で走らせた時にどうなってほしいの?
話はそれからだ 一般にtreeの探索順序はアルゴリズムと深く結びついてるし、
そこ凝りだすと沼だぞ。 関数ポインタをシリアライズしてファイルとして保存し、
ファイルからその関数ポインタを利用できる形に復元する方法ってあるのでしょうか? 関数だろうが変数だろうがポインタはただの整数値でしょ >>923 環境や「利用」の仕方を具体的に限定すればやりようはあるかもね。 次に(別のプロセスで)ファイルを読み込んだときに、
元の関数を同じ番地で参照できると限らんしな。
関数ポインタの配列のインデクスなら大丈夫だろうだけど。 C++20以降のvector/stringとか
使われる時にconstexprであることを妨げないようにするために付いてるんだと思う デストラクタがデフォルトでvirtualじゃないのは設計不良ではあるまいか あえてベースの方のメソッドを呼びたいなんてことあるのかね? >>931
C++では基本的にゼロコストでできるところはそうできるようにするポリシーだからvirtualが必要なときだけvirtualを明示的に指定させる、というのをどこかで読んだ気がする virtualでなかったら継承禁止にしても良かったんじゃないかとは思う そうするとメタプログラミングに色々と支障が出たはずだし
STLも結構継承使ってるから実現出来なかったかコスト増えてるよ デストラクタをvirtualにする必要があるのは、baseのポインタ経由でdeleteする場合だけ
baseのポインタを使うことすらないようなもの(CRTPなど)までvirtualになるのは
どうなんだろうか unique_ptr使えばvirtualにする必要無いのでは? >>938 んなこたーない。
shared_ptr<Base>{new Derived} なら virtual デストラクタ不要になるから、間違えて覚えてるだけでは? >>937
>デストラクタをvirtualにする必要があるのは、baseのポインタ経由でdeleteする場合だけ
mjk、 セオリーとして覚えてる人多いけど、何故なのかまで考えてない人が多い例の一つだね
要するにdeleteする基底のポインタからデストラクタを呼ぶ際に末端のデストラクタを呼ぶ方法(vtable)が必要というだけ
末端のデストラクタを呼べれば、そこから基底のデストラクタを呼んでいくのは何が基底かわかりきってるから自動で出来る >>941
>基底のポインタからデストラクタを呼ぶ際に末端のデストラクタを呼ぶ方法(vtable)が必要というだけ
mjk、 永遠の初心者です、お願いします
1. 式で if 文を表現したいときは条件演算子(三項演算子 ?: )が使えますが、同じく式でループ構造を表す方法は C++11 以後にありますでしょうか?
2. 1 の質問の理由としては、C++ は Java とちがって uper() がなく、派生クラスのコンストラクタの基底クラス初期化部分に式しか書けません、ここにループを書くとすれば「コンストラクタ用メンバ関数(メソッド)」を置いていますがいかにも無様だと思っています…
3. ある既存のクラスに皮をかぶせて機能アップを図るとき、もとのクラスの派生クラスとして機能アップ部分を既述することは、よくある定石でしょうか、それともあまりしないことでしょうか?
---
以上3点の質問は以下のプログラムを書いていて感じました
お題は「エラトステネスのふるい」、ただし、当初、まっとうにふるいを書いた後、機能アップ項目として
篩部分に格納する数は 2n + 1 奇数に限定する、あるいは 6n + 1, 6n + 5 の形のみに限定する
等を元の篩に対して派生クラスとして記述しました
https://ideone.com/YPlfsC >>943
ラムダ式の出番かな?
void test(bool flag) { flag ? []{ for(int i = 0; i < 10; ++i) cout << i; } : throw 1; } エラストテネス
6n+1, 6n+5だけ保持とかってみんな考えるよね
ちなみに
巨大なテーブル作成時のパフォーマンスを上げるなら
キャッシュが効くよう分割処理するのが非常に効果的
スレッド分割の為にいずれにしろ分割処理は作る事になる >>943
初期化部分に複雑な処理をベタ書きする方が無様だと思うよ。
初期化リストの中にそんなごちゃごちゃしたこと書きたい?
ワイが思うだけなので世間でどう思われてるかは知らんけどとりあえずひとつの意見として。 >>939
親クラス(Base)のデストラクタに virtual 付けなくても...
{
shared_ptr<Base> obj( new Derived() );
} // ~Derived() called, then ~Base() called.
~Derived() はコールされるんですね... 確認してみて驚きました。
これができる仕組みを誰か教えてください。
スマートポインタのオブジェクトは子クラスの事何も知らないのに
どうして ~Derived() のコールが可能なのでしょうか? >>950
まだ仕組みのとこまでですが理解できました。ありがとうございます。 質問ですが構造体Fooの内側に構造体Barが定義されているという入れ子になった構造体において、
Fooの外のコードでFoo::Barのサイズをsizeof()で知りたいとき、以下は正しい?
1. C++だとsizeof(Foo::Bar)と書いたらおk
2. CまたはC++でもC互換構文の範疇で済ます場合、次のどちらかの方法でしか書けない
(1) Foo::Barのインスタンスyが存在するスコープ内で、sizeof(y)と書く
(2) Fooのインスタンスxが存在するスコープ内において、Foo::Bar型のメンバyをFooが持つ
(Foo::yが定義されている)という条件の下で、sizeof(x.y)と書く ふとオモタがインスタンスの必要性は無くせるかもしれん
Foo::Bar型のメンバFoo::yが定義さえされておれば、Fooのインスタンスが無くても
sizeof(((Foo*)0)->y)
と書けばC言語で逝けるかもしれん…
スゲー気持ち悪いコードだが、、、、 >>951
あくまでコンパイル時の型で決まるだけだから要注意
例えば
class A;
class B : public A;
A* p = new B();
std::shared_ptr<A> a(p);
これだとBのデストラクタは呼ばれない なんでそんな中途半端な機能を
わざわざコストをかけて入れたんだろう レス数が950を超えています。1000を超えると書き込みができなくなります。