2013-10-28 9 views
10

のメンバーの使用上の仮想の影響Iは(漠然と)がないを使用する場合は、テンプレートがインスタンス化されていないことを知っています。たとえば、T = intの場合、T::typeが意味を成さないにもかかわらず、次のコードは正常にコンパイルされます。クラステンプレート

template<typename T> 
struct A 
{ 
    void f() { using type = typename T::type; } 
}; 

A<int> a; //ok 

f()はないを使用しているので、—は、このようにT::typeの妥当性がチェックされないままにインスタンス化されていないので、それがコンパイルされます。 メンバーの機能がg()の場合はf()としても問題ありません。

template<typename T> 
struct A 
{ 
    void f() { using type = typename T::type; } 

    void g() { f(); } //Is f() still unused? 
}; 

A<int> a; //ok 

これもcompile finesです。しかし、ここで私は"使用"の定義の私の理解のあいまいさを実現します。私は尋ねます:

  • f()は未使用ですか?どのくらい正確に?

g()の中ではっきりとわかります。しかし、私はg()が使用されていないので、f()もインスタンス化の観点からは使用されていないと考えました。それは十分に妥当と思われる。これまでのところ。私はg()virtualキーワードを追加する場合

しかし、それはコンパイルされません。今ではf()をインスタンス化しようとするので、それがcompilation errorになり

template<typename T> 
struct A 
{ 
    void f() { using type = typename T::type; } 

    virtual void g() { f(); } //Now f() is used? How exactly? 
}; 

A<int> a; //error 

。私はこの行動を理解していません。

誰でもこれを説明できますか?特に、virtualキーワードの影響は、クラステンプレートのメンバーの "使用"の定義に影響します。

+1

私が正しく思い出すと、 'virtual'は、この関数が使用されるかどうかを静的に評価することはほとんど不可能なので、メンバー関数のインスタンス化を強制します。実際には、関数へのポインタでいっぱいのvテーブルを作成するように求めています。関数へのポインタが必要なので関数が必要です。 –

+0

構造体テンプレートは、使用時にのみインスタンス化されます。これは構造体全体か何もありません。それはgやfとは関係がありません。 – Sarien

+1

@Sarien:テンプレートクラスのメンバー関数は、ODRが使用されている場合にのみインスタンス化されます。 –

答えて

8

3.2 [basic.def.odr]利回りで簡単に見:

3/[...]仮想メンバ関数は、それが純粋でない場合に使用ODR-です。 [...]

そして、私はまた、14.7.1 [temp.inst]で発見:

10 /暗黙的に関数テンプレートをインスタンス化してはならない実装、メンバーテンプレート、非仮想メンバ関数、メンバクラス、またはインスタンス化を必要としないクラステンプレートの静的データメンバである。 仮想メンバ関数がインスタンス化されない場合、インプリメンテーションがクラステンプレートの仮想メンバ関数を暗黙的にインスタンス化するかどうかは不特定です。(強調鉱山)

だから... ...私はvirtualメソッドは常にインスタンス化される可能性があると言うでしょう。

実際には、クラスをインスタンス化するときに、コンパイラがテンプレートクラスの仮想テーブルをインスタンス化することを期待しています。このクラスのすべてのvirtualメンバ関数を即座にインスタンス化します(仮想テーブルのメンバー関数を参照できるようになります)。

関連する問題