この質問は私に考えさせました。引数のパブリックを定義できない場合は、クラステンプレートの特殊化から実際の引数を取得すると便利な場合がtypedef
あります。C ++ 03では、これは悪いテンプレートデザイン、または反対のデザイン意図のいずれかの兆候であり、特に一般的ではありません。ただし、可変個引数テンプレートを使用するとtypedefのカバレッジが不可能になるため、追加の作業を行わずに問題を解決するためのツールがあれば便利です。
C ++ 0xはtypedef
、1つの特定の可変個引数テンプレートの問題を解決しtuple
ます。
tuple_element< 2, tuple< char, short, int > >::type my_int; // nth element type
しかしtuple_element
、結婚していませんtuple
; とでも機能しpair
ますarray
。その宣言は言及していませんtuple
。
template< size_t index, typename something_like_a_tuple >
struct tuple_element; // general case is left incomplete, unimplemented
tuple
部分的な特殊化によって関連付けられています:
template< size_t index, typename ... tuple_elements >
struct tuple_element< index, tuple< tuple_elements ... > > { // impl. in here
しかし、そうである必要はありません。tuple
テンプレートテンプレートパラメータは、タイプに対してのみパラメータ化された他のテンプレートと一致する可能性があります。
template< size_t index,
template< typename ... > class template_over_types,
typename ... types >
struct tuple_element< index, template_over_types< types ... > > {
これにより、
tuple_element< 1, almost_any_template< char, int > >::type my_int;
tuple_element< 0, pair< int, char > >::type another_int; // same specialization
それでも、追加の専門化を許可しますarray
template< size_t index, typename element, size_t extent >
struct tuple_element< index, array< element, extent > >
{ typedef element type; }
array
の2番目の引数は型ではなく、であるため、競合は発生しませんsize_t
。
残念ながら、ユーザーはtuple_element
自分のタイプに合わせてインターフェースを特殊化することができます。ユーザーの前提条件とその保証は、C++0x§17.6.3.2.1/1によって与えられます。
プログラムは、宣言がユーザー定義型に依存し、特殊化が元のテンプレートの標準ライブラリ要件を満たし、明示的に禁止されていない場合にのみ、任意の標準ライブラリテンプレートのテンプレート特殊化を名前空間stdに追加できます。
したがって、一般的な特殊化が特殊化と競合してはならないだけでなく、ユーザー定義型を指定する特殊化array
とも競合してはなりません。つまり、ユーザーが特殊化を宣言した場合、一般引数ゲッターの存在は、それが選択されるかどうかに影響を与えることはできません。
インスタンス化であいまいさが生じた場合(つまり、2つの部分的な特殊化が引数リストに一致する場合)、選択肢が比較されて、どちらが最も特殊化されているか、つまり最も一般化されていないかが判別されます。選択肢をAとBと呼びます。これは、AがBの仕事をすることはできるが、BがAの仕事をすることができない場合、Bはより専門的であることを意味します。Aはジェネラリストです。Bが選択されます。インスタンス化を引き起こす実際の引数は、両方の候補に一致することがすでにわかっているため、考慮されません。
一般的なテンプレートを他のすべてに延期したいので、良好な状態です。
一般性は、Aの部分特殊化パラメーターを一意のダミー型に置き換え、Bもそのような特殊化を実装できるかどうかをチェックすることによってチェックされます。役割を逆にして繰り返します。反対の結果が得られた場合、1人の候補者がより専門的であることがわかります。
ユーザーのスペシャライゼーションにユーザー定義型が存在すると、その優先順位が保証されます。これは、引数ゲッターに対応する一意のダミー型が存在する必要があるためです。これは、それに一致しません。
たとえば、これは非常に一般的なユーザー宣言の専門分野です。これはtuple_element
、特定のを含むタイプパラメータ化されたテンプレートを定義しますuser_type
。
template< size_t I,
template< typename ... > class any_template,
typename ... T, typename ... U >
struct tuple_element< I, any_template< T ..., ::user_type, U ... > >;
シーケンス..., user_type, ...
は一般的なケースで処理できますが、ユーザーのケースでは、が含まれないため、完全に人工的な一意のタイプで構成されるシーケンスを処理できませんuser_type
。
いずれかのユーザー専門分野が候補である場合、それは優れた専門分野になります。
(標準では、疑似コードでの個別の部分特殊化が指定されていますがtuple
、as-ifルールでは省略できます。とにかく、実装されている場合は、ユーザーを保護するのと同じ優先順位ルールでカバーされます。)
私は半順序規則に多くの進出をしていません。この分析は正しいですか?実装が一般的なテンプレートインデクサーを公開しても大丈夫ですstd::tuple_element
か?