简化 API 的 类 通过 CRTP 相互扩展

Simplifying API of classes extending each other by CRTP

我想写 class 扩展多个 classes by (CRTP).

我只能Extension<Base<Extension>> my_object;工作。

我想要的api是:Extension<Base> my_object;

如何使这个 api 工作?

谢谢。

测试(代码也在godbolt.org):

#include <iostream>

template <template<typename...> class Extension>
class Base1 : public Extension<Base1<Extension>> {
public:
    static void beep() { std::cout << "Base1 "; }
};

template <class Plugin>
class Extension1 {
public:
    Extension1() : plugin_(static_cast<Plugin*>(this)) {}
    void beep() {
        plugin_->beep();
        std::cout << "Extension1\n";
    }
private:
    Plugin* plugin_;
};

template <template<typename...> class Plugin>
class Extension2 {
public:
    Extension2() : plugin_(static_cast<Plugin<Extension2>*>(this)) {}
    void beep() {
        plugin_->beep();
        std::cout << "Extension2\n";
    }
private:
    Plugin<Extension2>* plugin_;
};

int main() {
    // This works.
    Extension1<Base1<Extension1>>b;
    b.beep();
    // This doesn't work.
    Extension2<Base1> c;
    c.beep();
    return 0;
}

一个问题是 Extension2 的模板参数与 Base1 的签名不匹配。另一个是 Extension2Base1 期望的参数类型不匹配。

如果将Extension2的定义改为适当地接受Base1,它本身仍然不是要传递给Base1的候选者。您可以使用符合 Base1 预期的内部模板 class 解决此问题。这个内部 class 看起来很像 Extension1.

template <template<template<typename...> class> class Plugin>
class Extension2 {
    template <class P>
    struct Inner {
        Inner () : plugin_(static_cast<P *>(this)) {}
        void beep() { plugin_->beep(); }
    private:
        P* plugin_;
    };
public:
    Extension2() {}
    void beep() {
        plugin_.beep();
        std::cout << "Extension2\n";
    }
private:
    Inner<Plugin<Inner>> plugin_;
};