了解C++模板元编程

Pau*_*aul 6 c++ templates metaprogramming c++11

为了更好地理解C++中的模板和元编程,我正在阅读本文,但是我对代码片段的理解很快就会消失,例如:

template<class A, template<class...> class B> struct mp_rename_impl;

template<template<class...> class A, class... T, template<class...> class B>
    struct mp_rename_impl<A<T...>, B>
{
    using type = B<T...>;
};

template<class A, template<class...> class B>
    using mp_rename = typename mp_rename_impl<A, B>::type;
Run Code Online (Sandbox Code Playgroud)

代码使用如下:

mp_rename<std::pair<int, float>, std::tuple>        // -> std::tuple<int, float>
mp_rename<mp_list<int, float>, std::pair>           // -> std::pair<int, float>
mp_rename<std::shared_ptr<int>, std::unique_ptr>    // -> std::unique_ptr<int>
Run Code Online (Sandbox Code Playgroud)

有人可以像我这样解释代码吗?我对非模板化C++有一般性和基本的理解.

我没有得到的是:

为什么mp_rename_impl前向声明有两个类型参数(class A, template<class...> class B),那么它是同时定义和专用[*]三个(template<class...> class A, class... T, template<class...> class B)和两个(A<T...>, B)类型参数?

据我所知,它的别名(using type = B<T...>;)的typeB<T...>不是A<T...>,但我真的不明白它是如何做.

另外,为什么A模板模板参数只在专业化中?

[*]我肯定在这里弄错了

Ton*_*roy 5

为什么mp_rename_impl使用两个类型参数 ( class A, template<class...> class B) 进行前向声明,然后同时使用三个 ( template<class...> class A, class... T, template<class...> class B) 和两个 ( A<T...>, B) 类型参数对其进行定义和特化 [*] ?

前向声明确定了实例化所需的参数数量mp_rename_impl,并且前者应该是实际类型,后者应该是模板。

然后,当存在实际实例化时,它会尝试匹配 specialization struct mp_rename_impl<A<T...>, B>,并且在这样做时,它可以考虑专业化的值的任何组合AT...B匹配专业化的期望:即template<class...> class A, class... T, template<class...> class B. 请注意,特化中的A参数与A声明中的 共享一个名称,但不一样 - 前者是模板,后者是类型。实际上,要匹配特化,模板实例化必须作为声明的A参数传递,并且该模板的参数在 处捕获T...。它对可以传递的内容没有施加新的限制B(尽管using声明确实 -B<T...> 必须是有效的,否则你会得到一个编译错误——SFINAE 来不及启动)。

另外为什么A模板模板参数仅在专业化中?

专业化调用该参数A,但它在概念上与A声明中的不同。相反,前者A<T...>对应于后者A。也许专业化应该称它为“TA”或其他东西,以表明它是A可以结合T...参数形成实际的模板。然后特A<T...>, B化是of ,因此编译器从实际尝试的任何实例化开始向后工作,以找到A, T...and 的有效替换,并B受 中指定的形式限制的指导template<template<class...> class A, class... T, template<class...> class B>

这样做的目的是确保仅当两个参数是已经给定一些参数类型集的模板以及能够采用参数类型列表的模板时才匹配特化。匹配过程有效地隔离了T类型列表,以便它可以与B.