Установка элементов 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) для каждой записи списка, чтобы я мог получить к ней доступ позже?

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

2 ответа

Решение

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* поэтому актерский состав обязателен.

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

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

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

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