是否有可能专注于一些(不是全部)类模板参数?

时间:2010-02-08 07:03:02

标签: c++ templates specialization

是否可以专注于某些(不是全部)类模板参数?

例如:

template <typename T, typename U>
class TC
{
public:
 void Foo();
};

template <typename T, typename U>
void TC<T, U>::Foo()
{

}

template <???, typename U>
void TC<int, U>::Foo()
{
  //Want this defined for all U but only when T is int.
}

int main(int argv, char * args [])
{
 TC<int, char> tc;
 return 0;
}

3 个答案:

答案 0 :(得分:3)

通常,您可以专门化一个类模板的一些模板参数,这称为“部分特化”。执行此操作时,您将创建一个新的专用版本的模板,该版本将“覆盖”常规版本。

在您的情况下,似乎您只想专门化模板的一部分Foo()方法,但这是不可能的。你必须专注于整个TC类:

// specialization for T=int
template <typename U>
class TC<int, U> {
public:
  void Foo();
};

// implementation of Foo() for the specialized template
template <typename U>
void TC<int, U>::Foo()
{
  //Want this defined for all U but only when T is int.
}

答案 1 :(得分:1)

对于课程,是的。对于函数,no和yes。

部分模板专业化适用于类,但对于全局函数来说,它有点棘手。

对于类,您只需省略模板参数列表中的专用参数并将其包含在类定义中:

// General template class for a vector
template <class T, int N>
struct Vector
{
  T e[N];
};

// Specialization for N=3
template <class T> // omit the N
struct Vector<T, 3> // and include it here
{
  T e[3];

  static Vector<T, 3> cross(const Vector<T, 3>& a, const Vector<T, 3>& b)
  {
    return Vector<T, 3>( a.e[1] * b.e[2] - a.e[2] * b.e[1],
                         a.e[2] * b.e[0] - a.e[0] * b.e[2],
                         a.e[0] * b.e[1] - a.e[1] * b.e[0] );

  }
};

对于全局功能,您不能这样做。您可以定义一个完全通用的功能,也可以完全专门化 - 不允许部分功能化。

但是,您可以通过将函数创建为部分专用类的静态函数的代理来部分地对函数进行特化。

e.g。

template <class A, class B>
void foo(A a, B b)
{
  foo_impl::fun(a, b);
}

template <class A, class B>
struct foo_impl
{
  static void fun(A a, B b)
  {
    // real implementation here
  }
};

然后,您可以以任何方式对foo_impl进行专门化,这将反映在foo中。

答案 2 :(得分:0)

如果您只希望专门化类的一部分,则需要原始类来提供钩子。它通常描述为TraitsPolicies,具体取决于实施。

Traits类是一个类,它引用给定类型的某些属性,有时是方法,并且不会显式传递。 STL中的一个示例是std::iterator_traits<It>

Policy类是作为模板参数传递的类,用于实现许多功能。 STL中的一个示例是std::less<int>中的std::set<int, std::less<int> >

一般来说,Policy类的使用是明确的,而Traits的使用是隐含的...因此我更喜欢前者到后者。

如果您的班级没有使用这些挂钩,请报告部分专业化的sth答案,并注意部分表示某些参数仍然是模板,而不是您只希望专门研究班级的一部分,因为你必须重新定义一切。