2012-04-18 31 views
2

我有一個表示數值數組的模板類。我希望這個類適用於任何類型的數值(如int,double等)和三種類型的容器(std :: vector,std :: deque和std :: list)。模板類中函數的部分特化

下面是執行中的相關內容對我的具體問題:

template < typename Numeric_t, typename Container = std::vector<Numeric_t> > 
class Array { 

    // field member 
    Container m_data; 

    // other stuff here 
    // ... 

    // random element access for std::vector and std::deque 
    Numeric_t & operator[] (unsigned int index) { return m_data[index]; } 

    // random element access for std::list 
    Numeric_t & operator [] (unsigned int index) { 
    std::list<Numeric_t> :: iterator it = m_data.begin(); 
    std::advance(it, index); 
    return *it; 
    } 

} 

當然,編譯器不允許我重載運營商[]

我需要的是針對std :: list的運算符[]的一種部分特化,但在C++中不允許部分模板函數專門化。

(我知道隨機元素訪問對列表來說效率不高,但這不是重點)。

理想的情況下,在客戶端代碼中,我想用Array類是這樣的:

Array < int, std::vector<int> > vec; 
Array < int, std::list<int> > lst; 

// fill arrays here 
// ... 

std::cout << vec[0] << std::endl; 
std::cout << lst[0] << std::endl; 

大量的研究後,我沒能找到一個有效的解決方案。

什麼是最優雅的方式來解決這個問題?

感謝您的幫助。

+0

我認爲你的意思是'覆蓋',而不是'超載'......但我認爲你需要整個'Array'類專業化的情況下,'容器'是一個'列表'的情況。 – sje397 2012-04-18 06:40:40

+0

您是否嘗試爲整個班級寫作專業化?如果你的代碼不是特定於模板類型的,你可以編寫一個模板基類,並讓你的特定類繼承該基類。 – smichak 2012-04-18 06:44:52

+0

我們對此已有一個常見問題解答 – 2012-04-18 08:51:17

回答

1

乾淨的解決方案是使用完整的模板專業化。不同的專業化可以從一個共同的基類派生,以便共享通用的代碼。

編寫一個類ArrayBase,其中包含所有不依賴於特定容器類型的代碼,並通過使其受到保護或使Array成爲朋友類來授予對容器的訪問權限。

template <class Numeric_t, class Container> 
class Array 
    : public ArrayBase<Numeric_t, Container> 
{ 
    // Container specific code, generic version that works for all containers. 
}; 

template <class Numeric_t> 
class Array<Numeric_t, std::vector<Numeric_t>> 
    : public ArrayBase<Numeric_t, std::vector<Numeric_t>> 
{ 
    // Optimized code for std::vector. 
} 

另一種方法:你也可以寫一個靜態成員函數包含代碼來訪問容器的 idx個條目,並專門該功能:

template <class Numeric_t, class Container> 
class Array 
{ 
    template <class Cont> 
    static Numeric_t get(Cont const& container, unsigned int idx) 
    { 
    std::list<Numeric_t>::iterator it = container.begin(); 
    std::advance(it, idx); 
    return *it; 
    } 

    template <> 
    static Numeric_t get(std::vector<Numeric_t> const& container, unsigned int idx) 
    { 
    return container[idx]; 
    } 

    public: 
    Numeric_t operator[](unsigned int idx) const { return get(m_data, idx); } 
}; 

我對不起,這不起作用。我忘了你不能再專門化靜態成員函數。

另一種選擇是使用SFINAE,但它是非慣用的使用它,我不會在這種情況下推薦它。

+0

非常感謝。解決方案1可能更乾淨,但解決方案2是我現在正在尋找的。但是,我必須在函數聲明前添加'static'關鍵字,並在'get'函數的第二個定義中將'template <>''更改爲'template '。此外,我想知道這種方法是否會對基於std :: vector的Array與原始實現相比的性能產生一些影響。 – kokozul 2012-04-18 11:25:11

相關問題