LINUX.ORG.RU

История изменений

Исправление quasimoto, (текущая версия) :

#include <cstdio>

struct IApplyForce {
    virtual void ApplyForce() = 0;
};

struct IRotateObject {
    virtual void RotateObject() = 0;
};

struct ISetFriction {
    virtual void SetFriction() = 0;
};

template <class...>
struct IComb;

template <>
struct IComb<> {};

template <class T, class... Ts>
struct IComb<T, Ts...> : public T, public IComb<Ts...> {};

struct Engine1: public IComb<ISetFriction, IApplyForce, IRotateObject> {
    virtual void ApplyForce() { puts("Engine1::ApplyForce"); }
    virtual void RotateObject() { puts("Engine1::RotateObject"); }
    virtual void SetFriction() { puts("Engine1::SetFriction"); }
};

struct Engine2: public IComb<IApplyForce, IRotateObject> {
    virtual void ApplyForce() { puts("Engine2::ApplyForce"); }
    virtual void RotateObject() { puts("Engine2::RotateObject"); }
};

struct Engine3: public IComb<IApplyForce, ISetFriction> {
    virtual void ApplyForce() { puts("Engine3::ApplyForce"); }
    virtual void SetFriction() { puts("Engine3::SetFriction"); }
};

int main()
{
    IComb<IApplyForce, IRotateObject> *engine = new Engine1;
    engine->ApplyForce();
    engine->RotateObject();

    engine = new Engine2;
    engine->ApplyForce();
    engine->RotateObject();

    // engine = new Engine3;
}

это не полное решение, потому как с его помощью, например, для

struct ABCD: public IComb<A, B, C, D>;

генерируются следующие LSP-совместимые предки:

ABCD
IComb<A, B, C, D>
A
IComb<B, C, D>
B
IComb<C, D>
C
IComb<D>
D
IComb<>

а нам нужны все размещения. Можно ли с помощью template metaprogramming на variadic templates это сделать — не знаю. Александреску говорил что можно, например, делать slicы на parameter pack-ах, сортировать их и т.п., так что может быть и можно.

Исходная версия quasimoto, :

#include <cstdio>

struct IApplyForce {
    virtual void ApplyForce() = 0;
};

struct IRotateObject {
    virtual void RotateObject() = 0;
};

struct ISetFriction {
    virtual void SetFriction() = 0;
};

template <class...>
struct IComb;

template <>
struct IComb<> {};

template <class T, class... Ts>
struct IComb<T, Ts...> : public T, public IComb<Ts...> {};

struct Engine1: public IComb<ISetFriction, IApplyForce, IRotateObject> {
    virtual void ApplyForce() { puts("Engine1::ApplyForce"); }
    virtual void RotateObject() { puts("Engine1::RotateObject"); }
    virtual void SetFriction() { puts("Engine1::SetFriction"); }
};

struct Engine2: public IComb<IApplyForce, IRotateObject> {
    virtual void ApplyForce() { puts("Engine2::ApplyForce"); }
    virtual void RotateObject() { puts("Engine2::RotateObject"); }
};

struct Engine3: public IComb<IApplyForce, ISetFriction> {
    virtual void ApplyForce() { puts("Engine3::ApplyForce"); }
    virtual void SetFriction() { puts("Engine3::SetFriction"); }
};

int main()
{
    IComb<IApplyForce, IRotateObject> *engine = new Engine1;
    engine->ApplyForce();
    engine->RotateObject();

    engine = new Engine2;
    engine->ApplyForce();
    engine->RotateObject();

    // engine = new Engine3;
}

это не полное решение, потому как с его помощью, например, для

struct ABCD: public IComb<A, B, C, D>;

генерируются следующие LSP-совместимые предки:

ABCD
IComb<A, B, C, D>
A
IComb<B, C, D>
B
IComb<C, D>
C
IComb<D>
D
IComb<>

а нам нужны все размещения. Можно ли с помощью template metaprogramming на variadic templates это сделать — не знаю. Александреску, говорил что можно, например, делать slicы на parameter pack-ах, сортировать их и т.п., так что может быть и можно.