2


I have a function, in which const std::map<std::string, Array2D<unsigned short>&>* pDataPool is one of its input parameters. There a code snippet in the function body as follows:

std::map<std::string, Array1D<unsigned short>*> DataBuffers;

if (pDataPool != NULL)
{  
   for (std::map<std::string, Array2D<unsigned short>&>::iterator it = pDataPool->begin();
        it != pDataPool->end(); it++)   // Error 
   {    
       std::string sKeyName = it->first;
       DataBuffers[sKeyName] = new Array1D<unsigned short>(2048);
    }
} 

Compiler output:

1>e:\program files\microsoft visual studio 9.0\vc\include\map(168) : error C2529: '[]' : reference to reference is illegal
1>        f:\tips\tips\fy2svsdataiohandler.cpp(77) : see reference to class template instantiation 'std::map<_Kty,_Ty>' being compiled
1>        with
1>        [
1>            _Kty=std::string,
1>            _Ty=Array2D<unsigned short> &
1>        ] 
1>f:\tips\tips\fy2svsdataiohandler.cpp(77) : error C2440: 'initializing' : cannot convert from 'std::_Tree<_Traits>::const_iterator to  <br/>'std::_Tree<_Traits>::iterator' 
1>        with
1>        [ 
1>            _Traits=std::_Tmap_traits<std::string,Array2D<unsigned short> &,std::less<std::string>,std::allocator<std::pair<const <br/> std::string,Array2D<unsigned short> &>>,false> 
1>        ] 
1>        No constructor could take the source type, or constructor overload resolution was ambiguous 
1>Build log was saved at "file://f:\Tips\Tips\Debug\BuildLog.htm" 
1>Tips - 2 error(s), 0 warning(s) 
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ========== 
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
GoldenLee
  • 737
  • 2
  • 13
  • 28
  • In the code segement, the first line should be: std::map*> DataBuffers; – GoldenLee Jun 14 '11 at 07:19
  • Sorry, I don't know how to escape the special caracter"<" and ">" used in SO. So, I wrote an ugly string const std::map'<'std::string, Array2D'<'unsigned short'>'&'>'* pDataPool. It should be const std::map& >* pDataPool. – GoldenLee Jun 14 '11 at 07:24
  • There's a massive panel entitled "Formatting" that appears right next to the space where you write your question. Read it! – Lightness Races in Orbit Jun 14 '11 at 07:30

4 Answers4

2

Looks like a pDataPool is constant. So you need to use const_iterator:

std::map<std::string, Array2D<unsigned short>&>::const_iterator it = pDataPool->begin()
Kirill V. Lyadvinsky
  • 97,037
  • 24
  • 136
  • 212
1

Look here: Why are arrays of references illegal?

You should use pointers instead of references. Also pointers have additional advantage: it explicit indicate that data will be changed.

Community
  • 1
  • 1
Kirill
  • 3,364
  • 2
  • 21
  • 36
1
for (std::map<std::string, Array2D<unsigned short>&>::iterator it

should read

for (std::map<std::string, Array2D<unsigned short>*>::iterator it

You may not store references in a standard container; (you can wrap them using std::ref, but that's a topic for another day...).

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • Dear Tomalak Geret'kal Maybe you're right. I changed all my parameter list from by reference std::map&> to std::map*> pointer reference. My program passed compiling now. Why do I wrap Array2D with std::ref? Could you shed a little light on this topic today? Thank you again! – GoldenLee Jun 14 '11 at 07:52
  • @GoldenLee: Please use the "@name" syntax to generate SO notifications. – Lightness Races in Orbit Jun 14 '11 at 15:37
  • @GoldenRef: Why do you what? You don't. I'm confused. And you mean "pointer" not "pointer reference". – Lightness Races in Orbit Jun 14 '11 at 15:38
0

There've been some answers already, but let me summarize. Pay attention to the mapped type (which is a pointer! And is it 1D or 2D?) -- or even better, use typedefs to deconfuse yourself:

typedef Array3D<unsigned short> Array; // decide on 1D, 2D, 3D, ...!
typedef std::map<std::string, Array*> ArrayMap;

ArrayMap DataBuffers;

ArrayMap * pDataPool;

/* ... */

if (pDataPool != NULL)
{  
  for (ArrayMap::const_iterator it = pDataPool->begin(), end = pDataPool->end(); it != end; ++it)
  {    
    const std::string & sKeyName = it->first;
    DataBuffers[sKeyName] = new Array(2048); // terrible, use shared_ptr<Array>!
  }
}

Attention to detail is the key. A few notes:

  • Having a raw pointer as the mapped type is terrible; what if the element already exists and you just overwrite it with a new pointer? Memory leak! You should seriously consider making your map a std::map<std::string, std::tr1::shared_ptr<Array> >.

  • A string makes for a poor key type if you have lots of entries. Consider std::tr1::unordered_map instead. (If you're in C++0x or MSVC10, omit the ::tr1.)

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084