В последнее время я играл с std::map
и придумал грандиозный дизайн D для создания карты приоритетов - карты, которая содержит различные режимы, которые сгруппированы исходя из их приоритетов.Функция члена шаблона в классе без шаблона - как определить и позвонить
Я имею следующую структуру класса:
Mode
|
|----ModeSleep
|----ModeFactorial
где Mode
является:
class Mode
{
std::string name; ///< Mode's name
int priority; ///< Mode's priority used for storing the Mode in a specific priority group in the priority map. Default: 0
public:
Mode();
///
/// \brief Mode
/// \param name Mode's name
/// \param priority Mode's priority used for storing the Mode in a specific priority group in the priority map. Default: 0
///
Mode(const std::string &name, const int priority=0);
virtual ~Mode();
std::string getName() const;
void setName(const std::string &value);
int getPriority() const;
void setPriority(int value);
///
/// \brief run is the part of a Mode which is executed by the ModeExecutor
///
virtual void run() = 0;
};
С другой стороны, у меня есть еще один класс, который использует Mode
под названием PriorityMap
со следующим определением класса:
class PriorityMap
{
typedef std::pair<int, Mode *> ModeEntry;
typedef std::map<int, Mode *> PriorityGroup;
typedef PriorityGroup* PriorityGroup_Ptr;
typedef std::map<int, PriorityGroup_Ptr> Priority;
typedef Priority* Priority_Ptr;
Priority_Ptr priorities;
bool _insert(Mode *mode);
Mode *_find(const std::string &name);
public:
PriorityMap();
~PriorityMap();
void print();
void insert(Mode *mode);
template<class T> T *find(const std::string &name);
};
Belo ж вы можете увидеть пример того, как объекты инициализируются и называется:
int main()
{
PriorityMap *priorities = new PriorityMap();
ModeSleep *m1 = new ModeSleep("Sleep10", 0, 10);
priorities->insert(m1);
ModeSleep *m2 = new ModeSleep("Sleep5", 0, 5);
priorities->insert(m2);
ModeFactorial *m3 = new ModeFactorial("Factorial20", 1, 20);
priorities->insert(m3);
priorities->print();
// Example for a correct match (both name and type) - ERROR!!!
ModeSleep *foundM2 = priorities->template find<ModeSleep>("Sleep5");
if(foundM2)
std::cout << "Found mode \"" << foundM2->getName() << "\" has time interval set to " << foundM2->getMilliseconds() << "ms" << std::endl;
// Example for correct name match but incorrect type - ERROR!!!
ModeSleep *foundM1 = priorities->template find<ModeSleep>("Factorial20");
if(foundM1)
std::cout << "Found mode \"" << foundM1->getName() << "\" has time interval set to " << foundM1->getMilliseconds() << "ms" << std::endl;
delete priorities;
return 0;
}
В первый у меня не было каких-либо шаблонный материал для моего find()
(когда я переехал оригинальный find()
как частное _find()
под названием внутри версии template
find()
). Мой первоначальный дизайн (теперь _find()
) был:
Mode *PriorityMap::_find(const std::string &name)
{
for(const auto& priorityGroup : *priorities)
for(auto& modeEntry : *(priorityGroup.second))
if(!name.compare((modeEntry.second->getName())))
return modeEntry.second;
return nullptr;
}
После запуска find()
пар раза я столкнулся с проблемой, что мне пришлось вручную опущенные возвращаемый указатель к соответствующему выводу Mode
(в моем случае просто ModeSleep
и ModeFactorial
). Поэтому я решил, что добавление шаблонной функциональности для этой функции, а также добавляя некоторую обратную связь при вызове было бы полезно:
template<class T>
T *PriorityMap::find(const std::string &name)
{
Mode *foundMode = _find(name);
if(foundMode) {
T *foundModeCast = dynamic_cast<T *>(foundMode);
if(foundModeCast) {
std::cout << "Found mode \"" << foundModeCast->getName() << "\"" << std::endl;
return foundModeCast;
}
else {
std::cout << "Found mode \"" << foundMode->getName() << "\" however specified type is invalid! Returning NULL" << std::endl;
return nullptr;
}
}
}
Как вы можете видеть, по моему определению найден режим внутри мой приоритет карта основана от двух факторов:
name
является матчем- данного типа спички
У меня есть проблема с вызовом моего find()
, хотя и я моя сборка перерывы в первом использовании его со следующей ошибкой:
In function `main':
undefined reference to `ModeSleep *PriorityMap::find<ModeSleep>(std::string const&);'
Я не сделал много функций-членов шаблона и был бы признателен за обратную связь на этом. Если вам нужна дополнительная информация, сообщите и предоставите ее.
PS: Для тех из вас, интересно, о том, как режимы пути являются найдены на основе их имен - на самом деле я собираюсь изменить find()
вернуть вектор ссылок, поскольку имена не являются уникальными мой случай, и я могу иметь режимы с тем же именем в разных местах моей карты приоритетов. Прямо сейчас find()
возвращает первое совпадение, но должно быть достаточно для цели этого сообщения.
* Facepalm * Я совершенно забыл, что шаблоны должны быть в заголовки! Как глупо со мной ... Функции члена шаблона - это всего лишь шаблоны. – rbaleksandar