"std::vector<T>::iterator it;"无法编译。

19

我有这个函数:

    template<typename T>
    void Inventory::insertItem(std::vector<T>& v, const T& x)
    {
        std::vector<T>::iterator it; // doesn't compile
        for(it=v.begin(); it<v.end(); ++it)
        {
            if(x <= *it) // if the insertee is alphabetically less than this index
            {
                v.insert(it, x);
            }
        }
    }

而g++则会给出以下错误:

src/Item.hpp: In member function ‘void
yarl::item::Inventory::insertItem(std::vector<T, std::allocator<_CharT> >&, const T&)’:  
src/Item.hpp:186: error: expected ‘;’ before ‘it’  
src/Item.hpp:187: error: ‘it’ was not declared in this scope

这一定是某些简单的问题,但是我盯着它看了十分钟也没发现什么问题。有其他人看到了吗?


2
顺便提一下,您不应该使用it < v.end() -- 它可以与vector一起使用,但不能与list和其他容器一起使用。您应该始终使用it != v.end()来确保没有问题。 - Peter Alexander
2个回答

37

不妨试试这个:

typename std::vector<T>::iterator it;

这是一个页面,描述了如何使用typename以及为什么在这里需要它。


简洁回答+1,详细解释请提供链接。 - stinky472
简而言之:在引用类型时,必须在限定的依赖名称前加上 typename。限定名称是指任何使用 :: 作用域运算符的名称(例如 std::cout、OuterClass::InnerClass 等)。依赖名称是指任何使用通用模板的名称(例如 GenericWrapperClass<T>、vector<T> 等)。 - Tonia Sanzo

8

你现在的做法效率低下,建议使用二分查找算法代替:

#include <algorithm>

template <typename T>
void insertItem(std::vector<T>& v, const T& x)
{
    v.insert(std::upper_bound(v.begin(), v.end(), x), x);
}

2
+1 -- 比我先说了。还值得一提的是,由于当前代码在插入后没有跳出循环,它通常会在不需要的地方插入新项目的额外副本。 - Jerry Coffin
2
@Jerry:更糟糕的是,如果向量的大小等于其容量,insert将使之前获取的所有迭代器无效,因此++it将直接导致未定义行为。 - fredoverflow
1
+1(但我希望能够给+10)。第二次查看代码时,与代码的运行时行为相比,构建错误只是一个小问题。 - stinky472
1
你的回答在4年后帮了我。YOLO! - cegprakash

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接