在容器中查找元素的标准化方法?

时间:2016-06-04 15:33:46

标签: c++ std

是否有标准化的方法来搜索容器中的值((unordered_)映射的键)?

以此功能为例:

// binding
var binding = new WSHttpBinding();
// using System.ServiceModel
var channelFactory = new ChannelFactory<InfoWcfWS.IInfo>(binding);
// using System.ServiceModel.Description
var endpointClientbehavior = new ClientCredentials();
endpointClientbehavior.ClientCertificate
    .SetCertificate(
    "This is my TEST Cert", 
    StoreLocation.LocalMachine, 
    StoreName.My);
// add the behavior to the endpoint
channelFactory.Endpoint.EndpointBehaviors.Add(endpointClientbehavior);

// done configuring;
channelFactory.Open();
var endpoint = new EndpointAddress(
    new Uri(ConfigurationManager.AppSettings["ServiceUrl.Tls12.Info"]));
// create the clientChannel
var client = channelFactory.CreateChannel(endpoint);
client.Open();
// client implements the operations on InfoWcfWS.IInfo

我用:

template <class T, class V> bool find(T const &t, V const &v) {
    // For std::vector : return std::find(t.begin(), t.end(), v) != t.end();
    // For std::(unordered_)set and (unordered_)map : return t.find(v) != t.end();
    return ?
}

但是std有这种东西吗?

3 个答案:

答案 0 :(得分:2)

没有什么标准可以帮到你 - 但我们可以轻松地编写这样的解决方案。 “特殊”部分是容器是否具有find()成员函数。如果是的话,我们应该使用它。如果没有,我们将回归使用std::find()。无论如何,我们希望将结果与end()进行比较。

因此,我们为.find()编写首选重载,为另一个重写 fallback 重载:

template <class C, class V>
auto generic_find_impl(C const& container, V const& value, int /* unused */)
    -> decltype(container.find(value))
{
    return container.find(value);
}

template <class C, class V>
auto generic_find_impl(C const& container, V const& value, ...)
{
    using std::begin;
    using std::end;
    return std::find(begin(container), end(container), value);
}

template <class C, class V>
bool generic_find(C const& container, V const& value) {
    using std::end;
    return generic_find_impl(container, value, 0) != end(container);
}

如果container.find(value)是有效表达式,则由于最后一个参数(int0的匹配比...更好),首选重载将是首选。如果它不是一个有效的表达式,那么第一个重载是不可行的,我们只得到第二个重载。

答案 1 :(得分:-1)

所以你基本上问的是有没有能为你调用t.find的功能?不。库基础知识TS v2提出了一系列非成员eraseerase_if重载,这些重载是这样实现的:

  template<typename _Key, typename _Compare, typename _Alloc,
       typename _Predicate>
    inline void
    erase_if(set<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)
    { __detail::__erase_nodes_if(__cont, __pred); }

  template<typename _Key, typename _Compare, typename _Alloc,
       typename _Predicate>
    inline void
    erase_if(multiset<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)
    { __detail::__erase_nodes_if(__cont, __pred); }

另一方面,以下是list

的重载
  template<typename _Tp, typename _Alloc, typename _Predicate>
    inline void
    erase_if(list<_Tp, _Alloc>& __cont, _Predicate __pred)
    { __cont.remove_if(__pred); }

  template<typename _Tp, typename _Alloc, typename _Up>
    inline void
    erase(list<_Tp, _Alloc>& __cont, const _Up& __value)
    {
      using __elem_type = typename list<_Tp, _Alloc>::value_type;
      erase_if(__cont, [&](__elem_type& __elem) { return __elem == __value; });
    }

正如您所看到的,无法进行均匀擦除。逻辑同样延伸到find。你的方法很好,但我会遵循标准的风格,并为比较器,分配器等添加模板参数,以便健壮。

答案 2 :(得分:-1)

您可以为find_if函数提供一元谓词

template <class K, class V> bool find(std::unordered_map<K, V> const &t, K  const &v) {
    return std::find_if(t.begin(), t.end(), [v](const std::pair<K, V>& x) {return x.first == v; }) != t.end();
}

int main()
{  
    std::unordered_map<int,char> example = {{1,'a'},{2,'b'}};
    std::cout << find(example, 2);  // true
    std::cout << find(example, 3);  // false
}