2017-10-05 84 views
1

我想我只是缺少一些小東西。我想爲T =具有任何參數的模板類的實現專門化模板類的構造函數。對不起,如果我的單詞有點關閉。 基本上,我需要允許鋸齒狀的二維數組,所以我可能有一個ArEl<ArEl<int>>,我想預先初始化所有數組長度。如何在部分類模板專業化中實現繼承?

using namespace std; 

template <typename T> 
class ArEl { 
public: 
    ArEl(size_t size = 0) 
     : rSize(size), rArray(rSize ? new T[rSize]() : nullptr) {} 
    ArEl(const ArEl& other); 
    virtual ~ArEl() { delete[] rArray; } 
    void swap(ArEl& first, ArEl& second); 
    void redim(size_t size); 

private: 
    std::size_t rSize; 
    T* rArray; 
}; 

template <typename T, typename T1> 
class ArEl<ArEl<T>> : public ArEl<T1>{ 
    ArEl(size_t size = 0); 
}; 

編輯:

我得到這個錯誤:

error: template parameters not deducible in partial specialization: 
class ArEl<ArEl<T>> : public ArEl<T1>{ 

回答

4

你專注你的對象在錯誤的道路。

template<typename T, typename T1>意味着需要提供兩種數據類型,但很明顯,您的模板專業化需要的唯一東西就是基礎數組的數據類型。如果期望是ArEl<ArEl<T>>專業化,它不應該比這更多:

template<typename T> 
class ArEl<ArEl<T>> { 
    /*Blah Blah Blah*/ 
}; 

有沒有需要繼承,也沒有必要進行第二次數據類型。

不過,我還要補充一句:這個專業化沒有任何必要。如果你不寫專業化可言,下面的代碼仍然將正常運行,是:

ArEl<ArEl<int>> dim2Array(50); 
//I'm assuming ArEl will have a member size() function 
for(size_t index = 0; index < dim2Array.size(); index++) { 
    //I'm assuming ArEl will have an operator[] overload 
    dim2Array[index].redim(30); 
} 
//dim2Array is now 50 int arrays, each of size 30. 

我假設你打算的功能是有類似以下,這確實需要模板特像我上面貼:

ArEl<ArEl<int>> dim2Array(50, 30); 
//dim2Array is now 50 int arrays, each of size 30. 

但是,如果我是你,我會離開的ArEl實施單獨,轉而投向寫一個Matrix<T>類(或可能Matrix<T, N>,對於N維),處理這種語法代替(你可以使用ArEl<T>構建作爲構建基塊),尤其是因爲我不認爲你致力於編寫ArEl<ArEl<ArEl<int>>>或更深層次的專業化(並且是的,你嘗試這麼做的方式,每個層次都需要自己的專業化)。

3

專門化整個班級意味着使用專業化提供的成員替換所有成員。你不想那樣。

一種選擇是提供所有需要在基類中專業化的成員:BaseForA<T>將是專門的,並且A<T>將從它派生。

另一個問題是使用標籤分派,下面是一個如何根據類型參數使用它來執行不同操作的示例。

#include <iostream> 
#include <type_traits> 

template<typename T> 
struct tag {}; 

template<typename T> 
struct A 
{ 
private: 
    template<typename U> 
    A(std::size_t s, tag<A<U>>) 
    { 
     std::cout << "special constructor " << s << "\n"; 
    } 

    A(std::size_t s, ...) 
    { 
     std::cout << "general constructor " << s << "\n"; 
    } 
public: 
    A(std::size_t s = 0) : 
     A(s, tag<T>()) 
    { 

    } 
}; 

int main() 
{ 
    A<int> a; 
    A<A<int>> b; 
    A<A<long>> c; 
    A<long> d; 
} 

Live on Coliru

0

如果我理解正確你你想要的專業版繼承了通用版,然後加在它上面的東西。這裏的問題是你有一個專門的ArEl<ArEl<T>>,你不能請求它的通用版本。

解決方案是使通用版本和專用版本成爲不同的類型。

template<typename T, bool D=true> 
class ArEl { ... 

template<typename T> 
class ArEl<ArEl<T>>: 
    public ArEl<ArEl<T>, false> { ... 

但現在的問題是,ArEl<T, true>ArEl<T, false>無關和不兼容!

解決方案是爲他們引入一個通用的基類。

template<typename T> 
class ArElBase { 
    ... all functionality of ArEl 
}; 

template<typename T, bool D=true> 
class ArEl : public ArElBase<T> { 
    using ArElBase<T>::ArElBase; 
    // nothing more 
}; 

然後專業化,不變。

現在您可以使用ArElBase通過指針或引用傳遞對象,但使用ArEl自己聲明對象。