問題タブ [crtp]
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++ - C++ CRTP クラス階層
ウィキペディアから:
必要に応じてderived_from_derived
、次のように記述できます。
ここで、derived
オブジェクトが必要だとします。これは機能しません:
derived
抽象化する必要がありますか、それともインスタンス化する方法はありますか?
c++ - C++ CRTP およびベースからの派生のネストされた typedef へのアクセス
編集:興味のある人のためにデザインの変更が完了したら、ここに github リンクを配置します。
バックグラウンド
boost::intrusive
, , を独自の実装に置き換えます。これはintrusive_set
、64 ビットでコンパイルされた侵入セットがコンテナー ノードに 3 x 8 バイトのポインターを詰め込むためです。私のコンテナーには 2^16 ノードの制限があるため、2x 16 ビットのオフセット序数 (サイズの 6 倍の縮小) を使用して、ノードあたり 4 バイトまで下げることができます。
以下の例base
は、侵入セット コンテナーです。derived
クラスにはstd::vector<container_entry_type<entry_type> >
. 明らかに、このレベルの間接化では、ネストされた typedef を派生に含める必要があります。これをベースで参照したいと思います。
ps、コンテナーはデータ記述言語の AST 用です。したがって、含まれる要素は小さなデータ型であり、3 x 8 バイトは非常に重要です。コンテナーはタイトなループでデータセットを検証するために使用されるため、特にそうです。
分離された問題
次のセマンティクスを実現したい:
しかし、ネストされた typedef にベースからアクセスできません。この問題について、clang は次のように述べています。
代わりに、私はしなければなりません:
これが私のユースケースを達成する唯一の方法ですか? 物事がずっと冗長になるだけです。派生は、いくつかのキーストロークを節約するために特性から派生することもできると思います。
もう 1 つの選択肢は、派生を使用せず、現在派生されているものにロジックを直接接続することです。ただし、個別にテストベースを単体テストしたいと思います。
c# - 奇妙に繰り返されるテンプレート パターンを使用する場合の戻り値の型
私の C# プロジェクトで奇妙な繰り返しテンプレート パターン(CRTP) を使用していますが、いくつか問題があります。上記のリンクから抜粋したコード:
美しい!次のようなことをしようとすると、問題が発生します。
SomeClass は Base クラスの任意の実装を返すことができるはずですが、もちろん T は別のクラスにあるため、ここでは意味がありません。T コンパイルの代わりに Derived を配置しますが、Base から派生している限り、他のタイプのアイテムも返すことができるはずなので、これは私が望むものではありません。また、GetItem() は SomeClass オブジェクトの状態に応じて異なる型のオブジェクトを返す可能性があるため、SomeClass をジェネリックにすることも解決策ではありません。
ここで明らかな何かが欠けていますか、それとも CRTP の使用中にこれを行うことはできませんか?
c++ - CRTP テンプレート クラスのタイプを保存または転送する方法
一般的なアイデア:クラスのペア、ワーカーを作成するマネージャー。それぞれが、動作をカスタマイズする一連のポリシーを受け入れます。各ポリシーには、マネージャーに影響を与える部分 (いくつかのセットアップを行う) とワーカーに影響を与える部分 (ホスト ワーカー クラスの関数から呼び出す必要がある特定の作業関数を追加する - 現在は CRTP を介して行われます) があります。
ワーカーで使用されるポリシーは、常にマネージャーのポリシーを反映します。つまりmanager<foo,bar>
、タイプのワーカーを作成しますworker<foo_worker,bar_worker>
。このため、ワーカー ポリシーのタイプをマネージャー ポリシーに格納して、エンド ユーザーが両方を指定する必要がないようにしたいと考えています。
次のコードは、問題を示すコードの簡略化されたバージョンを実装しています。マネージャークラスのコメントを見てください。現在(例をコンパイルするために)、マネージャーはハードコーディングされたタイプのワーカーを作成しています。
質問:マネージャが独自のテンプレート パラメータに基づいて正しいワーカー クラスを決定/検索できるように、テンプレート クラス foo_worker のタイプをクラス foo 内に記録するにはどうすればよいですか?
typedef foo_worker work_policy;
class foo
foo_worker はクラス テンプレートではないため、inside ofは機能しません。さまざまな種類のラッパー クラスと、typename と template の組み合わせを試してみましたが、うまくいきませんでした。また、foo 内のネストされたクラスとして foo_worker を使用しようとしました。
回避できるのであれば、C++11 を必要としないことを望みますが、この問題が根本的に単純化されるのであれば、喜んで検討します。
この問題を回避するこのようなシステムを構築する別の方法はありますか?
よろしくお願いします=)
c++ - メンバー関数へのポインターのデフォルト値に関するCRTP関連のコンパイラー・エラー
やあ、
CRTPベースの汎用ラッパーを作成して任意のライブラリ関数を呼び出すときに、理解しにくい問題が発生しました。問題を説明するための非常に単純化されたコードを次に示します。
すべてが意図したとおりにコンパイルおよび動作します。ただし、 :TDerived::Foo()
の2番目のパラメーターのデフォルト引数としてポインターを使用しようとすると、TBase::Call(...)
コンパイラーは構文エラーを出します...コンパイラーがコードを解析する方法に関連していて、まだ定義されていない(またはインスタンス化されていない)クラスの関数へのポインターを理解できないと感じています。ただし、TDerived
の3番目のパラメーターのデフォルト引数としてコンストラクターを呼び出すことは問題ありませんTBase::Call(...)
。誰かが私に何が起こっているのかについて明確な答えを与えることができますか?派生クラスMFPが受け入れられず、派生クラスのオブジェクトがデフォルトの引数として受け入れられるのはなぜですか?
ありがとう。
編集:コンパイラのエラー(MSVS2010コマンドラインコンパイラ):
TDerived_
これは構文エラーです。MFPのデフォルト引数のタイプとして認識されません。これに続いて他のエラーがあります。関数定義の形式が正しくないため、これらはすべて構文エラーです。それが私がそれを理解する方法です。
編集:基本的に、オブジェクトをデフォルトの引数として使用できる理由はわかりませんがTDerived_
、メンバー関数へのポインターをデフォルトの引数として使用することはできません。
編集:わかりました、これは今私を夢中にさせています。まず、typedef TBase< PValue, TDerived > TBase_;
指摘された通りに変更しました(ありがとうございます!)。実際、このコンパイラは2つの部分からなる解析を行わないため、MSVC++でのみコンパイルされます。つまり、codepad.org(g ++ 4.1.2を使用)ではコンパイルされませんでした。static void Call( PType /*pSomething*/, void(TDerived_::*pFunction)( void ) = &TDerived_::Foo, TDerived_ pDerived = TDerived_() )
次に、 codepad.orgで使用してみましたが、コンパイルされて正しく実行されました。だから私は今本当に混乱しています:人々はそれが正しくない理由を私に説明しました(そして私は「なぜ」を理解できませんでした(私の前の編集を参照してください))そして今それはg++がそれを正しくコンパイルすることがわかります...それはちょうどそれを意味しますかコードではなくMSVC++の問題?または、コードには標準の観点から問題があり(そして私はそれを見ることができません)、g ++はそれを「誤って」受け入れます(おそらく、私は思いません)?..ヘルプ?!
c++ - crtp とタイプの可視性
私は解決しようとしているこのパズルを持っています。基本的には、次の例に要約されます。
上記の説明を試みることはできますが (約 3 回試行してテキストを削除しました!)、基本的に要件は次のとおりです。
C
B
typed withC
(CRTP の利用)から継承する必要があります。つまり、B<C<>>
C
インスタンス化できる唯一のものですA
(つまりA
、で入力する必要がありますC
)A
は定義できる唯一のものですFOO
(FOO
はタイプに依存しCT
、関係は提示されたものよりも複雑です)
問題 (上記のコードでわかるように) は、BAR
型が 内でのみ使用可能であり、インスタンス化さC
れたときにこれが不完全であるため、テンプレート引数( )の型が表示されないことです。残念ながら 内では、型は関数への引数として使用され、型を返します (つまり、関数スコープに限定されないため、typedef を関数スコープに単純に移動することはできません)。B
B
BAR
CT
C<int>
B
BAR
これを回避する方法はありますか?上記の関係を壊すことはできません (最後の手段でない限り)。おそらくc ++ 11を使用すると、 typedefを使用auto
する必要性を回避できますが、これは現在のところまだオプションではありません。BAR
B
編集: @bitmasks のコメントに続き、さらに情報が追加されました。
- とのコードは
A
、B
さまざまな状況でかなりの数のバイナリで使用されています。この場合の唯一のユニークな状況は、C
から派生したものB
であり、他のインスタンスでは、 から派生したもののインスタンスをC
所有していますB
。 - テンプレート引数は、 および の既存の使用を変更する必要のない値にデフォルト設定できる限り、(およびで)
A
変更できます。同じタイプのセットが、デフォルトのテンプレート パラメーターとして、またはその他のメカニズムとして使用できる必要があります。B
A
B
ここでテンプレートを使用しているのは、密結合が必要であり、さまざまな状況でコードを使用できる柔軟性が必要だったからです。
コンポーネントの説明:
A
コンテナーとして説明するのが最も適切であり、FOO
実際には反復子です。含まれるものは、テンプレート パラメーターの typedef によって定義されます。B
のインスタンスが所有するいくつかのコンポーネントによって呼び出される一連の関数を含む基本クラスとして説明するのが最も適切ですC
。前のケースでは、これらのコンポーネントには から派生したものへの参照が渡されましたB
(そして、それらのものは によって所有されC
ています)。この例では、C
それ自体への参照を提供しています。
主な複雑さは、コンテナへのアクセスから発生します。以前はとA
の間の関係は のインスタンスを持っていましたが、現在は のインスタンスです- このセマンティクスの変更により、型がクラスに注入される方法が壊れます。B
C
C
B
C
B
c++ - CRTP(C ++)のさまざまなエラー
これについて質問したばかりですが、何が間違っているのか理解できません。小さな部分だけを書き直しましたが、エラーが見つかりません(親の戻り子でC ++関数を参照として使用)
私のコード:
結果:
私は答えに非常に感謝します(私の無能は睡眠不足が原因かもしれませんが:D)
c++ - コンパイラは「typeid」演算子をどのように評価しますか?
この質問を解決するために使用したCRTP ベースのテンプレート コードを次に示します。ここにコードを投稿しますが、行は長く、codepad.org の方が読みやすいです (必要に応じてここに投稿します)。もちろん、それは機能しますが、醜く、やや人工的です。しかし、MSVC++ と GCC の両方でコンパイルされますが、一部のテンプレート タイプは実際には定義されていないことに最初は気づきませんでした。私が質問している部分は、関数の上部にあるいくつかの長い内部if( typeid( Derived(N) ) != typeid( Derived(N-1))
(記号表記)です。TBase::OnEvent
これらの型を使用することはできません。コンパイル エラーが発生します。typdef
このような長いチェーンで型を定義するための派生クラスが十分にない...::TDerived::...
ため、正しくコンパイル エラーが発生しますTDerived is not defined in TBase
。それでも、コンパイラはそれらを食べ尽くしますtypeid
。...::TDerived::...
デバッガーの MSVC++ コンパイラー出力 (完全なシンボリック情報付き) をチェックインすると、実際にはどのクラスにもならないすべての longがtypeid
、コンパイラーによって単にTDerived04
クラス チェーンの最後に解決されたようです。そして、RTTI は、...::TDerived::...
私が持っている数に関係なく、クラス チェーンの最後のクラスに対してプルされます。
MSVC++ と GCC の両方がそれを行うことを考慮して (私は codepad.org から GCC にしかアクセスできませんが)、私の質問は次のとおりtypeid
です。では、なぜtypedef
これらの long のいずれかが に...::TDerived::...
解決されないのTDerived04
でしょうか?
編集:つまり、 が に解決typedef
されないことをうれしく思います。TDerived04
typedef
typeid
typedef
編集: GCC はTDerived04::TDerived04::TDerived04::TDerived04 lD4;
変数宣言を受け入れます。そして、タイプは単にTDerived04
最後にあります。スコープの解決を折りたたむためのルールはありますか? どうやら、MSVC++ と GCC の両方が で同じことを行っているようですが、typeid
GCC とは異なり、MSVC++ は他のシナリオを処理できません。コンパイル エラーが発生し、コンストラクターの引数が必要になります。