問題タブ [standard-layout]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - is_standard_layout はどのように役立ちますか?
私が理解していることから、標準レイアウトでは次の 3 つのことが可能です。
- 空の基本クラスの最適化
- 特定のポインタ キャストによる C との下位互換性
- オフセットの使用
現在、ライブラリに含まれているのはis_standard_layout
述語メタ関数ですが、上記にリストした C 機能が汎用コードでチェックする必要があることは非常にまれであるため、汎用コードでの使用はあまり見られません。私が考えることができる唯一のことは、内部static_assert
で使用することですが、それはコードをより堅牢にするためだけであり、必須ではありません。
どのようにis_standard_layout
便利ですか?それなしでは不可能であり、標準ライブラリでそれを必要とするものはありますか?
c++ - 共通の初期配列とアラインメント
この質問の反例を考えているうちに、私は思いつきました:
しかし、それが合法で標準的なレイアウトである場合、これとレイアウト互換struct B
ですか?
さらに、
と の共通の初期シーケンスはA
ありB
ますか? もしそうなら、それはA::y
&を含みB::y
ますか? つまり、UB を呼び出さずに次のように記述してもよろしいでしょうか?
(C++1y / "fixed C++11" の回答も歓迎)
配置については [basic.align] を、配置指定子については [dcl.align] を参照してください。
[basic.types]/11 は、基本型について「2 つの型
T1
とT2
が同じ型である場合、T1
とT2
はレイアウト互換型です」と述べています。(根本的な問題はA::byte
、 とB::byte
がレイアウト互換の型を持っているかどうかです)[class.mem]/16 「2 つの標準レイアウト構造体型は、同じ数の非静的データ メンバーを持ち、対応する非静的データ メンバー (宣言順) がレイアウト互換型を持っている場合、レイアウト互換性があります。」
[class.mem]/18 "2 つの標準レイアウト構造体は、対応するメンバーがレイアウト互換の型を持ち、どちらのメンバーもビットフィールドではないか、どちらも 1 つのシーケンスに対して同じ幅のビットフィールドである場合、共通の初期シーケンスを共有します以上の初期メンバー。」
[class.mem]/18 「標準レイアウト共用体に共通の初期シーケンスを共有する 2 つ以上の標準レイアウト構造体が含まれている場合、および標準レイアウト共用体オブジェクトに現在これらの標準レイアウト構造体の 1 つが含まれている場合、それは許可されます。それらの共通の最初の部分を検査します。」
もちろん、言語弁護士レベルでは、別の質問は、共通の初期シーケンスの検査が「許可されている」とはどういう意味かということです。u.b.x
他の段落が上記の未定義の動作(初期化されていないオブジェクトからの読み取り)を行う可能性があると思います。
c++ - レイアウト互換の標準レイアウト タイプ間で合法的に reinterpret_cast できますか?
列挙型のレイアウトは、基になる型と互換性がありますか? 「はい」、レイアウト互換性がありますが、 、 などにes をstruct kevent
使用し、関連するフィールドの適切な基本型を使用します。また、標準レイアウトです (フィールドはすべて標準レイアウトであり、メンバーも基本クラスもありません)。を読んだことから、自分のクラスが同じ値表現を持っていると判断できますが、標準には何も表示されないため、enum class
filter
flags
private
virtual
n3690
struct kevent
reinterpret_cast
それは「値の表現」の合理的な解釈のように思えますが。これは標準で技術的に許可されていますか? そうでない場合、型の値表現を知ることで何が得られるでしょうか?
EDIT 2014/02/24 16:45 ESTreinterpret_cast
:コメントに応じて、最初のクラスを2番目のクラスへの参照にしたいことを明確にする必要があります。もちろんreinterpret_cast
、非ポインター型を別の非・ポインタ型。
c++ - C++ - 標準レイアウト
現在の C++ 標準ドラフトによると、標準レイアウト クラス
最も派生したクラスに非静的データ メンバーがなく、非静的データ メンバーを持つ基本クラスが最大 1 つあるか、または非静的データ メンバーを持つ基本クラスがない
この制限でより効率的な実装はまだ見たことがありません。なぜそれが存在するのですか(物事をより困難にすることを除いて)?
c++ - アクセス制御が異なるメンバーを持つ共用体が標準レイアウトではないのはなぜですか?
§9.0
7. 次の場合、クラス S は標準レイアウト クラスです。
(7.3) すべての非静的データメンバーに対して同じアクセス制御 (第 11 節) を持ち、
8 標準レイアウト構造体は、class-key struct または class-key class で定義された標準レイアウト クラスです。標準レイアウト共用体は、クラスキー共用体で定義された標準レイアウト クラスです。
AFAICT、§9.2.13のために§9.0.7.3が存在します
13 同じアクセス制御 (第 11 節) を持つ (非共用体) クラスの非静的データ メンバーは、後のメンバーがクラス オブジェクト内でより高いアドレスを持つように割り当てられます。アクセス制御が異なる非静的データメンバーの割り当て順序は規定されていません(第 11 節)。実装のアライメント要件により、隣接する 2 つのメンバーが互いの直後に割り当てられない場合があります。仮想関数 ( 10.3 ) および仮想基本クラス ( 10.1 ) を管理するためのスペースの要件も同様です。
ただし、ユニオンのすべての (非静的データ) メンバーは同じアドレスを持っているため、これはユニオンには当てはまらないようです。これは規格の欠陥ですか?それとも、私が見ていないのには説得力のある理由がありますか?
c++ - メンバーのメモリ オフセットを確認するために、クラスは標準レイアウト タイプである必要がありますか?
押し付けがましいリストを書きたいとしましょう。ノードとして使用するメンバーへの型とポインターを受け取る侵入型のリスト クラス テンプレートがあります。おおよそ次のようになります。
リストに保存したいものごとに IntrusiveListNode があります。その IntrusiveListNode を IntegerListNode のように使用できるものに戻すには、クラス内のオフセットに基づいてノードでポインタ演算を行う関数を呼び出し、それを適切な型にキャストします。これは機能しているように見えますが、保証されていないと思います。
使用している型が安全であることをコンパイル時に検証するクラスに static_assert を追加できるようにしたいのですが、static_assert の条件がどうなるかわかりません。これは、IntrusiveListNode を保持する型が標準レイアウト クラスである場合にのみ機能することが保証されていると思いますが、標準レイアウト型の要件は実際に必要以上に厳しいように見えるため、確信が持てません。
特に、標準レイアウト タイプでは、すべてのメンバーが同じアクセス コントロールを持つ必要があります。私が必要としているのは、ポインター演算が機能することを確認できることだけです。つまり、構造体の 2 つの異なるバージョンが異なるレイアウトになる可能性があるため、ポリモーフィック型でこれを使用できないことを意味しますが、型にプライベート データ メンバーとパブリック データ メンバーが混在している場合、これは問題になりませんよね? 型が非ポリモーフィックであることを要求しただけで安全でしょうか? または、行うべきより良いチェックがありますか?それとも、私はis_standard_layout
チェックをしているのですか?
c++11 - ABI 互換の shared_ptr 実装
私は、ABI 互換性のために互換性のある仮想テーブルの実装に依存する、COM スタイルのコンパイラ相互互換性プラグイン フレームワークに取り組んでいます。純粋な仮想メンバー関数とオーバーライドされた削除演算子のみを含むインターフェイスを定義して、破棄を実装の場所に送ります。これは、インターフェイスのプラグイン実装をインスタンス化し、インターフェイス型ポインターを返す extern "C" ファクトリ関数でうまく機能します。
しかし、スマート ポインターは、プラグイン オブジェクトの有効期間を管理するための最新の方法ではないのではないかと考えていました。プラグイン インターフェイスと同じ方法で定義および実装された参照カウント オブジェクトを使用する、標準レイアウトの shared_ptr/weak_ptr を実際に作成できたと思います。次のようになります。
3 つの質問:
スマート ポインターの前は、ファクトリ関数は次のようになっていました。
これで、次のようになります。
VS2013 で警告 C4190 が表示されます: 'factory' には C リンケージが指定されていますが、C と互換性のない UDT 'shared_ptr' が返されます。MSDN によると、呼び出し元と呼び出し先の両方が C++ であれば問題ありません。
「C」リンケージ関数から標準レイアウト オブジェクトを返すことに関して、他に潜在的な問題はありますか?
呼び出し規約。すべての純粋仮想インターフェイス関数とファクトリ関数に対して __stdcall を指定する必要がありますか?
<atomic>
参照カウントに使用しています。プラットフォームに依存しないコードを書いていますが、ARM 用のコンパイルはまだ試していません。http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dht0008a/ch01s02s01.htmlによると、armccはstd::atomicを実装していません。より良いコンパイラ/ stl はありますか?
c++ - `=` を (削除された) コピー代入よりも変換からの代入を優先させることは可能ですか?
これができないことを強く示唆するスレッドをいくつか見つけましたが、まったく同じ演算子と条件の組み合わせを使用するスレッドはありません。そのため、より具体的にお尋ねしたいと思います。うまくいけば、それが誰かにとって迅速かつ簡単な答えになることを意味します...何らかの形で!
ストレージのより大きなブロック内の値を管理するために作成されたプロキシ クラスの例を考えてみましょう。
すべての割り当てがユーザー定義operator
の s を介して機能するようにします。ユーザーは、この場合、「公開された」タイプのみを渡したり取り出したりできる必要がありますstd::uint16_t
。さまざまなプロキシ クラス タイプを使用している可能性があり、これをそれらすべてに適用したいと考えています。理想的には、どのような型の組み合わせでも、型を入力するだけで、後someProxy = anotherProxy
はコンパイラーに任せることができます。
しかし、代入の左側と右側が同じ型または継承に関連する型を持つ場合、デフォルトのコピー代入演算子 (もちろん) はこの目標と競合します。必要に応じて「公開された」値だけをコピーするのではなく、全体をコピーするstorage
ため、残りの半分を上書きします。uint32_t
そして当然のことです!ほとんどの場合。しかし、LHS と RHS の型が同じであっても、「変換によって割り当てる」方法が欲しいです。これを回避するために、次のことができます。
operator
ユーザー定義の sを使用して「プロキシ」コピーを実行するようにコピー代入演算子を再定義します。の- 私が保持する必要があるもの。とにかくまだsですが、定義された動作が必要です。struct
memcpy()
g++
- または
= delete
コピー代入演算子(TC 型に対して実行できるようになりました)。しかし、割り当てはまだそれを使用しようとし、コンパイル エラーをスローしますdelete
。これは、「オーバーロードの解決から私を除外する」のではなく、「選択されたオーバーロードの場合にエラーで中止する」ことを意味するためです。これを回避するには、変換演算子を使用してその結果から割り当てるようにコンパイラに明示的に指示する必要があります。
コンパイラに「優先オーバーロードによって生成されたエラーを無視し、次善のものを選択する」ように指示する方法はないようです。ある?より一般的には、そのような状況で、コンパイラに特定の sを自動的に使用/優先させるoperator
方法/ハック/恐ろしいクラッジはありますか?
つまり、理想的には、
それb = a;
は本当にこれを行うでしょう:
これを手動で入力したり、 を使用しstatic_cast
たり、名前付きの get/set メソッドを実装したりする必要はありません。理想的には、そのようなプロキシへの読み取り/書き込みは、すべて=
.
私はそれが不可能だと強く思っています...しかし、確認はいいでしょう!
c++ - C++14 標準レイアウト型は、フィールドに「alignas」を使用できますか?
テンプレートを使用して、自明でない型の共用体の構築を簡素化したいと考えています。以下は実際には「機能する」ように見えますが、仕様では技術的には合法ではありません。
問題は、(N4141 によると) 両方の構造が標準レイアウト タイプである場合にのみ、共用体 (つまり、フィールド) 内の 2 つの構造の共通の初期シーケンスにアクセスできることです。destructor_
少なくとも 9.5 の非規範的な注意に従ってください。 .1. 9.0.7 によると、標準レイアウト型は非標準レイアウトの非静的データ メンバーを持つことはできません。したがって、A または B のいずれかが標準レイアウトでない場合destructor_
、間違った共用体でアクセスすることは違法になります。
抜け穴は、に変換してunion_entry
標準レイアウトを作成value_
することのようですalignas(T) char[sizeof(T)]
。9.0.7 では、alignas
. したがって、私の質問: 次はどのタイプの標準レイアウト タイプT
ですか? したがって、前の例をエミュレートするためvalue_
にキャストできますが、アクティブでない ?T&
destructor_
union_entry
clang-3.8.1 と g++-6.2.1 の両方で、そうでない場合でも標準レイアウトをstd::is_standard_layout
提案します。この手法をどのように使用したいかの完全な実用例を次に示します。union_entry<T>
T