Упрощение API классов, расширяющих друг друга с помощью CRTP - PullRequest
0 голосов
/ 06 мая 2018

Я хочу написать класс, который расширяет несколько классов на ( 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;
}

1 Ответ

0 голосов
/ 06 мая 2018

Одной из проблем является то, что параметр шаблона для Extension2 не соответствует сигнатуре, имеющейся у Base1. Другая причина в том, что Extension2 не соответствует типу параметра, ожидаемому Base1.

Если вы измените определение Extension2 для правильного принятия Base1, оно само по-прежнему не является кандидатом для передачи на Base1. Вы можете обойти это с внутренним классом шаблона, который соответствует тому, что ожидает Base1. Этот внутренний класс будет выглядеть так: 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_;
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...