2011-09-22 121 views
0

我正在练习功能专业化,我试图用专门的打印功能创建一个小的存储对象。这里是我的代码:模板功能专业化,C++

#ifndef STORAGE_HPP_ 
#define STORAGE_HPP_ 

#include <iostream> 

using namespace std; 

template <typename T, int size> class Storage 
{ //LINE 16 ERROR 
public: 
    Storage():arr(new T*[size]){}; 
    ~Storage() 
    { 
     for (int i = 0; i < size; i++) 
     { 
      delete arr[i]; 
     } 
     delete[] arr; 
    } 
    void push(T obj, int i) 
    { 
     arr[i] = new T(obj); 
    } 
    void print() 
    { 
     for (int i = 0; i < size; i++) 
     { 
      cout << *arr[i]; 
     } 
     cout << endl; 
    } 


private: 
    T** arr; 
}; 

template <typename T, int size> void Storage<int,size>::print() //LINE 38 ERROR 
{ 
    for (int i = 0; i < size; i++) 
     { 
      cout << (char) *arr[i]; 
     } 
     cout << endl; 
} 
#endif /* STORAGE_HPP_ */ 

而且我得到这个错误:

../Storage.hpp:38:63: error: invalid use of incomplete type 
class Storage<int, size> 
../Storage.hpp:9:1: error: declaration of ‘class Storage<int, size>’ 

所以,第一个问题:可以专门的函数类内部实现的?我试过但得到一个错误。 其次,为什么我得到我附加的错误? 谢谢!

编辑:我尝试了一些新的东西,因为这里有人建议。我在课堂上打印的内容只有void print(),我已经在外面实现了,所以我可以重载这个函数。在这里:

template <typename T, int size> 
void Storage<T,size>::print() 
{ 
    for (int i = 0; i < size; i++) 
    { 
     cout << *arr[i]; 
    } 
    cout << endl; 
} 


template <typename T, int size> 
void Storage<int,size>::print() //ERROR HERE 
{ 
     for (int i = 0; i < size; i++) 
     { 
      cout << *arr[i]; 
     } 
     cout << endl; 
} 

现在,我得到invalid use of incomplete type ‘class Storage<int, size>’我在哪里写了错误的位置 我明白这是一个通用的解决方案,我在正确的(当然!)?为什么我会得到这个错误?

+0

我不知道,你可以做一个偏特 – Seb

+0

其他一切不谈,不应该'模板无效存储 ::打印()'是​​'模板 void存储 :: print()'? – Chad

+0

@查德:不,他试图做部分专业化。他想要的是'typename T'被删除。 – PlasmaHH

回答

3

的问题是,你正在试图使用整个类的部分特无需定义所述部分专门类。

如果print本身就是一个函数模板,情况将会不同,因为您确实可以专门化函数模板。但是,您的构建只将整个班级作为模板。

这意味着template <typename T, int n> class Storage<T, n>template <int n> class Storage<int, n>是完全不同的,无关的类。因此必须首先限定后一类:

template<int n> class Storage<int, n> 
{ 
    // define everything 
}; 

template<int n> void Storage<int, n>::print() { /* implement */ } 

认为部分特Storage<int, n>可以是从主模板完全不同的类,并且它可以具有完全不同的成员函数。直到您真正定义该类为止,编译器才知道这一点。


继SBI的评论,这里有一个想法:

//... in the class definition 

template<typename S, int m> friend void print_helper(const Storage<S, m> &); 
template<int m> friend void print_helper(const Storage<int, m> &); 

void print() { print_helper(*this); } 

// outside: 

template <typename S, int size> void print_helper(const Storage<S, size> & s) 
{ 
    // ... 
} 
template <int size> void print_helper(const Storage<int, size> & s) 
{ 
    // ... 
} 

取而代之的friend你也可以做辅助函数模板static,但可能会增添了不少代码膨胀,因为每个类类型都有两个静态函数模板,而不是全局两个。

+0

因此,要有不同的打印功能,我必须重新编写整个类,只将T更改为int(例如)?听起来像应该有一个更优雅的解决方案。在那儿? – yotamoo

+0

@yotamoo:一个常见的解决方案是将'Storage <> :: print()'作为一个自由函数模板的小包装器,可以在自由意志上专用/超载。 – sbi

+0

注意我的编辑,我试过你说的 – yotamoo

0

部分特殊化总是需要使用完整的模板,因为它们也定义了模板。

所以这是行不通的:

template <int size> void Storage<int,size>::print() 

成员职能的全部特可以做出来线单一成员函数的,因为它们定义的功能。

所以这会工作:

template <> void Storage<int,44>::print() 

而且你不能声明/主模板中定义的任何(部分)专业。

+0

功能模板没有部分专业化。 – sbi

+0

@sbi:没有涉及的功能模板。 – PlasmaHH

0

我不认为你可以在单一方法上使用部分专业化。你只能使用完整的专业化。

问题是:你为什么要使用一个指定大小的数组?为什么不使用std :: vector并让push()函数动态调整大小(使用std :: vector :: push_back())?

+0

我只是在练习使用模板.... – yotamoo

0

我能看到的唯一错误是你的专业化中无关的typename T。它应该是:

template <int size> void Storage<int,size>::print() {...}