【问题标题】:template syntax for containers容器的模板语法
【发布时间】:2011-04-11 20:01:31
【问题描述】:

这就是我现在拥有的:

template<template<typename T> class container, typename T>
inline bool contains( const container<T> &cont, const T &element )
{
    if( cont.size() == 0 )
        return false;

    return( std::find(cont.begin(), cont.end(), element) != cont.end() );
}

我想这样称呼它:

std::vector<string> stringvector;
contains( stringvector, "somestring" );

我相信这应该是可能的,但我尝试过的一切都会引发不同的错误。任何帮助表示赞赏。谢谢!

更新:感谢所有答案,我看得太远了,但我仍然遇到问题:

template<class container_type, typename T>
inline bool contains(const container_type& c, const T& e)
{
    return !(c.size() && std::find(c.begin(),c.end(),e)!=c.end());
}

int main(int argc, char *argv[])
{
    vector<string> stringvector;
    stringvector.push_back("hello");
    cout << contains( stringvector, string("hello") );
    return 0;
}

编译失败,即使没有显式的 `string´ 构造函数:

error: no matching function for call to 'find(std::vector<std::basic_string<char> >::const_iterator, std::vector<std::basic_string<char> >::const_iterator, const std::basic_string<char>&)'

【问题讨论】:

  • 你能举出错误信息的例子,以免每个人都不得不编写一个(非)可编译的例子并自己尝试吗?

标签: c++ templates


【解决方案1】:

STL 容器采用两个 参数,一个用于包含的类型,另一个用于描述如何获取内存的分配器。

试试这个:

template<template<typename T, typename Alloc> class container, typename T, typename Alloc>
inline bool contains( const container<T, Alloc > &cont, const T &element )

但是,这确实是一个很好的例子,说明了为什么您应该完全避免在容器上对算法进行参数化。最好遵循&lt;algorithm&gt;的模式,只指定迭代器类型参数。

template< typename Iter, typename T >
inline bool contains( Iter first, Iter last, const T &element )
    { return std::find( first, last, element ) != last; }

如果您必须要求提供容器,请不要费心指定容器的外观。假设它有你想要的界面。这对你来说是最简单的,对用户来说也是最灵活的。

template< typename Cont, typename T >
inline bool contains( Cont const &cont, T const &element )
    { return std::find( cont.begin(), cont.end(), element ) != cont.end(); }

【讨论】:

  • 第二个模板参数不是提供了默认值吗(即std::allocator&lt;T&gt;?我从来没有在任何地方指定分配器?
  • 哇,你的代码我得到no matching function for call to 'find(std::vector&lt;std::basic_string&lt;char&gt; &gt;::const_iterator, std::vector&lt;std::basic_string&lt;char&gt; &gt;::const_iterator, const std::basic_string&lt;char&gt;&amp;)'。也许这里已经太晚了......
  • 您的最后一个代码示例未声明 last ;-) 我相信您打算将其更改为 cont.end()
  • @rubenvb:是的,有一个默认值,但这不影响传递模板模板参数时匹配哪些参数规范。
  • 您更新的代码会导致相同的错误消息:(“没有匹配的函数调用”。
【解决方案2】:

为什么不直接

template<class container_type,typename T>
inline bool contains(const container_type& c,const T& e) {
    return !(c.size() && std::find(c.begin(),c.end(),e)!=c.end());
}

【讨论】:

  • 不需要检查size()。 - 如果必须,!c.empty() 会更好(有些实现std::list.size() 具有线性复杂度)。
  • UncleBens,所以我想,但还是从原版借来的。如果有的话我会去.empty()
  • +1 不错,简单并且正确,这是公认的答案所不具备的。
【解决方案3】:

试试:

template <class T> 
bool contains(const T & cont, const typename T::value_type & elem)
{
   return( std::find(cont.begin(), cont.end(), elem) != cont.end() );
}

大多数标准容器都有一个value_type typedef,可以简化这一点。

【讨论】:

    【解决方案4】:

    比这更简单...只需将容器和包含的元素类型视为模板参数...

    #include <vector>
    #include <list>
    #include <set>
    #include <string>
    #include <algorithm>
    #include <iostream>
    
    template<typename C, typename E>
    bool contains(const C& c, const E& e)
    {
        return std::find(c.begin(), c.end(), e) != c.end();
    }
    
    int main()
    {
        std::vector<std::string> V;
        std::list<std::string> L;
        std::set<std::string> S;
    
        V.push_back("Foo"); L.push_back("Foo"); S.insert("Foo");
        V.push_back("Bar"); L.push_back("Bar"); S.insert("Bar");
    
        std::cout << contains(V, "Foo") << std::endl;
        std::cout << contains(L, "Foo") << std::endl;
        std::cout << contains(S, "Foo") << std::endl;
    
        std::cout << contains(V, "Baz") << std::endl;
        std::cout << contains(L, "Baz") << std::endl;
        std::cout << contains(S, "Baz") << std::endl;
    
        return 0;
    }
    

    但是请注意,例如在上面的代码中,我同时使用containsstd::set,其中std::find 不是搜索事物的聪明方法(std::set::find 可以做得比 O(n) 更好) .

    【讨论】:

    • 我想我记得有一个std::set::find 调用lower_bound,它具有更好的复杂性。 (GCC 4.5)
    • 正是我的观点;但是std::find 只是被赋予了一个迭代器,所以它必须改为遍历它。我只是说contains 在这种情况下效率很低。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-26
    • 1970-01-01
    • 2013-05-11
    • 1970-01-01
    • 2011-04-07
    相关资源
    最近更新 更多