包装器包含()函数用于不同的容器

Wrapper contains() function for different containers

本文关键字:用于 函数 包含 包装      更新时间:2023-10-16

受contains()的启发,我想声明contains(),适合杂项容器。

// 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. 来自 (1) 的 val 和来自 (2) 的的类型是未知的。这是否意味着我不需要将函数放入任何命名空间,或者我是否需要将它们放在容器所属的 std 命名空间中?

  2. 是否有可能改进 (2) 编译器首选 (1) 对于 std::map、std::set、boost::unordered_map、boost::unordered_set?

  3. boost::
  4. algorithm::contains()。我需要为我的包装器选择另一个名称吗?

(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),并且适用于所有具有 key_type typedef 的类型(例如 std::map、boost::unordered_map 等)。

3)放入单独的命名空间(见@Tony的答案)

旁注:我不确定我是否认为这些函数应该具有相同的名称。如果我看到一个函数包含 maps() 接受一个 map + 另一个参数,我可以认为 (1) 该函数检查映射是否包含给定值的条目(例如,某个键具有提供的值)或 (2) 该函数检查映射中是否有这样的条目(例如,提供的值是一对)。相反,我会为地图调用函数 contains_key()。

编辑:经过一番检查,我怀疑上面的代码不合规,因为它使用了"模板类型定义"。这不是标准的C++功能,但似乎Visual Studio在某些情况下支持它。可能有一个解决方法,但我现在不够聪明,想不出一个解决方法。

在第 3 号上。 应将包含的版本放在其自己的命名空间中,以避免命名冲突。这就是命名空间的目的。

是的,将它们保存在单独的命名空间中。

唯一要与参数类型放在同一命名空间中的是运算符重载,以允许 Koenig(依赖于参数)查找。这些不是重载运算符。故事结束。

请注意,这也回答了问题 2.:如何使编译器首选您的实现:

 using myownversions::contains;

假设您现在将命名空间命名为 myownversions

  1. 不得将它们放入 std 命名空间中。这是禁止的。您可以将它们放入您喜欢的任何命名空间中。
  2. 你可能在那里可以做一些SFINAE魔法,但我自己想不出。
  3. 看@Tony的回答。