理解模板部分专门化

Understanding Template Partial Specialization

本文关键字:专门化 板部      更新时间:2023-10-16

我试图理解模板部分专门化的概念。然而,我似乎把它与模板专门化混淆了。我正在考虑以下两个例子

template <typename T> 
struct test
{
   ///Some stuff
};
template <> //Specialization
struct test<int*>
{
   ///Some stuff
};

template<typename t> //Partial specialization
struct test<t*>
{
   ///Some stuff
};

我正在尝试下面的

test<int*> s;

,这调用专门化模板。如何调用部分专门化类。有没有人可以用一个例子来解释局部模板和专门化模板的区别?

更新:

在浏览了答案之后,我意识到部分模板专门化只有在需要专门化参数子集时才有帮助。所以我试着这样写

template <>
struct test<int*>
{
};

//Partial Specialized
template<typename t>
struct test<t, std::string>
{
};
test<int*,std::string> s;  //Error : Too many arguments for class template

在讨论类模板时:

  • 显式(完整)专门化:指定所有模板参数
  • 部分专门化:通过只指定模板参数的子集来定制模板

三种情况的例子:

#include <iostream>
template<typename T, typename U> //Primary template
struct test
{
   void foo() { std::cout << "nPrimary"; }
};
template <typename T> //Specialization
struct test<T, int*>
{
   void foo() { std::cout << "nPartial Specialization"; }
};

template<> //Full specialization
struct test<int*, int*>
{
   void foo() { std::cout << "nFull Specialization"; }
};
int main()
{
    test<int, double> t1;
    t1.foo();
    
    test<double, int*> t2;
    t2.foo();
    
    test<int*, int*> t3;
    t3.foo();
}
输出:

主要

局部特殊化

完整的专业化

现场演示。


回复你的更新:

  • 模板专门化不能添加参数,它只能专门化已有的参数

部分专门化可以达到两种效果:

一,你可以将一个或多个模板参数"固定"为具体的值,同时保持其他的"未绑定"。下面是一个例子:

template <class A, class B>
struct Foo  // The primary template
{
  static const int i = 0;
};
template <class A>
struct Foo<A, int>  // Partial specialisation which "fixes" B
{
  static const int i = 1;
};
template <>
struct Foo<char, int>  // Full specialisation
{
  static const int i = 2;
};
int main()
{
  std::cout << Foo<char, double>::i;  // 0
  std::cout << Foo<double, int>::i << Foo<void, int>::i;  // 11
  std::cout << Foo<char, int>::i;  //2
}
第二,您可以为模板提供一个更具体版本(仍然是通用的)模板参数的替代定义:
template <class A>
struct Bar  // Primary template
{
  static const int i = 0;
};
template <class A>
struct Bar<A*>  // Patrial specialisation for pointers
{
  static const int i = 1;
};
template <>
struct Bar<int*>  // Full specialisation
{
  static const int i = 2;
};
int main()
{
  std::cout << Bar<int>::i;  // 0
  std::cout << Bar<void*>::i << Bar<int**>::i;  // 11
  std::cout << Bar<int*>::i;  // 2
}

这正是你的原始代码所做的。

当然你也可以将两者结合起来,像这样:

template <class A>
struct Foo<std::vector<A>, int>  // Partial specialisation of primary Foo from above, for any std::vector and an int
{
  static const int i = 3;
};

这是个模板:

tempalte <typename A, typename B>
class Foo {};

你可以专门化它:

template <>
class Foo<int, int> {};

你也可以让其中一个参数自由(部分专门化):

template <typename B>
class Foo<std::string, B> {};

看看这个关于模板专门化的链接。

template <>

将是您处理特定类型的方式,而

template<typename t> //Partial specialization
struct test<t*>

是处理泛型类型的方式。当然可以

test<int*> s;

调用专门化模板,因为这是您在上面指定的。若要调用部分专门化,请使用模板的任何其他类型调用。例如

test<char*> s;