How do nested templates get resolved in C++?

只愿长相守 提交于 2020-03-23 05:42:22

问题


I recently asked a question about determining whether an iterator points to a complex value at compile time and received an answer that works.

The question is here: How can I specialize an algorithm for iterators that point to complex values?

And the solution was a set of templates that determine whether one template is a specialization of another:

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 {};

This does work, but I am really struggling to understand how this works. Particularly the nested template within a template is confusing to me. I'm also still fairly new to using variadic templates and it seems odd to have a variadic template with no type provided, for example: <class...> instead of something like this <class... Args>.

Can someone please break down this template and describe how it gets resolved?


回答1:


You have to take in count that there are three types of template parameters:

1) types

2) non-types (or values)

3) template-templates

The first type is preceded by typename (or class)

template <typename T>
void foo (T const & t);

In the preceding example, T is a type and t (a classical function argument) is a value of type T.

The second type of template parameter are values and are preceded by the type of the value (or auto, starting from C++17, for a not specified type)

template <int I>
void bar ()
 { std::cout << I << std::endl; }

In the preceding example the I template parameter is a value of type int.

The third type is the most complex to explain.

Do you know (I suppose) that std::vector<int> and std::vector<double> are different types, but they have in common std::vector, a template class.

A template-template parameter is a parameter that accept std::vector, the template class without arguments.

A template-template parameter is preceded by a template keyword, as in the following example

template <template <int> class C>
void baz ();

The template-template parameter C in the preceding example is class (or struct) that require a single int (value) template parameter.

So if you have a class

template <int I>
class getInt
 { };

you can pass getInt, as template parameter, to baz()

baz<getInt>();

Now you should be able to understand your code:

template <class T, template <class...> class Template>
struct is_specialization : std::false_type {};

the is_specialization struct is a template struct that receive, as template parameters, a type (T) and a template-template Template that accept classes/structs receiving a variadic number of type template parameters.

Now you have a specialization of is_specialization:

template <template <class...> class Template, class... Args>
struct is_specialization<Template<Args...>, Template> : std::true_type {};

This specialization is selected when the first template parameter (Template<Args...>) is a class based on the second (Template).

An example: if you instantiate

is_specialization<std::vector<int>, std::map>

the main version (that inherit from std::false_type) is selected because std::vector<int> isn't based on std::map.

But if you instantiate

is_specialization<std::vector<int>, std::vector>

the specialization (that inherit from std::true_type) is selected because std::vector<int> is based on std::vector.



来源:https://stackoverflow.com/questions/59976065/how-do-nested-templates-get-resolved-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!