Как мне настроить и использовать 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-битных платформах).

Другие вопросы по тегам