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

时间:2011-05-19 11:04:31

标签: c++ templates boost stl

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

// 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(); 
}

question之后,我想将这些函数添加到参数所属的命名空间中。

问题:

  1. 来自(1)的 val 和来自(2)的 key 的类型未知。这是否意味着我不需要将函数放到任何命名空间中,还是需要将它们放在 std 命名空间中,容器属于?

  2. 是否有可能改进(2)编译器优先于(1)std :: map,std :: set,boost :: unordered_map,boost :: unordered_set?

  3. 升压::算法::含有()。我需要为包装器选择其他名称吗?

4 个答案:

答案 0 :(得分:2)

在数字3上,你应该将你的包含版本放在它自己的命名空间中,以避免命名冲突。这就是命名空间的目的。

答案 1 :(得分:2)

(1)Don't add anything to the std namespace

(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的回答)

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

修改 经过一些检查后,我怀疑上面的代码不符合,因为它使用"template typedefs"。这不是标准的C ++功能,但似乎Visual Studio在某些情况下支持它。可能有一个解决方法,但不是一个我现在聪明的想法。

答案 2 :(得分:1)

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

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

请注意这也是如何回答问题2:如何使编译器更喜欢您的实现:

 using myownversions::contains;

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

答案 3 :(得分:1)

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