2014-09-03 100 views
1

我正在从Linux移植一个相对较大的代码到Windows(我必须使用Visual Studio 2008)。 我完成了移植并且正在工作,但是我不得不评论一小段代码,因为Visual Studio给出了这个错误,我无法准确理解原因。 所以,基本上,存在从一个std收集了函子::所有的“项目”是satify一定的条件下,这样定义的映射:从它继承C++ VS2008 - 类模板实例化上的奇怪错误

/* 
* 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; 
} 

此代码编译细的Linux上的g ++(我试图与两克++ 4.2和4.9,可在机)。 我也尝试过使用Visual Studio 2013,它很好。 但是,使用VS2008(以及VS2010)进行编译时,它会在实例化类模板“CMapCollector”时发生错误。 的错误是在标准::交换函数,从标准::对叫,在这一点(“实用程序”的文件,一个标准包括):

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 ::队列,性病::地图的“钥匙”(因此“第一”的标准::对)是不变根据定义,但我没有弄清楚如何解决它

回答

0

我终于通过使用一个常量指针的队列来解决,所以我只是将指针存储到std :: pair而不是std ::的值这使得也更有意义:

std::queue<const tValueType *> 

所以最终的地图收藏家类成为S:

/* 
* 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