最近翻出自己之前常用的main函数参数分析类,却意外发现自己原来一直踩着一个语法“陷阱”。
具体的情况是:这是个模板类,内容大概为:
template<typename T>
class MainArgParser
{
//...
vector<basic_string<T>>::iterator iter;
//...
};
过去一两年用这个类,一直没有出现什么问题。近日换了个环境,又回到了ubuntu下工作。昨天用这个类写了个程序,编译却出错了,又是满屏的stl系列。g++说不能用有歧义的‘>>’,要加空格‘> >’。这倒不是什么大问题,只是一直以为只有vc6的编译器才会报这样的错。
修改成‘vector<basic_string<T> >::iterator iter;’再编译,结果还是有错,提示iter前缺少分号。把代码拿到vs2010去,编译通过。一时觉得懵了,其实这个类最早就是我几年前在ubuntu下写代码时弄出来的,一直不断完善用到今天。不过当时不是模板类,是迁到windows下工作之后才加上去的。看来问题就和这个模板参数有关了。
上网查了下资料,编译器在实例化T前不知道vector<basic_string<T>>是什么类型,自然推不出
vector<basic_string<T> >::iterator;要使用typename关键字,提示编译器。于是代码改成
template<typename T>
class MainArgParser
{
//...
typedef typename vector<basic_string<T> > string_array_t;
string_array_t::iterator iter;
//...
};
问题解决了,我也反思了一下:
1.又是typename关键字,我发现我之前对这个关键字真的没有一点认识。可以参考我之前的文章 Modern C++ Design学习笔记:Int2Type, Type2Type, TypeSelect 。
2.为啥vs2010下就编译通过了?为啥g++就这么严格了?据闻g++是最接近c++标准的编译器,它这么做应该是有充分理由的。不过像我这种小码农,哪会认真去看标准......感觉这些typename从人惯性思维的角度来说是可有可无的,所以像这种编译错误太不人性化了吧。不知道g++是不是有编译选项跟这个有关的呢?
3.以后打算复用的东东,现在各主流编译器跑一下,有问题早发现,以免使用的时候耽误了时间。