views:

288

answers:

4

Hi,

I have an enum StackIndex defined as follows:

typedef enum 
{
    DECK,
    HAND,
    CASCADE1,
    ...
    NO_SUCH_STACK
} StackIndex;

I have created a class called MoveSequence, which is a wrapper for a std::deque of a bunch of tuples of the form <StackIndex, StackIndex>.

class MoveSequence
{
    public:
        void AddMove( const tpl_move & move ){ _m_deque.push_back( move ); }
        void Print();
    protected:
    deque<tpl_move> _m_deque;
};

I thought I could create a static std::map member of the MoveSequence class, which would translate a StackIndex to a std::string, for use by the Print() function. But when I tried, I got the error:

"error C2864: 'MoveSequence::m' : only static const integral data members can be initialized within a class"

If its not possible to created a std::map as a static member, is there another way to create a std::map that translates a StackIndex to a std::string that can be used to print out MoveSequence objects?

thanks

Beeband.

+6  A: 

You need to move the initialization into a source file:

// header
struct foo
{
    typedef std::map<unsigned, std::string> the_map;
    static const the_map m;
};

// source
const foo::the_map foo::m(...);

With however you want to initialize it. C++0x removes this restriction.

Keep in mind Boost.Assign makes this quite easy:

#include <boost/assign.hpp>
const foo::the_map foo::m = boost::assign::map_list_of(1, "a")(2, "b");
GMan
what are those iters?
anon
I dunno, just whatever he had in his header (i.e. I'm guessing). I'll change it.
GMan
Thanks GMan! I tried the boost assign thing in the class, that's what gave me the error.
BeeBand
Can't find about static initializers in C++0x, if it is static, which translation unit has the storage? I've seen it for non-static members in http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2628.html
Arkaitz Jimenez
I thought maybe `static const` had a special case, but I can't find it either.
GMan
+3  A: 

You can make a std::map a static member of the class. What you can't do is initiliaze it within the class definition. Note that this is what the error is telling you:

error C2864: 'MoveSequence::m' : only static const integral data members can be *initialized* within a class

So, you want to have this in the header:

class MoveSequence
{
    static std::map<StackIndex, std::string> _m_whatever;
};

And then in a source (.cpp) file you want this:

std::map<StackIndex, std::string> MoveSequence::_m_whatever( ..constructor args.. );
R Samuel Klatchko
+1  A: 

As others have suggested, you need to create a static instance of the map in a C++ source file. When it comes to initialising it, I suggest creating a static function in MoveSequence:

class MoveSequence {

   static void InitMap() {
      if ( m_map.size() == 0 ) {
           m_map.insert( std::make_pair( DECK, "deck" ) );
            m_map.insert( std::make_pair( HAND, "hand" ) );
      }
   }
   ...
};

You can then call this from MoveSequence's constructor.

Oh, and BTW there is no need for the typedef on the enum:

enum StackIndex {
  ...
};
anon
Thanks Neil. I suppose with the boost::assign thing, I was trying to get away with typing less, as I have about 24 `StackIndex`s in my enum :).
BeeBand
Neil, why not `if ( !m_map.empty() )`?
GMan
@Gman - why not, indeed - sheer incompetence on my part.
anon
Ha, I wonder what that makes me.
GMan
+1  A: 

I don't think you want a std::map (although all of the other answers here are good ones as to how to do that). It sounds like you just want a static C array of strings, where the index is the enum value.

const char* const stacknames[] = 
{
    "deck",
    "hand",
    "cascade1"
};

Then stacknames[DECK] is "deck", etc.

Terry Mahaffey
Brilliant. I really do love this site for all the new ideas. However, is there a big difference in speed between a std::map and an array of strings?
BeeBand
Yes, an array of strings will be much faster.
Terry Mahaffey
If StackIndex is consecutive integral values (or at least does not have too many large holes in it), an array is definitely the way to go.
R Samuel Klatchko