dependent name is not a type [关于模板类中的迭代器]

来源:互联网 发布:尖头高跟鞋淘宝 编辑:程序博客网 时间:2024/06/05 06:03

MSDN相关文档:https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=ZH-CN&k=k(C4346)&rd=true

 

如下一个模板类:

template <class T>
class CTest
{
public:
 typedef map<int, T> TEMPLATE_MAP;
 typedef map<int, T>::iterator TEMPLATE_MAP_ITER;
};

表面上看去没有问题,实际编译的时候会发现问题:

------ Build started: Project: typename, Configuration: Debug Win32 ------

Compiling...
main.cpp
e:\My Documents\Visual Studio Projects\typename\typename\main.cpp(10) : warning C4346: 'std::map<int,_Kty>::iterator' : dependent name is not a type
        prefix with 'typename' to indicate a type

        e:\My Documents\Visual Studio Projects\typename\typename\main.cpp(11) : see reference to class template instantiation 'CTest<T>' being compiled
e:\My Documents\Visual Studio Projects\typename\typename\main.cpp(10) : error C2146: syntax error : missing ';' before identifier 'TEMPLATE_MAP_ITER'
e:\My Documents\Visual Studio Projects\typename\typename\main.cpp(10) : error C2501: 'CTest<T>::TEMPLATE_MAP_ITER' : missing storage-class or type specifiers

Build log was saved at "Documents\Visual Studio Projects\typename\typename\Debug\BuildLog.htm"
typename - 2 error(s), 1 warning(s)


---------------------- Done ----------------------

    Build: 0 succeeded, 1 failed, 0 skipped

 

1>------ 已启动生成: 项目: typename, 配置: Debug Win32 ------
1>正在编译...
1>main.cpp
1>e:\my documents\visual studio 2008\projects\typename\typename\main.cpp(10) : warning C4346: “std::map<int,T>::iterator”: 依赖名称不是类型
1>        用“typename”为前缀来表示类型
1>        e:\my documents\visual studio 2008\projects\typename\typename\main.cpp(11): 参见对正在编译的类 模板 实例化“CTest<T>”的引用
1>e:\my documents\visual studio 2008\projects\typename\typename\main.cpp(10) : error C2146: 语法错误 : 缺少“;”(在标识符“TEMPLATE_MAP_ITER”的前面)
1>e:\my documents\visual studio 2008\projects\typename\typename\main.cpp(10) : error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int
1>生成日志保存在“file://e:\My Documents\Visual Studio 2008\Projects\typename\typename\Debug\BuildLog.htm”
1>typename - 2 个错误,1 个警告
========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========

在定义map<int, T>::iterator的时候,由于iterator依赖具体的map,而map中包含了一个模板T,在没有实例化的时候不能确定其类型。

根据编译错误信息,加一个typename前缀即可。

正确的写法:

template <class T>
class CTest
{
public:
 typedef map<int, T> TEMPLATE_MAP;
 typedef typename map<int, T>::iterator TEMPLATE_MAP_ITER;
};

这里可能会想到为什么TEMPLATE_MAP不需要typename,因为它不依赖其他的名称。

【注】以上代码在VC6.0是可以编译通过的;在VS200*以及g++编译不能通过。

 

========================================================================================================

原始问题比较隐蔽,在VS200*中编译运行正常,g++上出现了问题:

代码如下:(非问题原始代码)

#include <iostream>
#include <map>
using namespace std;

template <class T>
class CTest
{
public:
 /*********************** 1 ***************************/
 typedef map<int, T> TEMPLATE_MAP;
 //typedef map<int, T>::iterator TEMPLATE_MAP_ITER;
 /*****************************************************/

 /*********************** 2 ***************************/
 struct Node
 {
  T t;
 };
 typedef map<int, Node> TEMPLATE_NODE_MAP;
 //typedef map<int, Node>::iterator TEMPLATE_NODE_MAP_ITER;
 /*****************************************************/

 void Add(int key, T value)
 {
  m_map.insert(make_pair(key, value));
 }

 void Test()
 {
  for (map<int, T>::iterator it = m_map.begin(); it != m_map.end(); ++it)
  {
   cout << it->first << " " << it->second << endl;
  }
 }

private:
 TEMPLATE_MAP m_map;
};

int main()
{
 CTest<double> t;
 t.Add(1, 3);
 t.Add(2, 4);
 t.Test();
 return 0;
}

这在windows下编译运行良好,在linux下g++编译结果:

main.cpp: In member function 'void CTest<T>::Test()':
main.cpp:30: error: expected `;' before 'it'
main.cpp:30: error: 'it' was not declared in this scope
main.cpp: In member function 'void CTest<T>::Test() [with T = double]':
main.cpp:45:   instantiated from here
main.cpp:30: error: dependent-name 'std::map::iterator' is parsed as a non-type, but instantiation yields a type
main.cpp:30: note: say 'typename std::map::iterator' if a type is meant

和windows下的提示信息有一些差距,但是最后一行也给出了解决办法

0 0
原创粉丝点击