初学stl,写了个用于显示容器内容的函数模板,但是在编译的时候就出错了。
ps.我只想用一个函数就可以显示所有容器,而不管它是关联容器还是序列容器。
函数模板代码如下:
template<class _COLL>
void PrintAll( _COLL container)
{
for(_COLL::iterator it = container.begin(); it != container.end() ; ++it)
{
string tmpStr;
if( (string( typeid(*it).name() )).find_first_of("struct std::pair") != string::npos )
{
tmpStr = (*it).second;
}
else
{
tmpStr = *it ;
}
std::cout << "# " << tmpStr << std::endl;
}
}
然后在main中,调用PrintAll分别显示一个multimap和list
std::multimap<int,string> my1stMap;
my1stMap.insert( std::make_pair(1,"Y") );
my1stMap.insert( std::make_pair(2,"H") );
my1stMap.insert( std::make_pair(3,"J") );
my1stMap.insert( std::make_pair(3,"Ji") );
PrintAll(my1stMap);
list<int> intList;
intList.push_back(1);
intList.push_back(1);
intList.push_back(1);
PrintAll(intList);
编译时报错:
Error 11 error C2679: binary '=' : no operator found which takes a right-hand operand of type 'std::pair<_Ty1,_Ty2>' (or there is no acceptable conversion) e:\learnspace\Boost\Boost\Boost.cpp 72 Boost
Error 12 error C2228: left of '.second' must have class/struct/union e:\learnspace\Boost\Boost\Boost.cpp 68 Boost
我觉得,应该是编译器检查“PrintAll(my1stMap)”时,因为it是个pair,所以tmpStr = *it 这条语句就通不过了。我本意是想在运行时通过typeid来区分,可是在编译期间就出错了,怎么呢?麻烦知道的c++大牛回答一下。
我不是大牛,对C++稍有了解而已.
1, 不行.
没有通用的方法能做到这样的事情. 一个通用性非常差的方法可以这样做:
template<class _COLL>
void PrintAll( _COLL container)
{
for(_COLL::iterator it = container.begin(); it != container.end() ; ++it)
{
string tmpStr;
if( (string( typeid(*it).name() )).find_first_of("struct std::pair") != string::npos )
{
tmpStr = (std::multimap<int,string>(*it)).second; //这里你根本不知道key是什么类型的--除非专门为multimap<T1,T2>做一个
特化
}
else
{
tmpStr = string(*it ); //这里你也不知道collection里的数据是不是string,只能强制转型,后果是很可怕的
}
std::cout << "# " << tmpStr << std::endl;
}
}
2, 你用了C++,但是没有接受C++的思想,你的作法里动态的味道很浓. C++里没有Reflection,所以对编译期和运行期的区分很明显.
不要使用强制转型--这个相当于原子弹级别的东西,威力太大.强制转型本身在运行时几乎总是成功的--不像C#里会有InvalidCastException扔出来, 但是把Poison转型成Food的后果,是要出人命的.
学习....