【问题标题】:CRTP pattern with variable Base具有可变基数的 CRTP 模式
【发布时间】:2021-08-09 21:12:14
【问题描述】:

假设有两个基类Base1Base2 需要CRTP 模式。

template <typename TDerived>
class Base1 {
};

template <typename TDerived>
class Base2 {
};

现在我想定义一个Derived 类,这样它就可以用一个基类“参数化”。 在 C++ 中定义它的正确方法是什么(如果重要的话是 C++17)?

下面是伪C++代码

template <template <typename> class TBase>
class Derived : public TBase<Derived<TBase>> {}; // Recursion problem here

实际上,这样的派生类是适用于任何基类的扩展。

【问题讨论】:

标签: c++ templates inheritance c++17


【解决方案1】:

来自您的评论:

我认为问题仍然存在。

考虑将您自己的伪代码提供给编译器(以及一些附加内容):

template <typename TDerived>
struct Base1 {
    auto get() const -> int {
        return static_cast<TDerived const*>(this)->a;
    }
};

template <typename TDerived>
struct Base2 {
    auto get() const -> int {
        return static_cast<TDerived const*>(this)->b;
    }
};

template <template<typename> typename TBase>
struct Derived : TBase<Derived<TBase>> {
    int a;
    int b;
};

auto main() -> int {
    auto b = Derived<Base1>{};

    b.a = 1;
    b.b = 2;

    return b.get();
}

Live example

如您所见,该模式对编译器来说没有问题。

现在我想定义一个派生类,这样它就可以用一个基类“参数化”。在 C++ 中定义它的正确方法是什么(如果重要的话,C++17)?

您在问题中发布的方式是正确的,并且一直有效到 C++98。


您似乎说这里存在递归问题,但实际上没有。

您有一个模板类Derived,其模板模板参数为Base1。编译器现在“知道”这种类型Derived&lt;Base1&gt;。但是,在到达} 之前,它是不完整的。

然后编译器会看到基址,即TBase&lt;something&gt;,即带有一些模板参数的Base1Base1 需要被实例化。 somethingDerived&lt;Base1&gt;,这是一个不完整的类型。

然后编译器用Derived&lt;Base1&gt; 实例化Base1。在此过程中,您不能以需要完整的方式使用Derived&lt;Base1&gt;

现在基类已经实例化并且是一个完整的类型,编译器完成实例化Derived&lt;Base1&gt;,现在完成了。

这里没有递归。

【讨论】:

  • 是的,你完全正确。我陈述了不存在的“递归”问题。非常感谢您的解释。我认为我对不完整类型的理解存在差距,这让我感到困惑并让我问了最初的问题。在此期间,我会更彻底地阅读您的答案。再次感谢您的详细解释。我会接受答案,如果需要,我可能会提出后续问题。
猜你喜欢
  • 2021-03-30
  • 1970-01-01
  • 1970-01-01
  • 2011-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-29
相关资源
最近更新 更多