T::iterator 出错,其中模板参数 T 可能是 vector<int> 或 list<int>

Posted

技术标签:

【中文标题】T::iterator 出错,其中模板参数 T 可能是 vector<int> 或 list<int>【英文标题】:Error with T::iterator, where template parameter T might be vector<int> or list<int> 【发布时间】:2011-04-13 16:43:40 【问题描述】:

我正在尝试编写一个函数来打印常见 STL 容器(向量、列表等)的表示。我给函数一个模板参数 T,例如,它可能代表向量。我在获取 T 类型的迭代器时遇到问题。

vector<int> v(10, 0);
repr< vector<int> >(v);

...

template <typename T>
void repr(const T & v)

    cout << "[";
    if (!v.empty())
    
        cout << ' ';
        T::iterator i;
        for (i = v.begin(); 
             i != v.end()-1;
             ++i)
        
            cout << *i << ", ";
        
        cout << *(++i) << ' ';
    
    cout << "]\n";

...

brett@brett-laptop:~/Desktop/stl$ g++ -Wall main.cpp
main.cpp: In function ‘void repr(const T&)’:
main.cpp:13: error: expected ‘;’ before ‘i’
main.cpp:14: error: ‘i’ was not declared in this scope
main.cpp: In function ‘void repr(const T&) [with T = std::vector<int, std::allocator<int> >]’:
main.cpp:33:   instantiated from here
main.cpp:13: error: dependent-name ‘T::iterator’ is parsed as a non-type, but instantiation yields a type
main.cpp:13: note: say ‘typename T::iterator’ if a type is meant

我按照编译器的建议尝试了“typename T::iterator”,但只得到了一个更神秘的错误。

编辑:感谢您的帮助!以下是任何想要使用此功能的人的工作版本:

template <typename T>
void repr(const T & v)

    cout << "[";
    if (!v.empty())
    
        cout << ' ';
        typename T::const_iterator i;
        for (i = v.begin(); 
             i != v.end();
             ++i)
        
            if (i != v.begin())
            
                cout << ", ";
            
            cout << *i;
        
        cout << ' ';
    
    cout << "]\n";

【问题讨论】:

发布“更神秘”的错误信息怎么样? 顺便说一句,您可能希望将 v.end()-1 替换为非随机访问迭代器也支持的其他内容。 【参考方案1】:

你需要typename 告诉编译器::iterator 应该是一个类型。编译器不知道它是一个类型,因为在实例化模板之前它不知道 T 是什么。例如,它也可以引用一些静态数据成员。这是你的第一个错误。

您的第二个错误是v 是对const 的引用。因此,您必须使用::const_iterator 而不是::iterator。您不能向常量容器询问非常量迭代器。

【讨论】:

并不是编译器不知道::iterator 是什么,而是标准要求它将其解释为非类型,因为它很好地放入了错误消息中:“依赖-name 'T::iterator' 被解析为非类型,但实例化产生类型" @visitor:使用正确的两阶段实现(读作“非 MSVC”),编译器在第一遍中无法知道 iterator 是什么,因为尚未设置模板参数。参见例如项目 6 和 7 here.【参考方案2】:

T::iterator i; 更改为typename T::const_iterator i;,因为::iteratorT 类型,而vconst &amp;

在限定依赖类型之前,您需要typename。 如果没有typename,则有一条 C++ 解析规则规定,合格的依赖名称应解析为 non-types,即使它会导致语法错误。

typename 声明后面的名称应被视为一种类型。否则,名称将被解释为引用非类型。

【讨论】:

【参考方案3】:

也许这会有所帮助:

Typename 在引用类型的限定依赖名称之前是必需的,除非该名称正在命名基类或在初始化列表中。在模板中使用限定(但不依赖的名称)之前,typename 是可选的,除非在命名基类或初始化列表时再次使用。

【讨论】:

以上是关于T::iterator 出错,其中模板参数 T 可能是 vector<int> 或 list<int>的主要内容,如果未能解决你的问题,请参考以下文章

可持久化树模板

迭代器/可迭代对象/生成器

拆分可变参数模板参数

在成员变量中使用模板类作为模板模板参数时出错

gcc 编译带有大量模板参数的模板类时出错

为啥尝试使用显式类型参数调用模板成员函数时会出错?