2014-09-03 57 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