简体   繁体   English

嵌套 class 的部分特化

[英]Partial specialization of a nested class

How to partially specialize nest ed class without partially specializing the nest ing class?如何在不部分专门化嵌套class的情况下部分专门化嵌套class

Implementation of class C is the same for all N . class C的实现对于所有N都是相同的。

Implementation of C::iterator is special for N=1 . 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
{
    ...
};

I can partially specialize class C for N=1 , but that's a lot of code duplication...我可以class C部分专业化为N=1 ,但这是很多代码重复......

If you do not want to specialize whole class then just move the iterator out of class and make it template:如果您不想专门化整个 class 则只需将迭代器移出 class 并将其设为模板:

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

If needed make your specializations:如果需要,使您的专业化:

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

Then use it in your class as iterator, if needed befriend it:然后在您的 class 中使用它作为迭代器,如果需要,请与它成为朋友:

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

The reason is that:原因是:

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

Attempts to be the definition for a member class iterator on a partial specialisation for C , where no such partial specialisation exists.尝试成为 C 的部分特化的成员C iterator的定义,其中不存在这样的部分特化。 The exact same issue would happen if you tried this with a non-static data member, a member function, or a member template: C++ does not allow partial specialisations where only the outer class is partially specialised.如果您使用非静态数据成员、成员 function 或成员模板尝试此操作,则会发生完全相同的问题:C++ 不允许部分特化,其中只有外部 ZA2F2ED4F8EBC2CBB4C21A29DC40AB6 是特化的。

For example, this compiles:例如,这编译:

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

Whereas without the partial specialisation near (B), there is nothing for the second definition to define.而在 (B) 附近没有偏特化,则第二个定义没有任何定义。 As a general rule of thumb, a partial specialisation can only refer to the innermost entity, so it must be a template.作为一般的经验法则,部分特化只能引用最里面的实体,所以它必须是一个模板。

(Note this has nothing to do with what kind of entity iterator is: The same issue would have happened if iterator was a template class and you try to partially specialise it based on N=1 ) (请注意,这与实体iterator的类型无关:如果iterator是模板 class 并且您尝试基于N=1对其进行部分专门化,则会发生同样的问题)


So the simplest answer is: you can't do exactly what you want to do.所以最简单的答案是:你不能完全做你想做的事。

The simplest solution is what Öö Tiib's answer is: Lift the class out and make iterator a member type alias.最简单的解决方案是 Öö Tiib 的回答是:将 class 取出并使iterator成为成员类型别名。

For fun, you could make iterator a template class so you can partially specialise it.为了好玩,您可以将iterator设为模板 class 以便您可以对其进行部分专门化。 You still can't partially specialise the outer class only, so I use a constraint to emulate it:您仍然不能仅部分专门化外部 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)`)

By re declare the iterator class, You can get the same result.通过重新声明迭代器 class,可以得到相同的结果。

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

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

It should be separated from the common working part of the class.它应与 class 的常用工作部分分开。 (unless you want to rewrite it) (除非你想重写它)

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 {};
};

The code below is for testing.下面的代码用于测试。

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