2016-11-28 6 views
-4
#include <iostream> 
using namespace std; 
class A{ 
public: 
     void K() 
     { 
      cout<<"1"; 
     }; 
}; 
class B{ 
public: typedef A T; 
     void K() 
     { 
      cout<<"2"; 
     }; 
}; 
class C{ 
public: 
     void K() 
     { 
      cout<<"3"; 
     }; 
}; 
class D{ 
    public: 
    void K() 
    { 
     cout<<"4"; 
    }; 
}; 
template <class D=A> class E{ 
public: typedef D T; 
    void K() 
    { 
     cout<<"5"; 
    }; 
}; 
template <> class E<A>{ 
public:typedef C T; 
    void K() 
    { 
     cout<<"6"; 
    }; 
}; 
template <>class E<C>{ 
public:typedef B T; 
    void K() 
    { 
     cout<<"7"; 
    }; 
}; 
template <class W, class V=E<W> > 
class F{ 
typedef typename V::T R; 
public: 
    void K() 
    { 
     V().K(); 
     W().K(); 
     R().K(); 
    }; 
}; 
    int main(){ 
    E<>().K(); 
    F<A>().K(); 
    F<C>().K(); 
    return 0; 
} 

なぜプログラムの出力が6 - 612 - 732であるかわかりません。誰かがこのプログラムの仕組みを助けてくれたら、メインの最初の行もし誰かが最初の雄叫びが6ステップバイステップであると私に言うことができたら、それはすばらしいでしょう。テンプレートとtypedefクラスのプログラム出力

+2

このような問題を解決する適切なツールはデバッガです。スタックオーバーフローを尋ねる前に、コードを一行ずつ進める必要があります。詳しいヘルプは、[小さなプログラムをデバッグする方法(Eric Lippert)](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/)を参照してください。最低限、[最小、完全、および確認可能](http:// stackoverflow)を含めるには、質問を編集する必要があります。com/help/mcve)の例と、デバッガで行った観察結果を表示します。 –

+2

[それはもう少し明確になりますか?](http://coliru.stacked-crooked.com/a/a58abdf4e557a8ae) –

答えて

0

これは、テンプレートの発注ルールによるものです。もっと詳しく調べましょう。

int main(){ 
    E<>().K(); // Line 1. 
    F<A>().K(); // Line 2. 
    F<C>().K(); // Line 3. 
    return 0; 
} 

1行目:ここで

、私たちは、テンプレートパターンE<>に一致するようにしようとしています。選択肢は次のとおりです。

コンパイラは、プライマリテンプレートを調べて、デフォルトパラメータがAであることを確認します。空白が埋め込まれ、テンプレートがE<A>に解決されます。これにより、それがスペシャライゼーションの1つと一致するようになり、スペシャライゼーションが選択されます。ライン1と同様に

E<>().K(); // Calls E<A>::K(). 

ライン2.

パラメータのいずれかが指定されていないため、コンパイラはF<A, E<A>>にテンプレートを解決する、空白を埋めます。従って、WA,VE<A>、そしてRはE<A>::TまたはCである。これは、呼び出される次の関数に解決:

template <class W, class V=E<W> > 
class F{ 
typedef typename V::T R; 
public: 
    void K() 
    { 
     V().K(); // Calls E<A>::K(). 
     W().K(); // Calls A::K(). 
     R().K(); // Calls C::K(). 
    }; 
}; 

3行目:

2行目と同様に、コンパイラは F<C, E<C>>に解決、空白を埋めます。したがって、 WC, VE<C>RE<C>::Tまたは Bです。これは、以下の機能が呼び出されるに解決します。

template <class W, class V=E<W> > 
class F{ 
typedef typename V::T R; 
public: 
    void K() 
    { 
     V().K(); // Calls E<C>::K(). 
     W().K(); // Calls C::K(). 
     R().K(); // Calls B::K(). 
    }; 
}; 

そして今、我々は、テンプレートを解決したことを...出力がゆえである

int main(){ 
    E<>().K(); // E<A>::K(). 
    F<A>().K(); // F<A, E<A>>::K() -> E<A>::K(), A::K(), C::K(). 
    F<C>().K(); // F<C, E<C>>::K() -> E<C>::K(), C::K(), B::K(). 
    return 0; 
} 

...

6613732 

[注意:コンパイラから出力された出力が6612732の場合、それは想定されていませんでした。 Clang、GCC、およびMSVCは、ここに適切な出力が6613732であることにすべて同意します。]

+0

うん、正しい出力は実際には6613732、私の悪いです。あなたの時間と私を助けてくれてありがとう! – redizzar

+0

@PatrikTóthよろしくお願いします。 –