Установка элементов std :: map в качестве элементов данных CListBox

У меня похожий вопрос Вот но контекст этого нового вопроса другой.

У меня есть эта переменная: PublisherMap m_mapPublishers;

Определение PublisherMap является:

using PublisherMap = std::map<CString, S_DEMO_ENTRY_EX>;

У меня есть этот метод, который читает карту и заполняет CListBox:

bool CChristianLifeMinistryPersonalCopiesDlg::InitPublishersGrid()
{
try
{
m_lbPublishers.ResetContent();

for (auto & mapPublisher : m_mapPublishers)
{
bool bInclude = false;

if (m_iDisplayMode == DISPLAY_EVERYONE)
bInclude = true;
else if (m_iDisplayMode == DISPLAY_BROTHER && mapPublisher.second.eGender == GENDER_MALE)
bInclude = true;
else if (m_iDisplayMode == DISPLAY_SISTER && mapPublisher.second.eGender == GENDER_FEMALE)
bInclude = true;

if (bInclude && m_bLimitDisplay)
{
CString strTemp;
if (!m_mapSSAssignedPublishers.Lookup(mapPublisher.first, strTemp))
bInclude = FALSE;
}

if (bInclude)
{
int i = m_lbPublishers.AddString(mapPublisher.first);
m_lbPublishers.SetItemData(i, MAKEWPARAM(mapPublisher.second.eGender, mapPublisher.second.eAppointed));

}
}
}
catch (_com_error e)
{
LPCTSTR szError = e.ErrorMessage();
AfxMessageBox(szError);
return false;
}
catch (CException* e)
{
e->Delete();
AfxMessageBox(_T("CException"));
return false;
}

m_iSelectMode = SELECT_NONE;
UpdateData(FALSE);

return true;
}

Обратите внимание, что я использую данные элемента:

m_lbPublishers.SetItemData(i,
MAKEWPARAM(mapPublisher.second.eGender, mapPublisher.second.eAppointed));

Работает абсолютно нормально. Если бы я использовал CPtrArray Я бы назначил фактические указатели объекта структуры для каждой записи в списке.

Я не знаю механику std::map довольно. Есть ли безопасный способ напрямую связать каждую запись с карты (mapPublisher) для каждой записи списка, чтобы я мог получить к ней доступ позже?

Я понимаю, что могу взять текст записи списка, а затем найти его на карте и получить таким образом. Но есть ли более прямой способ связать их вместе?

1

Решение

std::map указан как ассоциативный контейнер, который никогда не перемещает существующие элементы, см. [Associative.reqmts] / 9:

insert а также emplace члены не должны влиять на действительность итераторов и ссылок на контейнер, а erase члены должны делать недействительными только итераторы и ссылки на стертые элементы.

На практике это часто реализуется как красно-черное дерево.

Таким образом, безопасно сохранять указатели на существующие элементы, если их время жизни превышает время жизни указателей.

Обратите внимание, что вы потеряете эту гарантию, если вы переключитесь на std::unordered_map (хеш-карта).


Установить:

    m_lbPublishers.SetItemDataPtr(i, &mapPublisher.second);

Чтобы получить:

    auto psEntry = (S_DEMO_ENTRY_EX*)m_lbPublishers.GetItemDataPtr(i);

CListBox::GetItemDataPtr() возвращается void* поэтому актерский состав обязателен.

4

Другие решения

Пока узел карты не разрушен / удален, вы можете передать указатель на сопоставленный тип данных непосредственно в CListBox::SetItemDataPtr,

Так что в вашем случае доступ к S_DEMO_ENTRY_EX и используя указатель, используя &mapPublisher.second все в порядке.

Это гарантировано правилами для STL

2

По вопросам рекламы [email protected]