1

考虑这段代码:

#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...>()) {}

这将查找 staticReligion*的“表”。毕竟,属于完全相同教派的两个人应该共享相同的Religion*值。所以这是我试图在这里实现的轻量级设计模式。问题是我们不知道Is...包装有多长(子子-...-面额的数量在任何地方都不是固定的),所以我不认为一个简单的多维数组行不通。因此,我正在做的是Religion*在适当的类中放置一些 s 的静态 const 向量,并且该Is...包将用于查找要查找的最终向量。

更新:有更好的方法吗?如果您在下面看到,到目前为止我发现的解决方案有一个主要缺点。

4

1 回答 1

0

好的,我已经制定了几乎完整的解决方案。 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>. 如何做到这一点?

于 2015-08-17T06:27:07.993 回答