嵌套 class 的部分专业化
Partial specialization of a nested class
如何在不部分特化 nesting class 的情况下部分特化 nested 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;
...
};
通过重新声明迭代器class,你可以得到相同的结果。
template<class T, int N>
class C
{
class iterator {};
};
template<class T>
class C<T, 1>
{
class iterator {};
};
它应该与class的公共工作部分分开。 (除非你想重写它)
template<class T>
class CWork
{
};
template<class T, int N>
class C : public CWork<T>
{
class iterator {};
};
template<class T>
class C<T, 1> : public CWorkDefine
{
class iterator {};
};
原因是:
template<class T>
class C<T, 1>::iterator {
// ...
}
尝试成为成员 class iterator
在 C
的偏特化上的定义,其中不存在这样的偏特化。如果您使用非静态数据成员、成员函数或成员模板尝试此操作,则会发生完全相同的问题:C++ 不允许部分特化,其中只有外部 class 是部分特化的。
例如这样编译:
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)`)
如何在不部分特化 nesting class 的情况下部分特化 nested 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;
...
};
通过重新声明迭代器class,你可以得到相同的结果。
template<class T, int N>
class C
{
class iterator {};
};
template<class T>
class C<T, 1>
{
class iterator {};
};
它应该与class的公共工作部分分开。 (除非你想重写它)
template<class T>
class CWork
{
};
template<class T, int N>
class C : public CWork<T>
{
class iterator {};
};
template<class T>
class C<T, 1> : public CWorkDefine
{
class iterator {};
};
原因是:
template<class T>
class C<T, 1>::iterator {
// ...
}
尝试成为成员 class iterator
在 C
的偏特化上的定义,其中不存在这样的偏特化。如果您使用非静态数据成员、成员函数或成员模板尝试此操作,则会发生完全相同的问题:C++ 不允许部分特化,其中只有外部 class 是部分特化的。
例如这样编译:
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)`)