The template
专门化的参数不是原始定义的模板参数。
与原始定义相对应的位于template
name.
中的论点template<>
专业化的一部分是为匹配专业化而引入的类型。
所以原来的定义:
template <typename Enable, typename...Args>
struct Get;
1 个或多个类型参数。并且,除非专业化匹配,否则不会定义。
第一专业:
template <typename FirstArg, typename... OtherArgs>
struct Get<typename std::enable_if<true>::type, FirstArg, OtherArgs...> {
using type = double;
};
well, std::enable_if<true>::type
只是void
,所以这与:
template <typename FirstArg, typename... OtherArgs>
struct Get<void, FirstArg, OtherArgs...> {
using type = double;
};
因此,如果第一种类型是,则匹配void
,并且至少还有一种其他类型。
第二专业:
template <typename Arg>
struct Get<typename std::enable_if<std::is_same<Arg, int>::value>::type, Arg> {
using type = double;
};
所以这会尝试匹配是否有两种类型。第二个是模式匹配。
如果不是的话int
,第一个 SFINAE 失败。如果它是一个int
,第一个最终是void
。所以这匹配Get<void, int>
only.
第三专业:
template <typename Arg>
struct Get<typename std::enable_if<std::is_same<Arg, double>::value>::type, Arg> {
using type = int;
};
同样,这匹配Get<void, double>
.
专业化是模式匹配。新加坡金融学会enable_if
子句不能进行模式匹配。所以模式匹配运行,然后enable_if
条款进行评估。如果失败,则专业化不匹配。如果他们成功了,enable_if
子句产生一个类型。生成所有类型(模式和非模式)后,生成的类型列表要么匹配,要么不匹配。
使用此机制的简单方法包括将公共版本转发到详细版本,通过void
作为第一种类型,并做你的enable_if
在那里工作。
另一种方法是将类型捆绑到类型列表中,例如template<class...>struct types{};
,并将其作为一个参数传递,并且void
作为第二个参数,然后再次执行 SFINAEvoid
.
这是一个例子:
namespace details {
template<class...>struct types{};
template<class Types, class=void>
struct foo;
template<class T0, class... Ts>
struct foo<types<T0, Ts...>,typename std::enable_if<
std::is_same<T0, int>::value && (sizeof...(Ts)>=1)
>> {
using type=double;
};
}
template<class T0, class... Ts>
struct foo:details::foo< details::types<T0, Ts...> >{};
专业化details::foo
模式匹配types
捆。它的作用是enable_if
与这些模式匹配类型的逻辑。这enable_if
当且仅当第一个类型是int
并且有 1 种或多种附加类型(用于任意一组测试)。