gpt4 book ai didi

C++ VS2008 - 类模板实例化的奇怪错误

转载 作者:太空宇宙 更新时间:2023-11-04 13:46:31 25 4
gpt4 key购买 nike

我正在将一个相对较大的代码从 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::pair 调用的 std::swap 函数中,此时(“实用程序”文件,标准包含):

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.0\vc\include\utility(22) : error C3892: '_Left' : you cannot assign to a variable that is const
c:\program files (x86)\microsoft visual studio 9.0\vc\include\utility(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.0\vc\include\utility(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.0\vc\include\utility(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.0\vc\include\deque(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.0\vc\include\queue(24) : see reference to class template instantiation 'std::deque<_Ty>' being compiled
with
[
_Ty=std::pair<const int,CMyClass *>
]
c:\users\my_name\desktop\test\test\test.cpp(42) : see reference to class template instantiation 'std::queue<_Ty>' being compiled
with
[
_Ty=std::pair<const int,CMyClass *>
]
c:\users\my_name\desktop\test\test\test.cpp(81) : see reference to class template instantiation 'CMapCollector<TMap>' being compiled
with
[
TMap=tMyMap
]
c:\program files (x86)\microsoft visual studio 9.0\vc\include\utility(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::queue 和 std::map 的“键”(因此是 std::pair 的“第一个”)有关,根据定义是不变的,但我没有想不出怎么解决

最佳答案

我最终通过使用常量指针队列解决了问题,所以我只存储指向 std::pair 的指针而不是 std::pair 本身的值,这也更有意义:

std::queue<const tValueType *>

所以最终的 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());
}

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 上也编译得很好

关于C++ VS2008 - 类模板实例化的奇怪错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25645205/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com