3

この質問は私に考えさせました。引数のパブリックを定義できない場合は、クラステンプレートの特殊化から実際の引数を取得すると便利な場合が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か?

4

1 に答える 1

1

したがって、一般的な特殊化は配列の特殊化と競合してはならないだけでなく、ユーザー定義型を指定する特殊化とも競合してはなりません。つまり、ユーザーが特殊化を宣言した場合、一般引数ゲッターの存在は、それが選択されるかどうかに影響を与えることはできません。

わかりません。どう言う意味ですか?


実装がstd::tuple_elementを介して一般的なテンプレートインデクサーを公開しても大丈夫ですか?

一般的なケースではそうすることは不可能です。これを想像してみてください

template<int A, char B, long C, class D, int &X, int(*Handler)()>
struct funny_template { };

int x, y();
std::tuple_element<3, funny_template<1, 2, 3, long, x, y> >::type along = 0;

ハッピーマクロメタプログラミング:)


私は半順序規則に多くの進出をしていません。この分析は正しいですか?

2つの半専門分野の半順序

template<class A1, ..., class AN>
class T<Am1, ..., AmM>;

template<class B1, ..., class BL>
class T<Bm1, ..., BmM>;

それらを関数テンプレートに変換して順序付けするように機能します

template<class A1, ..., class AN>
void f(T1<Am1, ..., AmM>);

template<class B1, ..., class BL>
void f(T2<Bm1, ..., BmM>);

分析によると、部分的な順序付けでは、テンプレートパラメータごとに一意の型が正しく配置され、他のテンプレートと比較して、引数を差し引くための引数に変換されます。

T1A<Uam1, ..., UAmM> -> T2<Bm1, ..., BmM>
T2A<UBm1, ..., UBmM> -> T1<Am1, ..., AmM>

推論されていないコンテキストがある場合、通常のように比較されません。BmMの場合と同様typename Foo::Xに、上記の最初の控除では、推論されていないコンテキストの不一致はあり得ないため、最後のサブタイプの控除は成功と見なされます。逆に言えば、それ自体が推論されていないコンテキストでない場合でも、Foo::Xに対してAmM 不一致になる可能性があります。AmM

控除が1つのラウンドで成功し、その逆ではない場合(...実際の関数テンプレートの順序付けでのみ発生するため、他のルールを省略します)、控除に失敗したラウンドの右上のテンプレートはより特殊化されます。それ以外の場合、部分的な特殊化は順序付けられていません。

于 2010-09-13T11:50:22.150 に答える