【问题标题】:Return an iterator to an STL container from a template function从模板函数返回迭代器到 STL 容器
【发布时间】:2014-10-17 21:20:24
【问题描述】:

我试图将一个迭代器从一个模板函数返回到一个向量(还不是一个模板类成员——我还在写那个)。编译器不断给我错误(复制如下以方便谷歌搜索)。我基本上知道问题出在哪里,但确切的语法难以捉摸。

我阅读了互联网,搜索了 SO,包括 Where and why do I have to put the "template" and "typename" keywords?,但没有找到有效的答案。我想我应该在这里提出问题并自己回答。

(略)原代码如下:

#include <vector>
#include <algorithm>  // std::lower_bound

template<typename T> std::vector<T>::iterator
              insertIntoVector(std::vector<T>& vec, const T& val)
{  itr = [some std::vector<T> iterator];
   return itr;  // return iterator to val in vec.
} // End of insertIntoVector();

编译器错误:

error C2145: syntax error: missing ';' before identifier 'insertIntoVector'
error C2065: 'T' : undeclared identifier
error C2923: 'std::vector' : 'T' is not a valid template type argument for parameter '_Ty'

明智地,我尝试了这个:

template<typename T> typename std::vector<T>::iterator
              insertIntoVector(std::vector<T>& vec, const T& val)

更多编译器错误:

error C1075: end of file found before the left brace '{'

如果这个问题被解锁,我会在下面发布我的答案。否则,请在Where and why do I have to put the "template" and "typename" keywords? 上查看我的回答。

【问题讨论】:

  • 使用template&lt;typename T&gt; typename std::vector&lt;T&gt;::iterator,因为你有一个依赖类型
  • 我不同意这个问题是重复的。首先,我在 SO 上搜索了我的 *ss off 以寻找答案。我怎么知道要搜索的神奇问题?问题是关于一个模板函数返回类型,它返回一个迭代器到一个stl容器。这些关键字不会将我引向所引用的问题。
  • @vsoftco。 typename std::vector::iterator 也不起作用,尽管依赖类型问题在正确的轨道上。当我因重复问题而被锁定时,我正在发布我的答案。阅读引用的问题,看看你是否发现你的建议有什么问题,或者即使它解决了返回类型。
  • @T.C.我再次查看了您引用的问题,使用浏览器搜索功能查找“返回类型”。那里甚至没有返回这个词。 vsoftco 上面的评论也不完全正确。显然你的引用并没有解决我的(前)问题。我本想尽自己的一份力,回馈社区,但在花了半个小时写完我的答案后,你把我赶走了。不确定我想再试一次。
  • @riderBill 依赖类型问题非常频繁地出现,这就是为什么我们中的一些人将这些问题作为规范问题的重复而关闭。那些搜索仍然可以找到将它们指向规范问题和答案的重复项。如果您能解释您的答案将涵盖哪些额外基础,我很乐意重新投票,因为据我所知,您发布的编译器错误都是由缺少 typename 引起的。

标签: c++ stl iterator return-type template-function


【解决方案1】:

奇怪的是,我必须在返回类型周围添加括号才能编译它。也就是说,

 template<typename T> (typename std::vector<T>::iterator)    // Tested--works as expected.
             insertIntoVector(std::vector<T>& vec, const T& val)

工作始终如一,但是

 template<typename T>  typename std::vector<T>::iterator     // Compile errors
             insertIntoVector(std::vector<T>& vec, const T& val)

在 MSVC 2013 上给我问题,但在 MSVC 2012 上编译。我不知道为什么。有人吗?

下面的代码可以在 MSVC 2013 上正确编译和运行。

// The following is based on Matt Austern's article,
// "Why you shouldn't use set (and what you should use instead)"
// (http://lafstern.org/matt/col1.pdf).
// I modified it slightly, mostly just reformatting and adding comments,
// but I also changed it to return an iterator to the inserted element.
// Also changed sorted_vector to sortedVector (cammelCase)

#include <vector>
#include <algorithm>  // std::lower_bound


 template<typename T> (typename std::vector<T>::iterator)  // Tested--works as expected.
             insertIntoVector(std::vector<T>& vec, const T& val)
{  // Insert t into vector vec such that v remains in sorted order
   // and all elements of vec are unique (like a set).
   // This only makes sense if the vector elements are
   // maintained in sorted order.
   // A sorted vector might perform better than a set if
   // there are many more access operations than insertions
   // (smaller storage, fast access via [], ... at the cost
   // of much slower insertions).
   // Note: Type T must have a defined < operator.
   /// Todo: overload this function to allow passing a Compare()
   /// function pointer.

   // std::lower_bound() gives log2(N) + O(1) performance.
   typename std::vector<T>::iterator itr
             = lower_bound(vec.begin(), vec.end(), val);
   if ( (vec.end() == itr) || (val < *itr) )
   {  itr = vec.insert(itr, val);
   }
   return itr;  // return iterator to val in vec.
} // End of insertIntoVector();

【讨论】:

  • 当我编译你的代码时(减去括号),我唯一的问题来自函数主体中 vector&lt;T&gt;::iterator 之前缺少的 typename std::
  • @T.C.我在 MSVC 2013 上尝试过。它现在可以带或不带括号进行编译。我一定是在星期五搞砸了其他事情——我很尴尬地承认这一点,但我没有其他解释。当我删除返回类型上的括号并重新编译时,编译器说“跳过...(未检测到相关更改)”。我猜它认为 () 是多余的。
  • 我的编译器没有抱怨在 itr 声明/定义行的正文中缺少类型名 std::,但是我根据您的建议添加了它以提高健壮性/可移植性,因为您说您有问题用它。你是用 GCC 编译的吗?将来我可能需要它在 Solaris 上运行。我不确定我是如何摆脱几个 std:: 的,因为我没有 using std;文件中的声明。
猜你喜欢
  • 2021-12-09
  • 2014-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-16
  • 1970-01-01
  • 2010-12-19
相关资源
最近更新 更多