开发者

Flyweight pattern and C++ templates

I have flyweight pattern. I have abstract class Glyph. I have class Letter and abstract Code derived from Glyph. I have YusciiCode, UniCyrCode and UniLatCode derived from 开发者_运维问答Code.

My flyweight factory can be done like this:

    template <class T>
 class CodeFactory : public AbstractCodeFactory
 {
 public:
  CodeFactory();
  virtual ~CodeFactory();
  virtual Glyph* GetFlyweight(unsigned int code);
  virtual Glyph* GetFlyweight(string letter);
 private:
  // pool of flyweights (codes or letters)
  map <unsigned int, Glyph*> my_code_map;
  map <string, Glyph*> my_letter_map;
 };

It can be done like this:

template <class key, class T>
 class CodeFactory : public AbstractCodeFactory
 {
 public:
  CodeFactory();
  virtual ~CodeFactory();
  virtual Glyph* GetFlyweight(key code);
 private:
  // pool of flyweights (codes or letters)
  map <key, Glyph*> my_code_map;
 };

In the first example GCC linker tell me that there are no Letter(unsigned int) and xxxCode(string) constructor. In fact there aren't any and GCC is right, but is there a better way to do this than to define those constructors?

In the seccond ecample GCC compiler tells me that there is an error on the line

map <key, Glyph*>::iterator it;

of the function GetFlyweight.

What is the way to implement this flyweight pattern?

I need to use it. Here is my current implementation:

class AbstractCodeFactory
{
public:
    AbstractCodeFactory();
    virtual ~AbstractCodeFactory();
    virtual Glyph* GetFlyweight(unsigned int code) = 0;
    virtual Glyph* GetFlyweight(string letter) = 0;
};


template <class T>
    class CodeFactory : public AbstractCodeFactory
    {
    public:
        CodeFactory();
        virtual ~CodeFactory();
        virtual Glyph* GetFlyweight(unsigned int code);
        virtual Glyph* GetFlyweight(string letter);
    private:
        // pool of flyweights (codes or letters)
        map <unsigned int, Glyph*> my_code_map;
        map <string, Glyph*> my_letter_map;
    };


template <class T>
    CodeFactory<T>::CodeFactory()
    {
        // TODO Auto-generated constructor stub

    }

template <class T>
    CodeFactory<T>::~CodeFactory()
    {
        // TODO Auto-generated destructor stub
        map <unsigned int, Glyph*>::iterator it;
        map <string, Glyph*>::iterator l_it;
        for (it = my_code_map.begin(); it != my_code_map.end(); ++it)
        {
            delete it->second;
            it->second = NULL;
            my_code_map.erase(it);
        }
        for (l_it = my_letter_map.begin(); l_it != my_letter_map.end(); ++l_it)
        {
            delete l_it->second;
            l_it->second = NULL;
            my_letter_map.erase(l_it);
        }
    }

template <class T>
    Glyph* CodeFactory<T>::GetFlyweight(unsigned int code)
    {
        map <unsigned int, Glyph*>::iterator it;
        T *code_class = NULL;
        if ((it = my_code_map.find(code)) == my_code_map.end())
        {
            my_code_map.insert(pair <unsigned int, Glyph*> (code, code_class = new T(code)));
            return code_class;
        }
        else return it->second;
    }

template <class T>
    Glyph* CodeFactory<T>::GetFlyweight(string letter)
    {
        map <string, Glyph*>::iterator it;
        T *letter_class = NULL;
        if ((it = my_letter_map.find(letter)) == my_letter_map.end())
        {
            my_letter_map.insert(pair <string, Glyph*> (letter, letter_class = new T(letter)));
            return letter_class;
        }
        else return it->second;
    }


As your flyweight factory can only produce either Letter, YusciiCode, UniCyrCode or UniLatCode objects, I would go with the second option (a second template parameter indicating the key type.

The problem that the compiler has with the declaration map <key, Glyph*>::iterator it; is that the compiler can"t be sure if map<key, Glyph*>::iterator refers to a type or something else. This is because it depends on the template parameter key, and you might have a specialisation of map<> somewhere where the member iterator is not a type.
To help the compiler out, you must specify that you expect that map<ket, Glyph*>::iterator refers to a typename:

typename map<key, Glyph*>::iterator it;
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜