Идиоматический C++ для чтения из карты константы

Вы можете создать файл .htaccess в корневой папке вашего проекта. Содержимое файла вроде этого;

RewriteEngine on
RewriteCond $1 !^(index\.php|assets)
RewriteRule ^(.*)$ /your-project/index.php/$1 [L]
14
задан Magnus Hoff 30 September 2008 в 12:46
поделиться

7 ответов

template <typename K, typename V>
V get(std::map<K, V> const& map, K const& key)
{
    std::map<K, V>::const_iterator iter(map.find(key));
    return iter != map.end() ? iter->second : V();
}

Улучшенная реализация на основе комментариев:

template <typename T>
typename T::mapped_type get(T const& map, typename T::key_type const& key)
{
    typename T::const_iterator iter(map.find(key));
    return iter != map.end() ? iter->second : typename T::mapped_type();
}
11
ответ дан 1 December 2019 в 08:20
поделиться

Выбрасывание константы является неправильным, потому что оператор [] на map<> создаст запись, если она не будет присутствовать с созданной строкой значения по умолчанию. Если карта будет на самом деле в неизменном устройстве хранения данных затем, то это перестанет работать. Это должно быть так, потому что оператор [] возвращает ссылку неконстанты для разрешения присвоения. (например, m[1] = 2)

А быстрая бесплатная функция для реализации сравнения:

template<typename CONT>
bool check_equal(const CONT& m, const typename CONT::key_type& k,
                    const typename CONT::mapped_type& v)
{
    CONT::const_iterator i(m.find(k));
    if (i == m.end()) return false;
    return i->second == v;
}

я буду думать о синтаксическом сахаре и обновлять, если я буду думать о чем-то.

...

непосредственный синтаксический сахар включил бесплатную функцию, которая делает map<>:: найдите (), и возвращает специальный класс, который переносит map<>:: const_iterator, и затем перегрузил оператор == () и оператор! = () для разрешения сравнения с отображенным типом. Таким образом, можно сделать что-то как:

if (nonmutating_get(m, "key") == "value") { ... }

я не убежден, что это намного лучше, чем:

if (check_equal(m, "key", "value")) { ... }

И это, конечно, намного более сложно и что продолжается, намного менее очевидно.

цель объекта, переносящего итератор, состоит в том, чтобы прекратить создавать значение по умолчанию объекты данных. Если Вы не заботитесь, то просто используют "получить" ответ.

В ответ на комментарий о получении быть предпочтенным по сравнению в надежде на нахождение некоторого будущего использования, у меня есть эти комментарии:

  • Говорят, что Вы имеете в виду: вызывание функции, вызванной "check_equal", проясняет, что Вы делаете сравнение равенства без создания объекта.

  • я рекомендую только реализовать функциональность, после того как у Вас есть потребность. Выполнение чего-то к тому времени является часто ошибкой.

  • В зависимости от ситуации, конструктор по умолчанию мог бы иметь побочные эффекты. Если Вы выдерживаете сравнение, почему делают что-либо дополнительное?

  • аргумент SQL: ПУСТОЙ УКАЗАТЕЛЬ не эквивалентен пустой строке. Является отсутствие ключа от Вашего контейнера действительно тем же, поскольку ключ, присутствующий в Вашем контейнере со значением по умолчанию, создал значение?

сказавший все это, значение по умолчанию созданный объект эквивалентен использованию map<>:: оператор [] на контейнере неконстанты. И возможно у Вас есть текущее требование для получить функции, которая возвращает значение по умолчанию созданный объект; я знаю, что у меня было то требование в прошлом.

11
ответ дан 1 December 2019 в 08:20
поделиться

find идиоматическая форма. Выбрасывающий const является почти всегда плохой идеей. Необходимо было бы гарантировать, что никакая операция записи не выполняется. В то время как это может обоснованно ожидаться доступа для чтения на карте, спецификация ничего не говорит об этом.

, Если Вы знаете , что значение существует, можно, конечно, предшествовать тесту с помощью count (который довольно неэффективен, так или иначе, так как это означает пересекать карту дважды. Даже если Вы не знаете, существует ли элемент, я не использовал бы это. Используйте следующее вместо этого:

T const& item(map<TKey, T> const& m, TKey const& key, T const& def = T()) {
    map<TKey, T>::const_iterator i = m.find(key);
    return i == m.end() ? def : i->second;
}

РЕДАКТИРОВАНИЕ/: Как Chris правильно указал, конструкция по умолчанию объектов типа T могла бы быть дорогой, тем более, что это сделано, даже если этот объект не на самом деле необходим (потому что запись существует). Если это верно, не используйте значение по умолчанию для def аргумент в вышеупомянутом случае.

5
ответ дан 1 December 2019 в 08:20
поделиться

Действительно, оператор [] является неконстантой один на станд.:: карта, так как это автоматически вставляет пару "ключ-значение" в карту, если это не было там. (Побочные эффекты Oooh!)

правильный путь использует map::find и, если возвращенный итератор допустим (!= map.end()), возвращаясь эти second, когда Вы показали.

map<int, int> m;
m[1]=5; m[2]=6; // fill in some couples
...
map<int,int>::const_iterator it = m.find( 3 );
if( it != m.end() ) {
    int value = it->second;
    // ... do stuff with value
}

Вы могли добавлять map::operator[]( const key_type& key ) const в подклассе станд.:: карта Вы используете и утверждаете ключ, который будет найден, после которого Вы возвращаетесь it->second.

1
ответ дан 1 December 2019 в 08:20
поделиться

Интересное в стороне, существует два пути, выполняют в шаблонном исследовании типа получить реализация, которая была принята (тот, который получает значение или возвращает значение по умолчанию созданный объект). Один, можно сделать то, что было принято, и имейте:

template <typename K, typename V>
V get1(const std::map<K, V>& theMap, const K const key)
{
    std::map<K, V>::const_iterator iter(theMap.find(key));
    return iter != theMap.end() ? iter->second : V();
}

или можно использовать тип карты и получить типы от этого:

template<typename T>
typename T::mapped_type
get2(const T& theMap, const typename T::key_type& key)
{
    typename T::const_iterator itr = theMap.find(key);
    return itr != theMap.end() ? itr->second : typename T::mapped_type();
}

преимущество этого состоит в том, что тип ключа, передаваемого в, не играет в исследовании типа, и это может быть что-то, что может быть неявно преобразовано в ключ. Например:

std::map<std::string, int> data;
get1(data, "hey"); // doesn't compile because the key type is ambiguous
get2(data, "hey"); // just fine, a const char* can be converted to a string
5
ответ дан 1 December 2019 в 08:20
поделиться
std::map<std::string, std::string>::const_iterator it( m.find("a") );
BOOST_CHECK_EQUAL( 
                     ( it == m.end() ? std::string("") : it->second ), 
                     "b" 
                 );

, Который не выглядит слишком плохо мне... Я, вероятно, не записал бы функцию для этого.

0
ответ дан 1 December 2019 в 08:20
поделиться

Продолжение идеи xtofl о специализации контейнера карты. Будет ли работать следующее хорошо?

template <typename K,typename V>  
struct Dictionary:public std::map<K,V>  
{  
  const V& operator[] (const K& key) const  
  {  
    std::map<K,V>::const_iterator iter(this->find(key));  
    BOOST_VERIFY(iter!=this->end());  
    return iter->second;  
  }  
};  
0
ответ дан 1 December 2019 в 08:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: