История изменений
Исправление 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-ах, сортировать их и т.п., так что может быть и можно.