最初の質問への回答
ここで定義したテンプレートの特殊化:
template <typename T> struct HasXYZ <T,typename T::XYZ>
{ static const bool value = true; };
誰かが特定のデータ型HasXYZ<A,A::XYZ>
にデータ型を使用すると有効になりA
ます。
A
とにかく、A::XYZ
は完全に独立したデータ型であることに注意してくださいA
。内部クラスは、それ自体がデータ型です。最初のテンプレート引数として使用する場合、その名前の内部クラスが存在し、そうするとコンパイラがリードする場合でも、コンパイラが2番目の引数A
と呼ばれるものを使用することを想定する理由はまったくありません。A:XYZ
テンプレート引数に正確に一致するテンプレート特殊化に。テンプレートの特殊化は、さらに可能なテンプレート引数に基づくのではなく、コーダーによって提供されるテンプレート引数に基づいて検出されます。
したがって、を使用すると、2番目のパラメーターHasXYZ<Foo>
にデフォルトのテンプレート引数を使用することにフォールバックしvoid
ます。
言うまでもなく、HasXYZ<Foo,Foo:XYZ>
明示的に使用すると、期待どおりの出力が得られます。しかし、それは明らかにあなたが意図したものではありません。
私はあなたが必要とするものstd::enable_if
(または同様の方法で機能するもの)を手に入れる唯一の方法を恐れています。
追加の質問への回答(更新後)
以下の簡略化を検討してください。
template <typename T, typename Check = void>
struct A
{ static const bool value = false; };
template <typename T>
struct A<T,void>
{ static const bool value = true; };
一次定義void
は、2番目のテンプレートパラメータのデフォルト引数を指定します。ただし、特殊化(上記の2番目の定義)は、2番目のテンプレートパラメーターが実際にである場合に実際にどのようにclass A
見えるかを定義します。 void
これが意味するのは、たとえば、A<int>
コードでデフォルトの引数を使用すると、が取得されるように補足されA<int,void>
、コンパイラが最も適切なテンプレートの特殊化を見つけるということです。これは上記の2番目の特殊化です。
したがって、デフォルトのテンプレート引数はプライマリテンプレート宣言の一部として定義されますが、それらを使用しても、プライマリテンプレート定義が使用されることを意味するわけではありません。これは基本的に、デフォルトのテンプレート引数がテンプレート定義(*)ではなく、テンプレート宣言の一部であるためです。
typedef void XYZ
これが、あなたの例で、がに含まれているFooWithTypedef
場合、2番目のテンプレートパラメータがデフォルトでに設定されvoid
、次に最も適切な特殊化が見つかる理由です。これは、テンプレートの特殊化で2番目の引数がのT::XYZ
代わりに定義されている場合でも機能しvoid
ます。これらが評価時に同じである場合、テンプレートの特殊化が選択されます(§14.4「タイプの同等性」)。
(*)私は、実際にそれを非常に明確に述べているステートメントを標準で見つけませんでした。しかし、§14.1/ 10があります。これは、テンプレートの複数の宣言(ただし、1つの主要な定義のみ)がある場合を説明しています。
(§14.1/ 10)テンプレート宣言または定義で使用できるデフォルトのテンプレート引数のセットは、定義からのデフォルトの引数(スコープ内の場合)と、デフォルトの関数の引数と同じ方法でスコープ内のすべての宣言をマージすることによって取得されます(8.3.6)。[ 例:
template<class T1, class T2 = int> class A;
template<class T1 = int, class T2> class A;
と同等です
template<class T1 = int, class T2 = int> class A;
]。
これは、デフォルトのテンプレート引数の背後にあるメカニズムが、テンプレートの最も適切な特殊化を識別するために使用されるメカニズムとは独立していることを示唆しています。
さらに、このメカニズムを参照する2つの既存のSO投稿があります。
クラスメンバーtypedefが存在しない場合にデフォルトタイプを使用するためのテンプレートスペシャライゼーションへのこの応答
クラステンプレートスペシャライゼーションのテンプレートパラメータのデフォルト値