Выполните итерацию `std::map` с `struct` вместо `std::pair`

Давно мне хотелось выполнить итерацию карты C++ с помощью struct вместо std::pair. Причина этого в том, что я всегда нахожу pair.first и pair.second двусмысленными.

Итак, я попробовал этот код:

map< string, int > wordCounts;

wordCounts[ "a" ] = 37;
wordCounts[ "the" ] = 10;
wordCounts[ "you" ] = 5;

struct WordCountPair {
  string word;
  int count;
    
  WordCountPair( const pair<const string, int>& p ) :
    word( p.first ), count( p.second ) { }
};
  
for( WordCountPair e : wordCounts ) {
  printf( "%s occurred %d times\n", e.word.c_str(), e.count );
}

Работает, правда, дороговато с теми копиями, которые происходят

Кто-нибудь знает способ сделать что-то подобное, без копирования?

Вы можете избежать копий, используя ссылки на участников, например.

StoryTeller - Unslander Monica 29.08.2024 23:18

«Я хотел выполнить итерацию карты C++ с помощью struct вместо std::pair». -- Я сомневаюсь, что это правда. Гораздо более вероятно, что вы хотели иметь более осмысленные имена для ключа и значения, чем first и second, и ваш план достижения этой цели состоит в том, чтобы использовать struct вместо std::pair (игнорируя тот факт, что std::pair<X,Y> является struct). Сосредоточение внимания на своей реальной цели может помочь избежать ослепления в отношении альтернативных подходов.

JaMiT 30.08.2024 00:50

Смотрите этот ответ в дюпе.

user12002570 30.08.2024 04:16
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
3
80
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Если у вас есть доступ к C++17 или новее, вы можете решить проблему с помощью структурированной привязки. Это создаст в серверной части заполнитель для возвращаемой пары, а затем предоставит вам именованные ссылки на пару с предоставленными вами именами. Это даст вам что-то вроде

for(const auto& [word, count] : wordCounts ) {
  printf( "%s occurred %d times\n", word.c_str(), count );
}

const auto& гарантирует, что внутренний объект является ссылкой на элемент карты, а затем word и count являются ссылками на эту парную ссылку, поэтому копий вообще не происходит.

struct WordCountPairRef {
  std::string const& word;
  int const& count;

  WordCountPairRef( std::pair<const std::string, int> const& p ) :
    word( p.first ), count( p.second ) { }
};

for( WordCountPairRef e:wordCounts )

это позволяет избежать копирования.

Обратите внимание, что это не обеспечивает соблюдение срока службы. Однако в цикле for(:) над std::map базовый std::pair находится в std::map, поэтому эти ссылки относительно безопасны.

Однако структурированные привязки — это современный идиоматический способ решения этой проблемы:

Если у вас есть доступ к C++17 или новее, вы можете решить проблему с помощью структурированной привязки. Это создаст в серверной части заполнитель для возвращаемой пары, а затем предоставит вам именованные ссылки на пару с предоставленными вами именами. Это даст вам что-то вроде

for( auto const&[word, count]:wordCounts )

это создает ссылки на word и count без создания структуры.

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