Рассмотрим этот код:
#include <iostream>
class Religion {
public:
virtual void pray() = 0;
};
// Example: Denomination<N0,N1,N2,N3> is derived from Denomination<N0,N1,N2> is derived
// from Denomination<N0,N1> is derived from Denomination<N0> is derived from Religion.
template <int...> class Denomination : public Religion {
virtual void pray() {std::cout << "Prays like a ... ?\n";}
};
template <> class Denomination<2> : public Religion {
virtual void pray() override {std::cout << "Prays like a Muslim.\n";}
};
template <> class Denomination<2,0> : public Denomination<2> {
virtual void pray() override {std::cout << "Prays like a Sunni Muslim.\n";}
};
template <> class Denomination<2,0,1> : public Denomination<2,5> {
virtual void pray() override {std::cout << "Prays like a Hanafi Sunni Muslim.\n";}
};
template <int...> struct D {};
class Person {
Religion* religion;
public:
template <int... Is>
Person (const D<Is...>&) : religion(new Denomination<Is...>) {}
// How to get the Flyweight Pattern here?
void pray() {religion->pray();}
};
int main() {
Person* person1 = new Person(D<2,0,1>{}); // "Prays like a Hanafi Sunni Muslim."Person* person2 = new Person(D<2,0>{}); // "Prays like a Sunni Muslim."Person* person3 = new Person(D<2>{}); // "Prays like a Muslim."person1->pray();
person2->pray();
person3->pray();
Person* person4 = new Person(D<2,5,6,2,1,3>{});
person4->pray(); // Should be "Prays like a Hanafi Sunni Muslim."}
Поэтому я хочу изменить Person
конструктор для
Person (const D<Is...>&) : religion(findDenomination<Is...>()) {}
который будет искать «таблицу» статических Religion*
s. В конце концов, 2 человека, принадлежащие к одной и той же конфессии, должны иметь одинаковые Religion*
значение. Так что я пытаюсь реализовать этот шаблон проектирования в навесном весе. Проблема в том, что мы не знаем долго Is...
pack — это (число под-sub -…- деноминаций нигде не зафиксировано), так что простой многомерный массив не будет работать, я не думаю. Поэтому вместо этого я размещаю статические константные векторы Religion*
S в соответствующих классах и Is...
Пакет будет использоваться, чтобы найти последний вектор для поиска.
Обновление: есть ли лучшие способы сделать это? Решение, которое я нашел до сих пор, имеет большой недостаток, если вы видите ниже.
Хорошо, я разработал почти полное решение. Person* person4 = new Person(D<2,0,1,2,1,3>{});
больше не работает, хотя Предполагается, что этот человек является подкатегорией суннитского мусульманина-ханафи, который по умолчанию должен молиться как суннитский мусульманин-ханафи из-за (преднамеренного) отсутствия переопределения для Denomination<2,0,1,2,1,3>
,
#include <iostream>
#include <vector>
#include <type_traits>
class Religion {
public:
virtual void pray() = 0;
};
template <int...> class Denomination : public Religion {
virtual void pray() {std::cout << "Prays like a ... ?\n";}
};
template <> class Denomination<0> : public Religion {
virtual void pray() override {std::cout << "Prays like a Christian.\n";}
};
template <> class Denomination<0,0> : public Denomination<0> {
virtual void pray() override {std::cout << "Prays like a Catholic.\n";}
};
template <> class Denomination<0,1> : public Denomination<0> {
virtual void pray() override {std::cout << "Prays like a Protestant.\n";}
};
template <> class Denomination<2> : public Religion {
virtual void pray() override {std::cout << "Prays like a Muslim.\n";}
};
template <> class Denomination<2,0> : public Denomination<2> {
virtual void pray() override {std::cout << "Prays like a Sunni Muslim.\n";}
};
template <> class Denomination<2,0,1> : public Denomination<2,5> {
virtual void pray() override {std::cout << "Prays like a Hanafi Sunni Muslim.\n";}
};
template <int...> struct ReligionDatabase;
template <> struct ReligionDatabase<> {
static const std::vector<Religion*> denominations;
};
const std::vector<Religion*> ReligionDatabase<>::denominations = {new Denomination<0>, new Denomination<1>, new Denomination<2>};
template <> struct ReligionDatabase<0> {
static const std::vector<Religion*> denominations;
};
const std::vector<Religion*> ReligionDatabase<0>::denominations = {new Denomination<0,0>, new Denomination<0,1>};
template <> struct ReligionDatabase<2> {
static const std::vector<Religion*> denominations;
};
const std::vector<Religion*> ReligionDatabase<2>::denominations = {new Denomination<2,0>, new Denomination<2,1>, new Denomination<2,2>};
template <> struct ReligionDatabase<2,0> {
static const std::vector<Religion*> denominations;
};
const std::vector<Religion*> ReligionDatabase<2,0>::denominations = {new Denomination<2,0,0>, new Denomination<2,0,1>, new Denomination<2,0,2>};
template <int...> struct D {};
template <typename Output, int... Input> struct RemoveLastHelper;
template <int... Accumulated, int First, int... Rest>
struct RemoveLastHelper<D<Accumulated...>, First, Rest...> : RemoveLastHelper<D<Accumulated..., First>, Rest...> {};
template <int... Accumulated, int Last>
struct RemoveLastHelper<D<Accumulated...>, Last> : std::integral_constant<int, Last> {
using type = D<Accumulated...>;
};
template <int... Is>
using RemoveLast = RemoveLastHelper<D<>, Is...>;
class Person {
template <typename> struct GetReligion;
Religion* religion;
public:
template <int... Is> Person (const D<Is...>&) : Person(RemoveLast<Is...>{}) {}
template <typename T> Person (const T&) : religion(GetReligion<typename T::type>::get(T::value)) {}
void pray() {religion->pray();}
};
template <int... Is>
struct Person::GetReligion<D<Is...>> {
static Religion* get(int n) {return ReligionDatabase<Is...>::denominations[n];}
};
int main() {
Person* person1 = new Person(D<2,0,1>{}); // "Prays like a Hanafi Sunni Muslim."Person* person2 = new Person(D<2,0>{}); // "Prays like a Sunni Muslim."Person* person3 = new Person(D<2>{}); // "Prays like a Muslim."person1->pray();
person2->pray();
person3->pray();
// Person* person4 = new Person(D<2,0,1,2,1,3>{}); // This doesn't compile.
// person4->pray(); // Should be "Prays like a Hanafi Sunni Muslim."
Person* person5 = new Person(D<0>{});
Person* person6 = new Person(D<0,1>{});
person5->pray(); // "Prays like a Christian."person6->pray(); // "Prays like a Protestant."}
Мне все еще нужна помощь, чтобы получить person4
чтобы скомпилировать хотя. Мне нужен компилятор, чтобы как-то уменьшить Denomination<2,0,1,2,1,3>
в Denomination<2,0,1>
, Как это сделать?