Как мне настроить и использовать std::map<void *, MyClass *>
У меня есть программа с набором входных данных и набором выходных переменных, которыми я обмениваюсь с веб-страницей Apache/PHP с использованием XML. На веб-странице пользователи могут видеть, что настроено / происходит, и могут изменять настройки.
Когда я передаю XML в программу PHP (мы используем сокеты Unix_domain), я добавляю много мета-информации о настройках и индикаторах, которые я передаю ему. Такие вещи, как тип данных, min, max, default, привилегии чтения / записи и т. Д.
<temperature datatype="INT32" min=-"40" max="150" permissions="R/O">25</temperature>
Мне нужно знать метаданные о каждой из моих переменных при создании исходящего XML. Хотя хороший способ сделать это - создать класс VarInfo, который я бы связал с каждой переменной. Я хотел сохранить имя переменной в качестве ключа на карте (не уверен, что всегда могу знать имя переменной). Я подумал о том, чтобы ключ был указателем на переменную, а значение - указателем на объект VarInfo для этой переменной. Единственный известный мне способ хранения смешанных типов указателей - привести их все к void *. Итак, что-то вроде:
bool cmpr( void* a, void*b) { return (long)a < (long)b;};
std::map<void*,VarInfo*,cmpr> VarMap;
int temperature;
VarInfo vi_temperature;
VarMap[(void*)&temperature] = &vi_temperature;
Это создает кучу ошибок при объявлении карты.
expected a type, got ‘cmpr’ ACT_iod.cpp
Invalid template arguments ACT_iod.cpp line 40 Semantic Error
invalid type in declaration before ‘;’ token
type/value mismatch at argument 3 in template parameter list for
‘template<class _Key, class _Tp, class _Compare, class _Alloc> class std::map’
Итак, кто-то может подсказать, как мне это сделать, и, возможно, также предложить лучший способ хранения метаинфо? Все еще думаю о переходе на std::string как ключ.
Благодарю.
1 ответ
Третий параметр std::map
должен быть тип компаратора. Как одно исправление вы могли бы сделать cmpr
функтор (который часто является предпочтительным подходом из-за своей нестабильности):
struct cmpr {
bool operator()(void* a, void* b) {...}
}
std::map<void*,VarInfo*,cmpr> VarMap;
Другой альтернативой является использование типа указателя на функцию (bool(*)(void*, void*)
iirc) и даем указатель на фактически используемую функцию в качестве параметра конструктора:
bool cmpr( void* a, void*b) { return (intptr_t)a < (intptr_t)b;}
std::map<void*,VarInfo*,bool(*)(void*, void*)> VarMap(&cmpr);
Изменить: теперь, когда я думаю об этом: сравнение по умолчанию для указателей <
в любом случае, так что вы можете просто использовать std::map<void*, VarInfo*>
который имеет преимущество быть более портативным. Как правило, вы должны избегать наведения указателей на long
, Избегайте указателей на целочисленные приведения, если это возможно, в противном случае используйте intptr_t
, uintptr_t
или же size_t
это гораздо лучшая идея, так как long
не гарантируется, что он будет достаточно большим, чтобы содержать указатель (и long действительно 32-битный на некоторых 64-битных платформах).