C++VS2008-类模板实例化出现奇怪错误
C++ VS2008 - Strange errors on class template instantiation
我正在将一个相对较大的代码从Linux移植到Windows(Visual Studio 2008,我必须使用它)。我完成了移植,它正在工作,但我不得不对一小段代码进行注释,因为Visual Studio在这方面出现了错误,我无法完全理解原因。因此,基本上,有一个函子从std::map中收集满足某个条件的所有"项",定义如下:
/*
* Map collector
*/
template<class TMap>
class CMapCollector
{
public:
typedef typename TMap::value_type tValueType;
CMapCollector(void)
{ }
void operator () (const tValueType& rcValue)
{
if (CheckCondition(rcValue))
mCollector.push(rcValue);
}
bool NextResult(void) const
{
return (!mCollector.empty());
}
tValueType GetResult(void)
{
if (!NextResult())
return tValueType();
tValueType curr_value = mCollector.front();
mCollector.pop();
return curr_value;
}
private:
virtual bool CheckCondition(const tValueType& rcValue) const = 0;
typedef std::queue<tValueType> tCollectorContainer;
tCollectorContainer mCollector;
};
然后,通过继承它,定义了一些收集器类。我写了一个显示错误的小例子,以便从所有其他代码中提取它:
/*
* Some class
*/
class CMyClass
{
public:
CMyClass(const int cNum) : mNum(cNum)
{ }
bool DifferentFrom(const int cFrom) const
{
return (Get() != cFrom);
}
bool EqualTo(const int cTo) const
{
return (Get() == cTo);
}
private:
int Get(void) const
{
return mNum;
}
int mNum;
};
/* Some map definition */
typedef std::map<int, CMyClass *> tMyMap;
/*
* Real collectors
*/
class CNoNullCollector : public CMapCollector<tMyMap>
{
private:
bool CheckCondition(const tValueType& rcValue) const
{
return (rcValue.second->DifferentFrom(0));
}
};
class CValueCollector : public CMapCollector<tMyMap>
{
public:
CValueCollector(const int cValue) : mValue(cValue)
{ }
private:
bool CheckCondition(const tValueType& rcValue) const
{
return (rcValue.second->EqualTo(mValue));
}
int mValue;
};
/*
* main
*/
int main(int argc, char *argv[])
{
tMyMap my_map;
/* Insert some value */
my_map.insert(std::make_pair(1, new CMyClass(0)));
my_map.insert(std::make_pair(2, new CMyClass(1)));
my_map.insert(std::make_pair(3, new CMyClass(2)));
my_map.insert(std::make_pair(4, new CMyClass(2)));
my_map.insert(std::make_pair(5, new CMyClass(3)));
/* Collect values */
CNoNullCollector collector = std::for_each(my_map.begin(), my_map.end(), CNoNullCollector());
while (collector.NextResult())
{
CNoNullCollector::tValueType curr_result = collector.GetResult();
/* Do something ... */
}
/* Free memory, not written ... */
return 0;
}
这段代码在使用g++的Linux上编译得很好(我尝试过使用机器上提供的g++4.2和4.9)。我还试用了Visual Studio 2013,效果很好。然而,使用VS2008(以及VS2010)编译它时,它在实例化类模板"CMapCollector"时会出现错误。错误出现在std::swap函数中,从std::pair调用,此时("实用程序"文件,标准包含):
template<class _Ty> inline
void swap(_Ty& _Left, _Ty& _Right)
{ // exchange values stored at _Left and _Right
if (&_Left != &_Right)
{ // different, worth swapping
_Ty _Tmp = _Left;
_Left = _Right; // <-- error C3892: '_Left' : you cannot assign to a variable that is const
_Right = _Tmp; // <-- error C3892: '_Right' : you cannot assign to a variable that is const
}
}
这是完整的错误消息:
c:program files (x86)microsoft visual studio 9.0vcincludeutility(22) : error C3892: '_Left' : you cannot assign to a variable that is const
c:program files (x86)microsoft visual studio 9.0vcincludeutility(31) : see reference to function template instantiation 'void std::swap<_Ty>(_Ty &,_Ty &)' being compiled
with
[
_Ty=int
]
c:program files (x86)microsoft visual studio 9.0vcincludeutility(64) : see reference to function template instantiation 'void std::_Swap_adl<_Ty1>(_Ty &,_Ty &)' being compiled
with
[
_Ty1=int,
_Ty=int
]
c:program files (x86)microsoft visual studio 9.0vcincludeutility(61) : while compiling class template member function 'void std::pair<_Ty1,_Ty2>::swap(std::pair<_Ty1,_Ty2> &)'
with
[
_Ty1=const int,
_Ty2=CMyClass *
]
c:program files (x86)microsoft visual studio 9.0vcincludedeque(518) : see reference to class template instantiation 'std::pair<_Ty1,_Ty2>' being compiled
with
[
_Ty1=const int,
_Ty2=CMyClass *
]
c:program files (x86)microsoft visual studio 9.0vcincludequeue(24) : see reference to class template instantiation 'std::deque<_Ty>' being compiled
with
[
_Ty=std::pair<const int,CMyClass *>
]
c:usersmy_namedesktoptesttesttest.cpp(42) : see reference to class template instantiation 'std::queue<_Ty>' being compiled
with
[
_Ty=std::pair<const int,CMyClass *>
]
c:usersmy_namedesktoptesttesttest.cpp(81) : see reference to class template instantiation 'CMapCollector<TMap>' being compiled
with
[
TMap=tMyMap
]
c:program files (x86)microsoft visual studio 9.0vcincludeutility(23) : error C3892: '_Right' : you cannot assign to a variable that is const
如果我注释类模板实例化的部分:
CNoNullCollector collector = std::for_each(my_map.begin(), my_map.end(), CNoNullCollector());
while (collector.NextResult())
{
CNoNullCollector::tValueType curr_result = collector.GetResult();
/* Do something ... */
}
编译将成功完成。我知道恒常有一些问题,但我不明白在哪里。g++为什么能成功编译它?
编辑:
我知道这与std::队列和std::映射的"键"(因此也是std::对的"第一个")有关,但我不知道如何解决它
我最终通过使用一个常量指针队列来解决问题,所以我只存储指向std::对的指针,而不是std:对本身的值,这也更有意义:
std::queue<const tValueType *>
因此,最终的地图收集器类变成:
/*
* Map collector
*/
template<class TMap>
class CMapCollector
{
public:
typedef typename TMap::value_type tValueType;
CMapCollector(void)
{ }
void operator () (const tValueType& rcValue)
{
if (CheckCondition(rcValue))
mCollector.push(&rcValue);
}
bool NextResult(void) const
{
return (!mCollector.empty());
}
const tValueType *GetResult(void)
{
if (!NextResult())
return NULL;
const tValueType *curr_value = mCollector.front();
mCollector.pop();
return curr_value;
}
private:
virtual bool CheckCondition(const tValueType& rcValue) const = 0;
typedef std::queue<const tValueType *> tCollectorContainer;
tCollectorContainer mCollector;
};
这与VS2008 编译也很好
相关文章:
- 为什么包含windows.h会产生语法错误,从而阻止类的实例化?(C2146,C2065)
- 错误的cv::face FacemarkLBF实例化
- 无法使用 SWIG 在 Python 中实例化C++类(获取属性错误)
- gcc出现不明确的模板实例化错误
- 尝试实例化模板类的对象时出现"No Matching Constructor"错误
- 无法实例化抽象类错误
- 错误 C2280 / 在 std::vector 中实例化对象时复制构造函数出现问题?
- 模板实例化分析错误
- unique_ptr 使用尚未定义的参数进行实例化不会导致错误
- 与模板实例化相关的编译错误
- 从模板实例化/类型推断中查找错误消息的实际来源
- 类模板实例化错误
- 错误 C2908:显式专用化; 已被实例化
- C++11 列出 push_back() 实例化错误
- 如何修复错误C2259:无法实例化抽象类
- 使用非量表类型实例化模板时修复编译错误
- 由于命名空间而导致的对象实例化错误
- 无法在好友函数中实例化类?我没有得到在范围错误中声明
- 实例化对象时如何修复分段故障错误
- 将 SFINAE 上下文中不正确的模板实例化的硬错误转变为软错误