受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)的 val 和来自(2)的 key 的类型未知。这是否意味着我不需要将函数放到任何命名空间中,还是需要将它们放在 std 命名空间中,容器属于?
是否有可能改进(2)编译器优先于(1)std :: map,std :: set,boost :: unordered_map,boost :: unordered_set?
升压::算法::含有()。我需要为包装器选择其他名称吗?
答案 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)
std
命名空间。这是被禁止的。您可以将它们放入任何您喜欢的命名空间中。