2016-06-17 5 views
0

申し訳ありませんが重複している場合、このシナリオでは何も見つかりませんでした。これは名前解決の問題自体ではなく、より多くのテンプレート/構造の問題です。クラスを含むクラスから派生したテンプレート引数が基本クラス

template< typename T > struct X; 

struct Y { 
    X<Y> & xy; 
    Y(X<Y> & _xy) : xy(_xy) {} 
    virtual ~Y(); 
}; 

template< typename T > struct X { 
    static_assert(std::is_base_of<Y, T>::value, "T is not a Y"); 
    T member_t; 
    X() : member_t(*this) {} 
    virtual ~X(); 
} 

struct DY : Y { 
    int test2 = 2; 
    void tester1() { 
     // int t1 = static_cast< X<DY> >(xy).test1; 
     // fails: no known conversion for argument 1 from 'X<Y>' to 'const X<DY>&' 
    } 
}; 

struct DX : X<DY> { 
    int test1 = 1; 
    void tester2() { 
     int t2 = member_t.test2; // perfectly ok, no problems. 
    } 
}; 

完全なエラーリストは、ほとんどが、理にかなってい意地の悪のカスケードである:タイトル毎の

は、次のようになりますような状況があります。私が理解できないのは、 tester1の状況をどのように処理するかです。それは、派生するクラスであり、そのメンバーの1つのテンプレートでそれ自身を使用し、派生クラスはコンパニオンクラスのテンプレート(X- > DX)。彼らは「無関係」クラスです - ここでは X<Y>が直接 X<DY>に変換することはできませんなぜ私は完全に理解し

main.cpp: In instantiation of 'struct X<Y>': 
main.cpp:35:44: required from here 
main.cpp:23:5: error: static assertion failed: T is not a Y 
    static_assert(std::is_base_of<Y, T>::value, "T is not a Y"); 
    ^
main.cpp: In member function 'void DY::tester1()': 
main.cpp:35:44: error: no matching function for call to 'X<DY>::X(X<Y>&)' 
     int t1 = static_cast< X<DY> >(xy).test1; 
              ^
main.cpp:35:44: note: candidates are: 
main.cpp:25:5: note: X<T>::X() [with T = DY] 
    X() 
    ^
main.cpp:25:5: note: candidate expects 0 arguments, 1 provided 
main.cpp:21:31: note: constexpr X<DY>::X(const X<DY>&) 
template< typename T > struct X 
          ^
main.cpp:21:31: note: no known conversion for argument 1 from 'X<Y>' to 'const X<DY>&' 

(申し訳ありません、事前に私の行番号がここにフォーマットさよりも若干異なります)...あなたの楽しみの人々のためにあります。実際には、Yが基本クラスのDYであることがわかっている一般的なケースでこの変換を実行するエレガントな方法はありますか?

現時点では私の推測では、コンパイラのノートの1あたりに、コンストラクタX<DY>::X(X<Y>)(または類似のオペレータ)を実装することですが、何らかの理由でYがコピーできない場合はそれができないかもしれません...だからX<DY>::member_yこのようX<Y>::member_yからコピーする必要がありますか、エレガントに静的にキャストできますか?わからない...


目指す

あり、二つのクラス、XYがあり、それらはXはテンプレート引数としてそのYまたはいくつかの派生物を受け入れるという関係を有しています。これは、たとえば、一部のコンテナX内のYのようなオブジェクトに共通する動作を調整することです。

派生したYとちょうどXを使用することは(私にとにかく)どのように行うのか自明です。課題は、「調整された行動」自体を拡張可能にすることです。上記のことは、派生したYタイプのXタイプを参照する必要がある場合には、明確に機能しない派生型のXDX)を作成する試みです。

+0

YがDYの基底であっても、X とX の間には強制的な関係はありません。上記のように定義しても、理論的にコンパイラは、パディングのためにX :: member_tとX :: member_tを異なるオフセットで格納することができます。 Btw、どうやってDYを構築しますか?あなたのX &受け入れることはありませんX ... – lorro

+0

ええ、それは問題の笑...私は分かりません。テンプレートパラメータ型の変換/キャストを行う方法はありますか? –

答えて

1

のは、あなたが持っているとしましょう:

struct A {}; 
struct B : A {}; 

template <typename T> struct Foo {}; 

int main() 
{ 
    A a; 
    B b; 

    A& aRef = b; // OK 

    Foo<A> foo_a; 
    Foo<B> foo_b; 

    Foo<A>& foo_aRef = foo_b; // Not OK. 
} 

BAのサブタイプです。これはのサブタイプをFoo<B>にしません。

あなたがラインで見ている問題:

int t1 = static_cast< X<DY> >(xy).test1; 

が悪化しています。

xyは、X<Y>です。あなたはX<DY>にキャストしようとしています。

これは、私のコード例でFoo<A>からFoo<B>にキャストしようとするのと同じです。

あなたのクラスで何を達成しようとしているのかがわからないので、修正案を提案できません。

+0

XとYの2つのクラスがあり、XがテンプレートパラメータとしてYを受け入れている関係を持ち、XとYの両方を派生クラスで拡張してXとYの関係/動作を保持できるようにしたいY.私はそれを表現する簡単な方法があることを疑うことはありませんが、これまで私はこの方向性とアイデアから守られてきました... –

+0

@XerenNarcy、 'DYで何をしようとしているのか説明していません:: tester1() 'さらに重要なのは、あなたが解決しようとしているユースケースが何であるかがはっきりしないことです。それは[XY問題](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)のように感じます。 –

+0

ありがとう、私はここに目的が何であるかについてのより良い説明を追加しました、うまくいけばXY問題にもう一度はなりません(まだ言えば、私はもう一度質問する前に長い考えを持っています) 。 –

関連する問題