这个模板构造是什么

What is this template construct?

本文关键字:是什么      更新时间:2023-10-16

这来自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后面的尖括号使它看起来像一个特殊化。但是,它并没有指定专门化模板的完整或部分类型,而是多次重复模板参数。

我想我以前没见过。它是什么?

更新

我们都清楚,专门化适用于模板的实例化,其中两个模板参数都是相同类型的,但我不清楚这是构成完全专门化还是部分专门化,也不清楚为什么。

当所有模板参数都是显式提供的或由默认参数提供的,并且完全按照提供的方式用于实例化模板时,我认为专业化是完全专业化,相反,专业化是部分的,如果不是所有模板参数是必需的,因为专业化提供了一个或多个(但不是全部)模板参数,和/或模板参数是否以被专门化模式修改的形式使用。例如

一个部分的专门化,因为该专门化提供了至少一个(而不是全部)模板参数。

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<char*&GT;则模板中的T实际上是char类型,即所提供的模板参数仅部分由于专用化模式的应用而被使用。

如果这是正确的,那么这难道不会使原始问题中的模板成为完全专业化而不是部分专业化吗?如果不是这样,那么我的误解在哪里?

当为两个参数传递相同类型时,它是部分类模板专用化。

也许这会更容易阅读:

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

以下任何一项的明确专业化:

[…]

可以通过CCD_ 1引入的声明来声明;即:

显式专业化:
template < >声明

和n3337,14.5.5/1

主类模板声明是指类模板名称是一个标识符。模板声明,其中类模板名称是简单模板id是分部simple-template-id中命名的类模板的专门化[…]

其中简单模板id在语法中定义如下:

简单模板id:

模板名称<模板参数列表opt>

模板名称

标识符

所以,无论哪里有template<>,它都是完全专业化,其他任何东西都是部分专业化。

您也可以这样想:完全模板专门化专门用于主模板的一个可能的实例化。其他任何事情都是部分专业化。您问题中的示例是部分专门化,因为尽管它限制了参数的类型相同,但它仍然允许模板实例化有无限多个不同的参数。

像这样的专业化,例如

template<>
vector<bool> { /* ... */ };

是完全专业化,因为它在类型为bool且仅为bool时生效。

希望能有所帮助。


我觉得这是值得一提的。我想你已经知道了——函数模板不能局部专业化。而这个

template<typename T>
void foo(T);
template<typename T>
void foo(T*);

乍一看,foo可能是指针的部分专用化,但事实并非如此——这是一个重载。

您提到在执行模板的专门化时指定"完整或部分类型",这表明您知道类模板的局部专门化等语言功能。

部分专业化具有相当广泛的功能。它并不局限于简单地为一些模板参数指定具体的参数。它还允许为某些参数类型组定义专用版本的模板,基于它们的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

现在,返回到您的代码示例,两个相同参数的部分专用化正是您发布的代码中使用的。