最近、イテレータがコンパイル時に複雑な値を指しているかどうかを判断する方法について質問し、機能する回答を受け取りました。
質問はここにあります:複雑な値を指すイテレータのアルゴリズムをどのように特殊化できますか?
そして、解決策は、あるテンプレートが別のテンプレートの特殊化であるかどうかを判断する一連のテンプレートでした。
template <class T, template <class...> class Template>
struct is_specialization : std::false_type {};
template <template <class...> class Template, class... Args>
struct is_specialization<Template<Args...>, Template> : std::true_type {};
これは機能しますが、これがどのように機能するかを理解するのに本当に苦労しています。特に、template
a内にネストされているtemplate
と、混乱します。また、可変個引数テンプレートの使用はまだかなり新しいので、たとえば、<class...>
このようなものの代わりに、型が指定されていない可変個引数テンプレートを使用するのは奇妙に思え<class... Args>
ます。
誰かがこのテンプレートを分解して、それがどのように解決されるかを説明できますか?
テンプレートパラメータには次の3つのタイプがあることを考慮に入れる必要があります。
1)タイプ
2)非タイプ(または値)
3)テンプレート-テンプレート
最初のタイプの前にはtypename
(またはclass
)が付きます
template <typename T>
void foo (T const & t);
前の例でT
は、は型であり、t
(古典的な関数の引数)は型の値ですT
。
テンプレートパラメータの2番目のタイプは値であり、値のタイプが前に付きます(またはauto
、指定されていないタイプの場合は、C ++ 17以降)。
template <int I>
void bar ()
{ std::cout << I << std::endl; }
前の例では、I
テンプレートパラメータはタイプの値ですint
。
3番目のタイプは、説明するのが最も複雑です。
std::vector<int>
とstd::vector<double>
は異なるタイプであることを知っていますか(私は推測します)が、共通してstd::vector
、テンプレートクラスがあります。
template-templateパラメーターは、std::vector
引数なしのテンプレートクラスを受け入れるパラメーターです。
template
次の例のように、template-templateパラメーターの前にキーワードがあります
template <template <int> class C>
void baz ();
C
前の例のtemplate-templateパラメーターは、単一のint
(値)テンプレートパラメーターを必要とするクラス(または構造体)です。
だからあなたがクラスを持っているなら
template <int I>
class getInt
{ };
getInt
テンプレートパラメータとして、に渡すことができますbaz()
baz<getInt>();
これで、コードを理解できるはずです。
template <class T, template <class...> class Template>
struct is_specialization : std::false_type {};
is_specialization
構造体は、テンプレートパラメータ、タイプ(として、受信テンプレート構造体であるT
)、およびテンプレートテンプレートTemplate
型テンプレートパラメータの可変長番号を受信するクラス/構造体を受け入れます。
今、あなたは以下の専門分野を持っていますis_specialization
:
template <template <class...> class Template, class... Args>
struct is_specialization<Template<Args...>, Template> : std::true_type {};
この特殊化は、最初のテンプレートパラメータ(Template<Args...>
)が2番目の(Template
)に基づくクラスである場合に選択されます。
例:インスタンス化する場合
is_specialization<std::vector<int>, std::map>
に基づいていないstd::false_type
ため、メインバージョン(から継承)が選択さstd::vector<int>
れていstd::map
ます。
しかし、インスタンス化する場合
is_specialization<std::vector<int>, std::vector>
に基づいているstd::true_type
ため、(から継承する)特殊化が選択さstd::vector<int>
れstd::vector
ます。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加