首先,我们编写一些机制来替换模板类型实例中的类型:
template<class In, class Replace>
struct replace_first_type;
template<template<class...>class Z, class T0, class...Ts, class Replace>
struct replace_first_type<Z<T0, Ts...>, Replace> {
using type=Z<Replace, Ts...>;
};
template<class In, class Replace>
using replace_first = typename replace_first_type<In,Replace>::type;
replace_first< Z, X >
拿
Z
,模式与任何
template<class...>
,获取第一个参数,并将其替换为
X
.
这不适用于
std::array<int, 7>
作为
7
不是一种类型,但适用于
std::vector<int>
;
vector
实际上是
<T, A>
使用默认参数。这个
模板类…
模式匹配接受0个或更多类的模板。
然后我们应用它:
template<typename A>
class foo {
template<typename B>
using result = replace_first<B, A>;
};
现在
foo<int>::template result< std::vector<double> >
是一个
std::vector<int, std::alloctor<double>>
. 诚然,这是一种相当愚蠢的类型。
如果您有一个函数:
template<class B>
result<B> do_something() {
return {};
}
实际上返回该类型的值。
我们可以用
std::allocator<double>
上面通过递归替换我们替换的类型…
template<class X, class Src, class Dest>
struct subst_type {
using type=X;
};
template<class X, class Src, class Dest>
using subst_t = typename subst_type<X, Src, Dest>::type;
template<template<class...>class Z, class...Ts, class Src, class Dest>
struct subst_type<Z<Ts...>, Src, Dest> {
using type=Z<subst_t<Ts, Src, Dest>...>;
};
template<class Src, class Dest>
struct subst_type<Src, Src, Dest> {
using type=Dest;
};
并申请先更换:
template<class In, class Replace>
struct replace_first_type;
template<template<class...>class Z, class T0, class...Ts, class Replace>
struct replace_first_type<Z<T0, Ts...>, Replace> {
using type=Z<Replace, subst_t<Ts, T0, Replace>...>;
};
现在当我们
foo<int>::result<std::vector<double>>
我们得到
std::vector<int, std::allocator<int>>
而不是
std::vector<int, std::allocator<double>>
(这是一种无用的类型)。
Live example
.
有可能我们会从递归替换中得到可怕的错误。
A
具有
B
在一个模板的其余参数中,但是如前所述,如果我们不这样做,我们肯定会对普通模板产生一些可怕的影响。