【问题标题】:Partial specialization of a nested class嵌套类的部分特化
【发布时间】:2022-01-21 13:28:22
【问题描述】:

如何在不部分特化嵌套ing类的情况下部分特化嵌套ed类?

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,但这是很多代码重复...

【问题讨论】:

  • 在您的实际代码中,iterator 中的 C 是不是像这里一样的非模板?如果是这样,那是你的问题。 iterator 需要是模板才能对其进行专门化。
  • 你想部分特化迭代器,但迭代器不是模板。部分专门化不是模板的东西没有多大意义。专业化 C 是有意义的,因为它是模板。
  • 所以您试图根据非类型模板参数N 的值来提供iterator 的不同定义?
  • @WBuck 是的,正如上面的人所说,iterator 本身如果不是模板类。所以我看到错误来自哪里。尽管如此,为N=1 复制class C 代码是很烦人的。

标签: c++ templates


【解决方案1】:

如果您不想专门化整个类,那么只需将迭代器移出类并使其成为模板:

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

如果需要,让您的专业化:

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

然后在你的类中使用它作为迭代器,如果需要的话和它成为朋友:

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

【讨论】:

  • 喜欢,好看又简单。
【解决方案2】:

原因是:

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

尝试在 C 的部分特化上定义成员类 iterator,其中不存在这样的部分特化。如果您尝试使用非静态数据成员、成员函数或成员模板进行此操作,则会发生完全相同的问题:C++ 不允许仅部分特化外部类的部分特化。

例如,这样编译:

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 是一个模板类并且您尝试基于N=1 对其进行部分特化,则会发生同样的问题)


所以最简单的答案是:你不能完全按照自己的意愿去做。

最简单的解决方案是 Öö Tiib 的回答是:将类提升出来并将 iterator 设为成员类型别名。

为了好玩,您可以将iterator 设为模板类,这样您就可以对其进行部分专门化。你仍然不能只对外部类进行部分特化,所以我使用约束来模拟它:

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)`)

【讨论】:

  • 感谢@Artyer 的详细解释。选择 Öö Tiib's 作为主要答案。给你+1
【解决方案3】:

通过重新声明迭代器类,可以得到同样的结果。

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

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

它应该与类的公共工作部分分开。 (除非你想重写)

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-27
    • 2013-06-12
    • 1970-01-01
    • 1970-01-01
    • 2012-02-26
    • 2016-01-11
    • 1970-01-01
    • 2011-02-02
    相关资源
    最近更新 更多