2011-09-22 212 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() {...}