Шаблон Flyweight и шаблоны C++
У меня есть легкий вес модели. У меня есть абстрактный класс Glyph. У меня есть класс Letter и абстрактный код, полученный из Glyph. У меня есть YusciiCode, UniCyrCode и UniLatCode, полученные из кода.
Моя фабрика по навесу может быть сделана так:
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 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;
};
В первом примере компоновщик GCC сообщает, что нет конструктора Letter(unsigned int) и xxxCode(string). На самом деле их нет и GCC прав, но есть ли лучший способ сделать это, чем определять эти конструкторы?
Во втором примере ECC компилятор GCC сообщает, что в строке произошла ошибка
map <key, Glyph*>::iterator it;
функции GetFlyweight.
Как реализовать этот шаблон в полулегком весе?
Мне нужно это использовать. Вот моя текущая реализация:
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;
}
1 ответ
Так как ваша фабрика навесного веса может производить только объекты Letter, YusciiCode, UniCyrCode или UniLatCode, я бы выбрал второй вариант (второй параметр шаблона, указывающий тип ключа).
Проблема, которую компилятор имеет с объявлением map <key, Glyph*>::iterator it;
является то, что компилятор не может быть уверен, если map<key, Glyph*>::iterator
относится к типу или что-то еще. Это потому, что это зависит от параметра шаблона key
и у вас может быть специализация map<>
где-то где член iterator
это не тип.
Чтобы помочь компилятору, вы должны указать, что вы ожидаете, что map<ket, Glyph*>::iterator
ссылается на имя типа:
typename map<key, Glyph*>::iterator it;