Ads

 

How to make a map of variant in C++

This code is used by RainbruRPG to store any scalar types in a single class instance. It's already in use since revision 254 to save game states values when switching fullscreen or changing screen resolution.
C++ map of variant example

The map class

It's basically a map of boost::variant using std::string as map key. I decided to use function template setter and getter to have a standardized exception-based error handling, but you could have multiple parameter-based specialized getter/setter (void set(bool), void set(int)...).

Here is the example implementation :
#include <boost/variant.hpp>
#include <map>
#include <string>

using namespace std;
using namespace boost;

/** The basic tStateMap value type */
typedef variant<int,float,bool,string> tStateMapType;

/** The map that stores StateSaver properties */
typedef map<std::string, tStateMapType> tStateMap;

/** A property map used to store some GameState values */
class StateSaver
{
public:
  StateSaver(){};
  ~StateSaver(){};

  bool exists(const string&)const;

  template<typename T> void set(const string& key, const T& value)
  {
    if (exists(key))
      throw "Duplicate key";
      
    mStates[key] = value;
  }

  template<typename T> const T& get(const string& key)const
  {
    if (!exists(key))
      throw "Can't find key";

    return boost::get<T>(mStates.find(key)->second);
  }

  /* Here you have a boost::bad_get exception if you try 
   * to get an existing key using a wrong type
   */
  bool exists(const string& key)const
  {
    if (mStates.find(key) == mStates.end())
      return false;

    return true;
  }

private:
  tStateMap mStates;                 // The property map
};

How to use it

Since It's a simple template-functions based class, you need to call it with a type specifier :
StateSaver sv;
sv.set<bool>("mykey", true);
...
bool b = sv.get<bool>("mykey");

Conclusion

This class can be (and is actually) used to store many other complex types. The current implementation in StateSaver.hpp and StateSaver.cpp is actually used by MainMenu::save() to save CEGUI windows position and status using subkeys.

Comments

Ads