0

.hppファイルの代わりに.cppファイルに定義されたメソッドを持つテンプレートクラスがある場合、明示的なインスタンス化を使用して、未解決の外部を避けるためにコンパイラを取得できます。テンプレートの明示的なインスタンス化は、forward-declared-typesで動作しますか?

明示的なインスタンス化が前方宣言型を使用して宣言されている場合は機能しますか? Aが最終的に定義されていないとTemplate<A>が使用されていない場合

template <typename T> struct Template 
{ 
    void someFunc(); //defined in the .cpp file 
} 

class A; 

template Template<A>; 

それは動作しますか?

+0

テンプレートを分割して、すべてをヘッダファイルに定義しないでください。 – NathanOliver

+0

ここでは完全にする必要がある「A」の使用はないので、とにかく問題はありません。 – Quentin

+0

@クエンティン:あなたの答えをありがとう。このコードがライブラリの一部である場合、テンプレート :: someFunc()のシンボルはlibにエクスポートされ、Aが定義されているときには未解決の外部は発生しません。 – Michel

答えて

1

まずは、コンパイラは、テンプレートがインスタンス化されている場合にのみコードを生成します(インスタンス化がないためコードは生成されません)。次に、型テンプレート引数を渡します。ここで、コンパイラはインスタンスを安全に作成することができます。 あなたの例では、あなたはどこかの型を使用しません。関数を定義するために、私の最初の文が再度適用され、関数はインスタンス化の際にちょうどどこかで生成されます。 この時点で、コンパイラはコードを生成するためのすべての知識を持っていなければなりません。

// Example program 
#include <iostream> 


template <typename T> struct Template 
{ 
    void someFunc(); //defined in the .cpp file 
}; 

class A; 
Template<A> foo; 

ただし、非型パラメータを使用してテンプレートを作成すると、あなたが懸念しているように、型定義が不完全であるために失敗します。

// Example program 
#include <iostream> 
#include <string> 

class A; 

template <A parm> struct Template 
{ 
    void someFunc() { 
     parm.foo(); 
    } 
}; 

A a; 
using foo = Template<a>; 

この例でも同じです。ここでは、オブジェクトaを作成します。もちろん、コンパイラは型の詳細を知る必要があります。これが失敗する理由です。

// Example program 
#include <iostream> 


template <typename T> struct Template 
{ 
    T a; 
}; 

class A; 
Template<A> foo; 

希望します。

+0

私は別のプロジェクトで、新しいタイプのこのテンプレートの特殊化を定義するときに、(期待通りに)未解決の外部を関数として持っていました体の中に定義されています。したがって、私はこのテンプレートを効果的に使用していましたが、テンプレートの定義時に存在しないシンボルがあり、libファイルが作成される前に定義されていなかったものです。そのフォワード定義のトリックでは、私はそれ以上の未解決の外部を持っていないし、なぜ私は不思議です。私はテンプレート関数の本体がサイズが分かるようにcppになければならないと信じていました。 – Michel

関連する問題