次のコードが準拠し、完全に機能する理由を説明してください。私は非常に混乱しています。
#include<iostream>
template<class A = int, class B=double>
class Base
{};
template<class B>
class Base <int, B>
{
public:
Base()
{
std::cout<<"it works!!!!!\n";
}
};
int main()
{
Base<> base; // it prints "it works!!!!!"
return 0;
}
テンプレートクラスBaseの一般化された形式に該当するべきではないでしょうか。
デフォルトの引数はスペシャライゼーションに適用され、実際、スペシャライゼーションは基本テンプレートのデフォルトの引数を(いわば)受け入れる必要があります。特殊化でデフォルトを指定しようとしています:
template<class A = int, class B=double>
class Base
{};
template<class B=char>
// ...
...エラーです。
同様に、特殊化を変更して、その特殊化が基本テンプレートによって提供されるデフォルトよりもタイプotherになるようにした場合:
template<class A = int, class B=double>
class Base
{};
template<class B>
class Base <char, B>
...次に、基本テンプレートが選択されます。
つまり、何が起こっているのかということです。まず、テンプレート引数のタイプが選択されます。この場合(インスタンス化時にタイプが指定されていない)、両方のタイプは、ベーステンプレートで指定されたデフォルトのテンプレート引数に基づいています。
次に(基本的に別の手順として)、これらの引数の型に適合するすべてのテンプレートで、オーバーロードの解決のアナログを実行します。通常、オーバーロードの解決では、明示的に指定された型が暗黙的に指定された型よりも優先されるため、(int
を明示的に指定した)特殊化が基本テンプレート(int
を暗黙的に指定した)よりも優先されます。 。
template<class A = int, class B=double>
class Base
{};
ここでは、AとBのデフォルト値/初期化がそれぞれintとdoubleとして宣言されています。
template<class B>
class Base <int, B>
ここでのクラス定義では、最初の引数は定数値のようなもの(ここではint;なぜこのように宣言して複雑にするのか?最初のテンプレート引数を削除するほうがよい)で、2番目のテンプレート引数はBで、デフォルト値は 'double'です。
Base<> base;
クラスのオブジェクトを作成するとき。テンプレート引数を指定しなくても、コンパイラーは引数(AおよびB)のデフォルト値(「int」および「double」)を取得し、コードはエラーや警告なしで実行されます。
オブジェクトを次のように作成するとどうなるかを見てください:Base<float,char> b;
またはBase<char,char> b;
Base<> base;
を記述すると、コンパイラーはBase<>
クラスのインスタンス化が可能かどうか、また可能であればコードが正常に機能するかどうかを調べようとします。この場合、Baseのデフォルトのテンプレート引数が原因で可能です。コンパイラは、Base<>
と書いた場合、Base<int,double>
のオブジェクトを作成する必要があるかどうかを知っているためです。すなわち:のため:
template<class A = int, class B=double>
class Base
{};
したがって、コードは正常に動作します。