簡體   English   中英

嵌套 class 的部分特化

[英]Partial specialization of a nested class

如何在不部分專門化嵌套class的情況下部分專門化嵌套class

class C的實現對於所有N都是相同的。

C::iterator的實現對於N=1是特殊的。

template<class T, int N>
class C
{
    class iterator;
    ...
};

template<class T, int N>
class C<T, N>::iterator
{
    ...
};

// Partial specialization doesn't compile:
template<class T>
class C<T, 1>::iterator
{
    ...
};

我可以class C部分專業化為N=1 ,但這是很多代碼重復......

如果您不想專門化整個 class 則只需將迭代器移出 class 並將其設為模板:

template<class T, int N>
class C_iterator
{
    ...
};

如果需要,使您的專業化:

template<class T>
class C_iterator<T, 1>
{
    ...
};

然后在您的 class 中使用它作為迭代器,如果需要,請與它成為朋友:

template<class T, int N>
class C
{
    using iterator = C_iterator<T, N>;
    friend iterator;
    ...
};

原因是:

template<class T>
class C<T, 1>::iterator {
    // ...
}

嘗試成為 C 的部分特化的成員C iterator的定義,其中不存在這樣的部分特化。 如果您使用非靜態數據成員、成員 function 或成員模板嘗試此操作,則會發生完全相同的問題:C++ 不允許部分特化,其中只有外部 ZA2F2ED4F8EBC2CBB4C21A29DC40AB6 是特化的。

例如,這編譯:

template<class T, int N>
class C {
    class iterator;  // (A)
};

template<class T>
class C<T, 1> {
    class iterator;  // (B)
};

template<class T, int N>
class C<T, N>::iterator {};  // Definition for entity declared at (A)

template<class T>
class C<T, 1>::iterator {};  // Definition for entity declared at (B)  *not a partial template specialisation

而在 (B) 附近沒有偏特化,則第二個定義沒有任何定義。 作為一般的經驗法則,部分特化只能引用最里面的實體,所以它必須是一個模板。

(請注意,這與實體iterator的類型無關:如果iterator是模板 class 並且您嘗試基於N=1對其進行部分專門化,則會發生同樣的問題)


所以最簡單的答案是:你不能完全做你想做的事。

最簡單的解決方案是 Öö Tiib 的回答是:將 class 取出並使iterator成為成員類型別名。

為了好玩,您可以將iterator設為模板 class 以便您可以對其進行部分專門化。 您仍然不能僅部分專門化外部 class ,因此我使用約束來模擬它:

template<class T, int N>
class C
{
    template<std::nullptr_t = nullptr>
    class iterator;
};

template<class T, int N>
template<std::nullptr_t>
class C<T, N>::iterator
{
};

template<class T, int N>
template<std::nullptr_t dummy> requires (N==1)
class C<T, N>::iterator<dummy>
{
};

// The first is a primary definition, the second a partial specialisation
// (Could have also made them both partial specialisations, with the first `requires (N!=1)`)

通過重新聲明迭代器 class,可以得到相同的結果。

template<class T, int N>
class C
{
    class iterator {};
};

template<class T>
class C<T, 1>
{
    class iterator {};
};

它應與 class 的常用工作部分分開。 (除非你想重寫它)

class CWorkDefine
{
    void func() {};
};

template<class T, int N>
class C : public CWorkDefine
{
    class iterator {};
};

template<class T>
class C<T, 1> : public CWorkDefine
{
    class iterator {};
};

下面的代碼用於測試。

template<class T, int N>
class C
{
public:
    class iterator {};
};

// Partial specialization doesn't compile:
template<class T>
class C<T, 1>
{
public:
    class iterator { public: bool specialization; };
};

void test()
{
    C<int, 2>::iterator
    {
        
    };

    C<int, 1>::iterator
    {
        .specialization = true
    };
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM