这是来自VS2012附带的C ++标准库xutility头。
template<class _Elem1,
class _Elem2>
struct _Ptr_cat_helper
{ // determines pointer category, nonscalar by default
typedef _Nonscalar_ptr_iterator_tag type;
};
template<class _Elem>
struct _Ptr_cat_helper<_Elem, _Elem>
{ // determines pointer category, common type
typedef typename _If<is_scalar<_Elem>::value,
_Scalar_ptr_iterator_tag,
_Nonscalar_ptr_iterator_tag>::type type;
};
具体来说,第二个_Ptr_cat_helper声明的性质是什么?声明符_Ptr_cat_helper之后的尖括号使它看起来像一个特化。但是,不是指定专门用于模板的完整或部分类型,而是多次重复模板参数。
我认为我以前没见过。它是什么?
更新
我们都很清楚,专业化适用于模板的实例化,其中两个模板参数的类型相同,但我不清楚这是构成完全或部分特化,还是为什么。
我认为当所有模板参数显式提供或由默认参数提供时,专门化是完全特化,并且完全用于提供实例化模板,相反,如果不是全部,则专业化也是部分的由于提供了一个或多个(但不是全部)的特化,并且/或者模板参数是在由特化模式修改的形式中使用的,因此需要模板参数。 E.g。
部分专业化,因为专业化提供至少一个但不是全部的模板参数。
template<typename T, typename U>
class G { public: T Foo(T a, U b){ return a + b; }};
template<typename T>
class G<T, bool> { public: T Foo(T a, bool b){ return b ? ++a : a; }};
部分特化,因为特化导致提供的模板参数仅部分使用。
template<typename T>
class F { public: T Foo(T a){ return ++a; }};
template<typename T>
class F<T*> { public: T Foo(T* a){ return ++*a; }};
在第二个示例中,如果使用A&lt; char *&gt;实例化模板然后模板中的T实际上是char类型,即由于应用了特化模式,所提供的模板参数仅部分使用。
如果这是正确的,那么不会使原始问题中的模板成为完全专业化而不是部分专业化,如果不是这样,那么我的误解在哪里?
答案 0 :(得分:11)
对于两个参数传递相同类型的情况,它是一个部分类模板特化。
也许这会更容易阅读:
template<typename T, typename U>
struct is_same : std::false_type {};
template<typename T>
struct is_same<T,T> : std::true_type {};
修改强>
如果对专业化是明确的(完全)专业化还是部分专业化有疑问,可以参考这个问题非常明确的标准:
n3337,14.7.3./1
以下任何一项的明确专业化:
[...]
可以由
template<>
引入的声明声明;那就是:明确分工:
template < >
声明
和n3337,14.5.5 / 1
主类模板声明是类中的声明 模板名称是一个标识符。一个模板声明,其中 类模板名称是 simple-template-id 是部分名称 simple-template-id。 [...]
中命名的类模板的特化
其中 simple-template-id 在语法中定义如下:
简单模板id
template-name&lt; template-argument-list opt&gt;
模板名称
标识符
所以,无论哪里有template<>
,它都是完全专业化,其他任何东西都是部分专业化。
您也可以这样考虑:完全模板专门化专门用于主要模板的一个可能的实例化。其他任何东西都是部分专业化。您的问题中的示例是部分特化,因为虽然它将参数限制为相同类型,但它仍然允许模板可以实例化的无限多个不同参数。
像这样的专业化,例如
template<>
vector<bool> { /* ... */ };
是一个完整的专业化,因为它在类型为bool
且仅bool
时启动。
希望有所帮助。
只是一张纸条,我觉得值得一提。我想你已经知道了 - 功能模板不能局部专业化。虽然这个
template<typename T>
void foo(T);
template<typename T>
void foo(T*);
对于乍一看指针,可能看起来像是foo
的部分特化,它不是 - 它是一个过载。
答案 1 :(得分:5)
在执行模板专业化时,您提及指定“完整或部分类型”,这表明您已了解类模板的部分特化等语言功能。
部分专业化具有相当广泛的功能。它不仅限于为某些模板参数指定具体参数。它还允许根据cv资格或间接级别为某些参数类型组定义专用模板版本,如下例所示
template <typename A, typename B> struct S {};
// Main template
template <typename A, typename B> struct S<A *, B *> {};
// Specialization for two pointer types
template <typename A, typename B> struct S<const A, volatile B> {};
// Specialization for const-qualified type `A` and volatile-qualified type `B`
它还包括基于某些模板参数是相同还是不同的专业化
template <typename A> struct S<A, A> {};
// Specialization for two identical arguments
template <typename A> struct S<A, A *> {};
// Specialization for when the second type is a pointer to the first one
另一个相当古怪的例子,多参数模板的部分特化可以用来完全覆盖主模板
template <typename A, typename B> struct S<B, A> {};
// Specialization for all arguments
现在,返回到您的代码示例,两个相同参数的部分特化正是您发布的代码中使用的内容。