問題タブ [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(不思議なことに繰り返されるテンプレートパターン)を使用すると、基本クラスにそれから派生したクラスの知識を提供できます。基本クラスから派生した各クラスのインスタンスを格納する配列を作成することはそれほど難しくありません(例を参照)。
すべてのタイプの派生クラスのタイプリスト( http://www.research.ibm.com/designpatterns/pubs/ph-jun00.pdfを参照)を作成できるかどうか疑問に思いました。問題は、コンパイラがそれから派生する新しいクラスをBase
検出するたびに、リストに新しい型を追加する必要があることですが、タイプリストは不変です(新しい型が追加された新しいリストを作成することは可能ですが、追加する私の知る限り、リストの要素は不可能です。最後に、次のようなものが必要です。
最終的な目標は、から派生するすべてのクラスを反復処理できるようにすることBase
です。
c++ - C++ : CRTP デストラクタ?
プロジェクトでは、次の問題があります。
私は非常に単純な継承スキームを持っています(構成ではなく継承が必要です):
クラスベース
-> クラス DerivedA
-> クラス DerivedB
-> クラス DerivedC
A、B、C は Base から派生し、それだけです。だから今私は2つの選択肢があります:
仮想性を伴う公開継承
仮想性のない私的継承
いくつかの最適化の理由から (大量のインライン化が必要です)、仮想性は必要ありません...そしてプライベート継承も必要ありません。残っている唯一のオプションはCRTPだと思います。しかし、基本クラスには約 300 の関数があり、そこに CRTP を実装するのは本当に面倒です。
したがって、次の解決策が有効かどうか疑問に思います: 基本クラスのデストラクタでのみ CRTP を使用します。
ここで、TCRTP は DerivedA、B、または C になり、公開継承を行います。それは完全に大丈夫ですか、それとも問題がありますか?
どうもありがとうございました。
c# - C# で興味深い反復テンプレート パターン (CRTP) を作成する方法
しばらく前に、平均的な ORM よりもはるかに単純な独自のデータ マッパーを作成したいと考えていました。そうすることで、基本クラスの継承クラスの型情報にアクセスする必要があることがわかりました。私が最初に考えたのはリフレクションでしたが、遅すぎます (ただし、リフレクションを使用する場合は、リフレクションのパフォーマンスの問題を「ほぼ」解消するFasterflectを確認してください)。
そこで、後に独自の名前があることを知ったソリューションに目を向けました: The Curiously Recurring Template Pattern です。これで問題はほとんど解決しましたが、このパターンを正しく実装する方法を学ぶのは少し大変でした。私が解決しなければならなかった2つの主な質問は次のとおりです。
1) オブジェクトが作成されたジェネリック パラメータを知らなくても、コンシューマー コードをジェネリック オブジェクトで動作させるにはどうすればよいですか?
2) C# で静的フィールドを継承するにはどうすればよいですか?
挑戦的な部分は、実際に質問を理解することでした. 自分が何をする必要があるかがわかれば、これらの質問を解決するのは非常に簡単です。CRTP が必要な場合は、これらの質問に答える必要があることに気付くでしょう... これらは密接に関連しているようです。
c++ - C++ SFINAE と CRTP、G++ コンパイル エラー
次のコードが有効かどうかを知りたいです。
元の意図は、特定のメンバーへの呼び出しを、派生クラスのメンバーが存在する場合は派生クラスのメンバーにディスパッチするか、派生クラスにこのメンバーがない場合はデフォルトの動作にフォールバックする基本クラスが好きだということです。もう 1 つの用途は、この基本クラスを単独で使用でき、Derived
テンプレート パラメーターが実装ポリシーになることです。いずれにせよ、次の MWE はclang++
、Intel、icpc
および MSVS で正しくコンパイルおよび実行されます。ただしg++
、質問の最後にエラーメッセージが表示されて失敗します(4.4から4.6まで、私が手にしたバージョン)。
call
ポイント(1)、(2)、(3)をcall_dispatch
(これは私が最初に行ったようなものでした)に変更すると、g++
もう文句はありません。ディスパッチ関数と呼び出し元を同じ名前にするのは良い習慣ではないと思います。私はそれがうまくいくかどうか興味があり、不思議なことにそれを試してみるのに十分でした(このアイデアがどのように思いついたのかわかりません)。これの背後にある私の理論的根拠は、pint (1) でcall
1 つのパラメーターで呼び出されるため、オーバーロードの解決が呼び出し元のゼロ パラメーター 1 と一致しないということです。メンバーを持たないSFINAE
ため、ポイント (2)のものとも一致せず、ポイント (3) のものと一致する必要があります。D2
(1)~(3)に名前を付けたときと同じようにcall_dispatch
。
しかしg++
、私や他のコンパイラには同意しません。それで、それは間違った実装ですか、g++
それともコード自体が無効ですか? エラーメッセージに加えて、本当に混乱しています。とはどこvoid (B<D2>::*)()
から&B<D2>::call
来たのですか?彼が呼び出したメンバ ポインタは、D2
のメンバとして定義されていました。
エラー:
編集
上記のコードで何がうまくいかないのか、まだ完全には理解していません。しかし、SFINAE クラスを具体的に構築せずに、同じ効果をアーカイブする別の方法があると思います。
基本的にD1
とD2
はどちらも から派生してB
いるため、式&Derived::call
は常に解決されます。にD1
解決されると&D1::call
、テンプレート バージョン メンバーが使用されます。ではD2
、独自の を持たないcall
ため、&D2::call
に解決されます。また、 @DavidRodríguez-dribeas の&B::call
おかげで、タイプが に
なったことを指摘したため、テンプレートと非テンプレート メンバーは等しく一致しますが、非テンプレートが優先されます。したがって、デフォルトの呼び出しが使用されます。&D2::call
B::call
この新しいコードに欠陥があるかどうかを確認するのに役立ちますか?
c++ - テンプレート クラスの CRTP サブクラスの数を数える方法は?
CRTP を使用してオブジェクトのサブクラスの数をカウントする方法を知っている人はいますか?
次のような設定があるとします。
など、TMP を使用すると、ObjectSubClassCount
サブクラスの総数を表す定数 ( ) を取得できますか?
これを行う方法を知っている人はいますか?
編集:結果を後でテンプレートパラメータとして使用したいので、TMPで行う必要があります...
c++ - ユーザーが誤ったCRTPベースから派生するのを防ぎます
問題を説明するための適切な質問のタイトルを考えることはできません。うまくいけば、以下の詳細が私の問題を明確に説明しています。
次のコードを検討してください
D2
の定義は意図的に間違っていますが、コンパイルして実行します。最初の呼び出しは、初期化されなかっd2.call_impl()
たと予想されるいくつかのランダムビットを出力します。D2::data_
2番目と3番目の呼び出しはすべて、に対して出力100
されますdata_
。
なぜコンパイルされて実行されるのか理解しています。間違っている場合は修正してください。
呼び出しを行うとd2.call()
、呼び出しはに解決されBase<D1>::call
、にキャストさthis
れD1
て呼び出されますD1::call_impl
。D1
は確かに派生形式であるためBase<D1>
、コンパイル時のキャストは問題ありません。
実行時、キャスト後、、this
は、実際にはD2
オブジェクトであるかのように扱われD1
、への呼び出しは、D1::call_impl
あるはずのメモリビットを変更してD1::data_
出力します。この場合、これらのビットはたまたまどこにありますかD2::data_
。d2.call_impl()
2つ目も、C++の実装によっては未定義の動作になると思います。
重要なのは、このコードは意図的に間違っていますが、ユーザーにエラーの兆候を与えないということです。私のプロジェクトで実際に行っているのは、ディスパッチエンジンのように機能するCRTP基本クラスがあることです。call
ライブラリ内の別のクラスは、たとえば、CRTP基本クラスのインターフェイスにアクセスし、基本クラスのデフォルト実装または派生クラスの実装call
にディスパッチします。call_dispatch
ユーザー定義の派生クラス、たとえばD
、が実際にから派生している場合、これらはすべて正常に機能しBase<D>
ます。から派生していないBase<Unrelated>
場所から派生している場合は、コンパイル時エラーが発生します。ただし、ユーザーが上記のようなコードを作成することを妨げることはありません。Unrelated
Base<Unrelated>
ユーザーは、基本CRTPクラスから派生し、いくつかの実装の詳細を提供することにより、ライブラリーを使用します。上記のような誤った使用の問題を回避できる他の設計の選択肢が確かにあります(たとえば、抽象基本クラス)。しかし、とりあえずそれらを脇に置いて、何らかの理由でこのデザインが必要だと私に信じさせましょう。
だから私の質問は、上記のようにユーザーが間違った派生クラスを書くのを防ぐことができる方法はありますか?つまり、ユーザーが派生実装クラス、たとえばを作成D
したが、それをから派生したBase<OtherD>
場合、コンパイル時エラーが発生します。
1つの解決策は使用dynamic_cast
です。ただし、これは広範囲にわたるものであり、機能する場合でも実行時エラーになります。
c++ - Boost.Parameter:CRTPと組み合わせた名前付きテンプレート引数
警告:問題を説明するために、先に長い紹介が必要です。VandevoordeとJosuttisの16.1章で最初に説明された名前付きテンプレート引数イディオムは、Boost.Parameterライブラリを使用して簡単に記述できます。
上記のコードを使用すると、のオプションのテンプレートパラメータに名前を付けて任意の順序でオーバーライドできBreadSlicer
ます。これにより、多くのデフォルトパラメータを使用したポリシーベースの設計が非常に便利になります。Policy1_is
Policy2_is
ポリシーベースの設計での非常に微妙なODR違反を回避するために(説明については、Alexandrescuによるこの古い投稿を参照してください)、名前付きテンプレート引数にCRTPパターンを適用できるようにしたいと思います。
ただし、一部の内部static_assertが(VC10 SP1)のようなメッセージで失敗するため、上記のBoost.Parameter実装はコンパイルに失敗します。
'main :: CuriousBreadSlicer':コンパイラの組み込み型特性'__is_base_of'への引数として未定義のクラスは許可されていません
質問:この静的チェックをオフにすることはできますか?マクロまたはテンプレートのトリックのいずれかを介して?
考えられる回避策について:
- 上記のコードは、この手書きコードと機能的に同等です。そのコードでは、CRTPパターンが機能します。ただし、Boost.Parameterライブラリが便利に自動化する多くの定型コードが必要です。
- CRTPパラメーターを常にテンプレート引数のリストの最初に配置し、
Policy1_is
クラスでラップしないようにすることができます。これにより、コンパイル時のエラーは解決されますが、オーバーライドの順序に依存しなくなります。
ですから、私はゴルフ選手が「クラブの間」と呼んでいるもののようです。どのソリューションが最適ですか?
c++ - テンプレート リーフ クラスを使用した奇妙な繰り返しテンプレート
私は自分のアプリケーションに不思議なことに繰り返されるテンプレート パターンを使用することを考えています。ただし、クラスがユーザー定義型で動作するようにしたいと思います。以下に示すような構造を作成できるかどうかを理解したいと思います。
上記のコードは、次のエラーでコンパイルに失敗します。
「テンプレート クラス BaseTrajectoryPoint」のテンプレート パラメーター リストの引数 1 で型/値が一致しません</p>
問題にアプローチする別の方法はありますか? 静的ポリモーフィズムを使用したいのですが、基本クラスで可能なすべてのメソッドを定義したいと考えています。
c++ - C++ でのミックスインによる興味深い循環継承
ここで循環継承を解読する良い方法は何ですか?
継承しようとするとTrafficLight
不完全な型であるため、失敗します(gcc 4.7.0) 。HasImportance
本当の問題は、HasImportance が によって返される型を知る必要があること
neighbors()
です。HasImportance
から継承する
場合、 ではなくのリストを返す
Node
と考え、その結果、アイテムを呼び出すことができるかどうかを知りません。まったく継承しない場合も同様の問題があります。neighbors()
Node*
TrafficLight*
receive_importance()
HasImportance
ところで、私がやろうとしているのは、さまざまな種類のグラフを簡単に定義し、各ミックスインを個別に単体テストするのに役立ついくつかのミックスインを作成することです。たとえば、次のように書くだけで、信号機のグラフのノード クラスを定義できるはずですclass TrafficLight : public HasImportance, HasState<3>,
virtual Node { }
。
これを解決する 3 つの方法を考え出しましたが、どれも醜いようです。(1)
static_cast<NodeType*>
. (2)そのコンストラクターでにをTrafficLight
渡し
ます。この方法で
は、継承する必要はまったくありません。(ahem)自体へのポインターを格納するだけで、テンプレートパラメーターはポインターの型を提供します。(3)次のようにクラス テンプレートを作成します。this
HasImportance
HasImportance
Node
それはコンパイルされ、 の不当なコピーは導入されませんがthis
、少し奇妙すぎるようです。
ここにコードの匂いはありますか?これらのグラフにまったく異なる方法でアプローチする必要がありますか?
c++ - テンプレート パラメータを CRTP に渡すにはどうすればよいですか?
次のコードでは:
CRPTInt を記述して、テンプレート化されたパラメーターを渡すことができるようにするにはどうすればよいですか?
ありがとう、
ジム