テンプレートに先立ち、タイプに依存しないC++コードは、ランタイムポリモーフィズムを使用して記述する必要がありました。しかしテンプレートでも、2つの手法を組み合わせることができます。
たとえば、後で取得するために、任意のタイプの値を保存するとします。テンプレートがなければ、あなたはこれを行う必要があるだろう:
struct PrintableThing
{
// declare abstract operations needed on the type
virtual void print(std::ostream &os) = 0;
// polymorphic base class needs virtual destructor
virtual ~PrintableThing() {}
};
class PrintableContainer
{
PrintableThing *printableThing;
public:
// various other secret stuff
void store(PrintableThing *p);
};
このライブラリのユーザーが自分のデータをラップアラウンドし、その上にprint
機能を実装するために手でPrintableThing
の独自の派生バージョンを記述する必要があります。
しかし、あなたは、このようなシステム周りのテンプレートベース層ラップすることができます:
template <T>
struct PrintableType : PrintableThing
{
T instance;
virtual void print(std::ostream &os)
{ os << instance; }
PrintableType(const T &i)
: instance(i) {}
};
をし、またPrintableContainer
クラスの宣言では、ライブラリのヘッダにメソッドを追加:
template <class T>
void store(const T &p)
{
store(new PrintableType(p));
}
これは、テンプレートとランタイムポリモフィズムの間の橋渡しとして、<<
演算子へのコンパイル時バインディングprint
を実装し、コピーコンストラクタa lso(もちろんネストしたインスタンスのデストラクタにも転送します)。
このようにして、ライブラリのソースに隠れて実装できるように、実行時の多形性に基づいてライブラリを完全に書くことができますが、テンプレート "sugar"を少し追加すると便利ですつかいます。
これが問題になるかどうかは、必要に応じて異なります。ランタイム多形性は時にはまさにあなた自身が必要とするものであるという点で純粋に技術的な利点があります。欠点として、間違いなくインライン化を効果的に行うコンパイラの能力が低下することは間違いありません。逆に、あなたのコンパイル時間とバイナリコードの膨れが低下する可能性があります。
std::tr1::function
とboost::any
は、非常にきれいで現代的なC++テンプレートベースのフロントエンドを備えていますが、ランタイムポリモーフィックコンテナとしてバックグラウンドで動作します。
なぜテンプレートの実装の詳細を公開したくないのですか? –
@ Neeil:私は彼がヘッダーファイルでプリコンパイルされたライブラリを出荷したいと思うでしょう、そして、ヘッダーファイルを提供することによって実装を公開したくありません。誰かにコードを渡すだけではない理由はいくつかあります。 –
@Daniel Sigh。申し訳ありませんが、私はあなたの前提(または他の誰か)を望んでいません - 私は、OPの理由が欲しいです。 SOに載っているほとんどの人がなぜ「仮定」または「推測」するような強い衝動を感じているのですか? –