55

私にとって、C++ テンプレートはダック タイピングのアイデアを使用していましたが、これは正しいですか? テンプレートクラスまたはメソッドで参照されるすべてのジェネリック型がダック型であることを意味しますか?

4

7 に答える 7

89

私にとって、C++ テンプレートはダック タイピングのコンパイル時バージョンです。コンパイラはクラスなどをコンパイルし、Duck に必要なすべての型がある限り、クラスをインスタンス化します。

何かが正しくない場合 (コピー コンストラクターがないなど)、コンパイルは失敗します。実際のダックタイピングで対応するのは、非ダック型で関数を呼び出したときの失敗です。そして、ここでは実行時に発生します。

于 2011-08-03T08:09:18.513 に答える
18

ダックタイピングとは、「アヒルのように鳴き、アヒルのように歩くなら、それはアヒルだ」という意味です。C++ と比較するための、コンピュータ サイエンスにおける正式な定義はありません。

もちろん、C++ は (たとえば) Python と同じではありませんが、どちらも暗黙的に定義されたインターフェイスの概念を持っています。Python 関数の引数として使用されるオブジェクトに必要なインターフェイスは、関数がそれに対して行うものです。C++ テンプレート引数として使用される型に必要なインターフェイスは、テンプレートがその型のオブジェクトに対して行うものです。これが類似性であり、C++ テンプレートを評価する根拠となります。

さらに、テンプレート引数推定により、C++ では古いオブジェクトを渡そうとすることができ、コンパイラは関数テンプレートをインスタンス化できるかどうかを判断します。

1 つの違いは、C++ では、引数がクワックしない場合、コンパイラ オブジェクトです。Python では、ランタイム オブジェクトのみ (関数が実際に呼び出された場合、コードに条件がある場合のみ)。これは、オブジェクト/型に要求されるインターフェイスの性質の違いです。C++ では、テンプレートが特定の式が有効であることを要求するか、それを要求しないかのいずれかです。Python では、必要な有効な式は、以前に必要な式の実行時の値に依存する場合があります。そのため、Python では、大きな音または静かな音を出すオブジェクトを要求できます。大きな音を出す場合は、オブジェクトも歩く必要があります。C++ では、条件によってそれを行うことができdynamic_cast、ボリュームがコンパイル時の定数である場合は、テンプレートの特殊化を行うことができますが、'quack_volume()戻りますloud。もちろん、Python では必要なインターフェイスは実際には「必須」ではない場合があります。メソッドが存在しない場合の動作は例外をスローすることであり、それが発生した場合の呼び出し元の動作を文書化して保証できる可能性があります。

この違いが C++ にはないことを意味するように、「ダック タイピング」を定義するかどうかはあなた次第です。

于 2011-08-03T09:07:18.050 に答える
15

私にとって、C++ テンプレートはダック タイピングのアイデアを使用していましたが、これは正しいですか?

いいえ、C++ テンプレートは汎用コードの実装に使用されます。つまり、複数の型で動作するコードがある場合、型ごとに複製する必要はありません。std::vectorやのようstd::listなものは、これが実際に行われている明らかな例です。C++ テンプレートは他のことを行うために悪用されてきましたが、汎用性が当初の意図でした。

テンプレートクラスまたはメソッドで参照されるすべてのジェネリック型がダック型であることを意味しますか?

いいえ、それらは C++ の他のすべての型と同様に、単なる「通常の」型です。テンプレートが実際にインスタンス化されるまで、それらはわかりません。

ただし、テンプレートを使用して、ダック タイピングのようなものを実装できます。イテレータはその例です。この関数を考えてみましょう:

template<class InputIterator, class OutputIterator>
    OutputIterator copy(InputIterator first, InputIterator last,
                        OutputIterator result)
{
    while (first!=last) *result++ = *first++;
    return result;
}

この関数は、不等式演算子、逆参照演算子、および後置インクリメント演算子を実装するだけでなく、任意の型のcopy引数を受け入れることができることに注意してください。これはおそらく、C++ で得られるダック タイピングに近いものです。

于 2011-08-03T08:02:48.590 に答える
6

ではない正確に。ダック型 (動的型スタイル) は型を持たないため、コンパイル時に型エラーが発生することはありません。テンプレートでは、テンプレートをインスタンス化するまで型はありません。一度実行すると、変数には異なる型があり、実際にコンパイル時にエラーが発生します。

また、ダック型を使用すると、変数には型がないため、1 つの変数がさまざまな型のオブジェクトを指すようにすることができます。これはテンプレートでは不可能です。インスタンス化すると、変数は特定の型を 1 つ持ちます。

ただし、制約が暗黙的であるという点では似ています。実際に使用される機能のみがチェックされます。たとえば、ポリモーフィック ポインターとは対照的に、実際の型は重要ではありません。

于 2011-08-03T08:02:36.343 に答える
4

はい。たとえば、タイプXに があり、AddRef()メソッドに適切なシグネチャが含まれている場合、テンプレート クラスを使用して COM オブジェクトとして使用できます。しかし、これは完全なダックタイピングではありません - 型チェックは依然としてパラメータに対して強制されています。Release()QueryInterface()CComPtr

于 2011-08-03T08:00:14.597 に答える
2

いいえ、これは別の概念です。ダックタイピングは、動的に型付けされたコンテナの型を見つける方法です。C++ テンプレートは動的な型付けではなく、特定の型でインスタンス化されます。

于 2011-08-03T08:01:40.107 に答える
1

ウィキペディアでは、この区別について説明しています。

于 2011-08-03T08:30:36.323 に答える