理解模板偏特化

3

我正在努力理解模板的偏特化概念。然而,我似乎将其与模板特化混淆了。我考虑了以下两个例子:

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

为什么会这样呢?

不,部分特化是指您提供了一般模板的另一个实现,明确地说明一个或多个类型。这不是您在此处所做的。您所评论的部分特化实际上就是一般模板。 - Stephane Rolland
4个回答

5
简言之,谈到类模板时:

三种情况的示例:

#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 <> - Rajeshwar
@Rajeshwar,评论是错误的,代码是正确的(请参见实时演示)。 - quantdev
@Rajeshwar 不是的,这就是我的回答要表达的意思。部分特化只指定一些参数,而完全特化(template<>)则指定所有参数。希望能有所帮助。 - quantdev
我刚刚更新了我的问题。您能否更新您的答案? - Rajeshwar
你可以使用 template<class U> myclass<std::vector<U>>{}; 部分特化 template<class T> myclass{};,因此最后一句话是错误的。 - pqnet

2

使用部分特化可以达到两个效果。

第一,您可以将一个或多个模板参数固定为具体值,同时保持其他参数“未绑定”。以下是一个示例:

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;
};

在最后一个例子中,主模板必须有两个参数才对吗? - Rajeshwar
@Rajeshwar 是的,我在使用我回答中第一部分的 Foo - Angew is no longer proud of SO

1

This is a template:

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

而且您可以进行专门化:

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

你也可以将参数保留为空(部分特化):
template <typename B>
class Foo<std::string, B> {};

0

请查看此链接,了解有关模板特化的信息。

template <>

这将是你处理特定类型的方式,同时

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

这是关于如何处理泛型类型的。当然了。

test<int*> s;

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

test<char*> s;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接