Оболочка содержит функцию () для разных контейнеров - PullRequest
1 голос
/ 19 мая 2011

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

// for std::vector, std::list, ..           (1)
template<typename C, typename T>
bool contains(const C& container, const T& val) 
{
    return ::std::find(container.begin(), container.end(), val) != container.end();
}

// partial specialization for std::map       (2)
template<typename K, typename V>
bool contains(const ::std::map<K, V>& container, const K& key)
{
   // std::map.find() is better than std::find used in (1)
    return container.find(key) != container.end(); 
}

После вопрос я хочу добавить функции в пространство имен, к которому принадлежат аргументы.

Вопросы:

  1. Типы val из (1) и key из (2) неизвестны. Означает ли это, что мне не нужно помещать функции в какое-либо пространство имен или мне нужно помещать их в std пространство имен, к которому относятся контейнеры?

  2. Можно ли улучшить (2), что будет предпочтительнее для компилятора, чем (1) для std :: map, std :: set, boost :: unordered_map, boost :: unordered_set?

  3. подталкивание :: Алгоритм :: содержит (). Нужно ли мне выбрать другое имя для моей обертки?

Ответы [ 4 ]

2 голосов
/ 19 мая 2011

(1) Не добавляйте что-либо в пространство имен std

(2) Как указывает Space_C0wb0y, (2) не является частичной специализацией,но перегрузка.Я не уверен, что это стандартное поведение, но на VS2008 это решено правильно (перегруженная версия используется для карты).В любом случае, я думаю, что немного лучшая версия была бы:

template<typename C>
bool contains(const C & mapContainer, const typename C::key_type & key)
{
  // std::map.find() is better than std::find used in (1)
  return mapContainer.find(key) != mapContainer.end(); 
}

Это частичная специализация (T специализируется на C :: key_type) и будет работать для всех типов, которые имеют type_f key_type (например,std :: map, boost :: unordered_map и т. д.)

(3) Поместить в отдельное пространство имен (см. ответ @ Тони)

Sidenote: Я не уверен, что думаю, что эти функции должны иметьодно и то же имяЕсли бы я увидел, что функция содержит () принимающую карту + другой аргумент, я мог бы подумать, что (1) функция проверяет, содержит ли карта запись для данного значения (например, какой-то ключ имеет предоставленное значение), или (2) функция проверяетесли есть такая запись на карте (например, предоставленное значение является парой).Вместо этого я бы вызвал функцию contains_key () для карт.

Редактировать: После небольшой проверки я подозреваю, что приведенный выше код не соответствует, так как использует "шаблон typedefs«.Это не стандартная функция C ++, но кажется, что Visual Studio поддерживает ее в некоторых случаях.Вероятно, есть обходной путь для этого, но не тот, который я достаточно умен, чтобы придумать сейчас.

2 голосов
/ 19 мая 2011

На номер 3. Вы должны поместить свою версию содержимого в собственное пространство имен, чтобы избежать конфликтов имен. Это цель пространств имен.

1 голос
/ 19 мая 2011
  1. Вы не должны помещать их в пространство имен std. Это запрещено Вы можете поместить их в любое пространство имён.
  2. Возможно, есть какая-то сфина-магия, которую вы можете сделать там, но я не могу придумать ее самостоятельно.
  3. См. Ответ Тони.
1 голос
/ 19 мая 2011

Да, храните их в отдельном пространстве имен.

Единственное, что нужно поместить в то же пространство имен, что и тип аргумента, - это перегрузки операторов, чтобы разрешить поиск Кенига (зависимый от аргумента).Это не перегруженные операторы.Конец истории.

Обратите внимание, как это также отвечает на вопрос 2 .: как вы заставляете компилятор предпочитать ваши реализации:

 using myownversions::contains;

(, если вы назвали свое пространство имен myownversions дляТеперь )

...