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;
,因为::iterator
是T
类型,而v
是const &
。
在限定依赖类型之前,您需要typename
。
如果没有typename
,则有一条 C++ 解析规则规定,合格的依赖名称应解析为 non-types
,即使它会导致语法错误。
typename
声明后面的名称应被视为一种类型。否则,名称将被解释为引用非类型。
【讨论】:
【参考方案3】:也许这会有所帮助:
Typename 在引用类型的限定依赖名称之前是必需的,除非该名称正在命名基类或在初始化列表中。在模板中使用限定(但不依赖的名称)之前,typename 是可选的,除非在命名基类或初始化列表时再次使用。
【讨论】:
以上是关于T::iterator 出错,其中模板参数 T 可能是 vector<int> 或 list<int>的主要内容,如果未能解决你的问题,请参考以下文章