C++ - 模板特化与偏特化

4

我在互联网和stackoverflow上寻找了很久,但似乎找不到一个具体的答案。我需要创建一个通用类,然后实现特定的函数。我的具体指令是:您需要使用模板表达式参数、模板类特化和部分特化。

我有一个模板类:

template <class T, int x, int y>
class Z {
    T **array[x][y];
    public:
         Z();
         void print();
         //and other methods
};

我需要做以下的事情:

1)只有当X=2且Y=2时,Z才需要有一个公共方法void J()

2)对于X=2且Y=2的char Z,J将执行某些操作;而对于其他所有内容,它将执行其他操作

3)仅对于T为char的Z,数组才会被初始化为某个值。对于其他所有内容,它都是0

显然,这是有效的:

template<class T, int x, int y>
Z<T,x,y>::Z<T,x,y>() { //initialize to 0 } 

但是这个不行:
template<int x, int y>
Z<char,x,y>::Z<char,x,y>() { //initialize to something}

同样地(假设 J 存在),这个也不起作用:

template <class T>
void Z<T,2,2>::J() { //something }

我的问题是:

有没有一种简单的方法来实现上述项目?我需要保留Z中的所有其他方法。给出一些提示或指向正确方向的建议(也许我错过了某个问题,因为有很多问题),这将会很有帮助。

谢谢。


你有哪些错误?J是什么?不清楚你想做什么。 - Synxis
J是某个函数。我需要做的事情列在1、2、3中。我的错误是(下一个注释): - aoi
对于Z<char,x,y>::Z<char,x,y>() { //stuff },出现了“在'<'标记之前期望构造函数、析构函数或类型转换”和“在'<'标记之前期望';'”的错误提示。 - aoi
假设J存在:void Z<char,x,y>::J() {//stuff} 会产生以下错误:"invalid use of undefined type class Z<char, x, y>'" 和 "template definition of non-template void Z<char, x, y>::J()' " - aoi
2个回答

5

看起来您只想定义某些特化函数:如果在char特化和通用情况下print()没有改变,那么您似乎不想重新定义它。

// What you want to do (illegal in C++)
template<int,typename T>
struct Z
{
    T myValue;
    Z();
    void print() { /* ... */ }
};

template<int i, typename T>
Z<i,T>::Z() { /* ... */ }

template<int i>
Z<i,char>::Z() { /* ... */ }

然而,它并不是这样工作的。类的部分或完全特化几乎没有什么共同之处,除了模板参数的“原型”:
// The two following types have only two things related: the template parameter is an int,
// and the second type is a full specialization of the first. There are no relations between
// the content of these 2 types.
template<int> struct A {};
template<> struct A<42> { void work(); };

每个(部分)特化都需要声明和定义:

// Fixed example
template<int,typename T>
struct Z
{
    T myValue;
    Z();
    void print() { /* ... */ }
};
template<int i, typename T>
Z<i,T>::Z() { /* ... */ }

// Specialization for <all-ints,char>
template<int i>
struct Z<i,char>
{
    char myValue;
    char othervalue;
    Z();
    void print() { /* Same code than for the general case */ }
};

template<int i>
Z<i,char>::Z() { /* ... */ }

避免代码重复的唯一方法是使用特质的继承:

// Example with the print function
template<typename T>
struct print_helper
{
    void print() { /* ... */ }
};

// Fixed example
template<int,typename T>
struct Z : public print_helper<T>
{
    T myValue;
    Z();
};
template<int i, typename T>
Z<i,T>::Z() { /* ... */ }

// Specialization for <all-ints,char>
template<int i>
struct Z<i,char> : public print_helper<char>
{
    char myValue;
    char othervalue;
    Z();
};

template<int i>
Z<i,char>::Z() { /* ... */ }

目前,如果没有重复,您无法做到自己想要的(删除代码重复的功能是使用static if实现的,并已被提议列入下一个C++标准,请参见n3322n3329)。


是的,我知道这一点。但我想知道是否有更简单的方法来完成这个任务,而不需要在各个地方复制代码。(因为显然那是非常糟糕的事情) - aoi
那不是继承,因为您仍然必须在解决方案的每个地方复制代码(与以前相同)。无论如何,我会尝试让一些继承起作用。 - aoi

0

你可以查看这门课程http://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Core-C-/Stephan-T-Lavavej-Core-C-5-of-N

虽然不可能为函数模板定义偏特化,但是你可以为类或结构体模板定义偏特化。

template<typename T> struct helper {
    static void doThingy(){}
};

template<typename X> struct helper<X*> {
    static void doThingy(){}
};

Helper(double*)::doThingy();

在这个例子中,当模板中的类型是指针类型时,您想要专门定制doThingy()的行为。在这种情况下,您无法使用doThingy()方法的重载,因为您不能重载没有参数的函数。但是您可以对helper结构进行部分特化。在专门的模板中,您可以实现doThingy()所需的行为。

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