0

これは、言語に関する質問というよりも、ベスト プラクティスに関する質問です。なぜなら、C++ でよくあるつまずきのブロックと思われるものに対する有効な解決策が既にあるからです。

テンプレート パラメーターの置換における典型的な循環依存の問題を扱っています。次のクラスのペアがあります。

template<class X>
class A { /* ... */ };

template<class X>
class B { /* ... */ };

そして、それぞれを次のようにインスタンス化したいと思います:

// Pseudocode -- not valid C++.
A<B> a;
B<A> b;

つまり、A を B に、B を A に「バインド」したいということです。

継承トリックを使用した前方宣言を通じて、問題を大まかに解決できます。

class sA;
class sB;

class sA : public A<sB> { /* ... */ };
class sB : public B<sA> { /* ... */ };

しかし、 とは実際には と ではないのでsA、これは一連の問題を引き起こします。たとえば、のコンストラクターを に適切に複製したり、何らかの形でコードの周りにきらめくキャストをしたりせずに、 のコンストラクターを呼び出すことはできません。sBABAsA

私の質問は、この問題に対処するための最も実用的な方法は何ですか? この問題に対する特別に賢い解決策はありますか?

MSVC2008 と G++ の両方を使用していますが、コンパイラ固有の拡張機能を使用したソリューションは大歓迎です。

ありがとう、

アレク

4

2 に答える 2

2

前述のように、これに対処するための最も実用的な方法は、リファクタリングすることです。つまり、デカップリングによって依存関係を解消します。

可能なオプションは次のとおりです。

  • 仮想メソッドを使用したインターフェース
  • 静的インターフェース(おそらく型特性または概念チェックを使用)
  • 片側または両側でコールバックを使用する(ファンクターまたはシグナルを介して緩和される可能性があります)

これは、要件が突然変更された場合にも役立ちます。場合によっては特別なものが必要だとserverします。もちろん、すでに作成したすべてのクライアントをサポートする必要があります。それらを書き直したくはありません。または、場合によっては特別なものが必要になりますclient...
あなたのアプローチでは、両側を書き直す必要がありますが、分離されたアプローチでは、変更する必要のある側の修正バージョンを書くだけです。

たとえば、クライアントとの静的なアプローチを取る:

template<class server>
class client {
    server& srv;
public:
    client(server& srv) : srv(srv) {};
    void work(const request& req) {
        srv.add_job(make_job(req));
    }
};

ここでclientは、具体的なタイプを知る必要はありserverません。メンバー関数add_job(job&)や互換性のあるものがない場合、コンパイルは単に失敗します。
より正式なものにしたい場合は、静的アサーションとコンセプトチェックを調べることができます。

于 2010-01-26T23:52:46.420 に答える
0

テンプレートのタイプはそのすべてのパラメーターに名前を付けるため、パラメーター化の無限のループを持つことはできません。

あなたはおそらく(確かに)同時に反対方向に情報を送信しようとしているだけです。問題はありませんが、実装を提供するクラスに情報をカプセル化することはできません。

template< class W > // define an abstract class to pass data
struct widget_traits {};

template<>
struct widget_traits< SpringySpring > { // specialize to put data in it
    struct properties { … };
    enum { boing = 3 };
};

template< class V >
struct veeblfetzer_traits {};

template<>
struct veeblfetzer_traits< VonNeumann > {
    typedef int potrzebie;
};

template< struct WT, struct VT > // pass info by using as argument
struct MyWidget { … };

template< struct VT, struct WT > // both ways
struct MyVeeblfetzer { … };
于 2010-01-26T23:48:07.227 に答える