Putting SDL surfaces in a map, along with file names - c++

I'm very new to using maps in C++, so I am having some difficulties using it for my SDL surfaces. This is what I've tried (not working):
map <SDL_Surface*, char*> mSurfaceMap;
mSurfaceMap.insert(pair<SDL_Surface*, char*>(m_poSurfaceTest, "..//..//gfx//testImage.png"));
The idea is to put all surfaces and their corresponding image files in a map to easily initialize them and do IMG_Load() on them, as well as free them when closing the program.
If this is a bad solution for it, please point me in the right direction. I first thought of making two arrays, but I wanted to try this instead, as I felt it was a more elegant solution. If the solution is ok, I'd love to hear what I am doing wrong in the code.

This code works for me. Output is as expected:
#include <map>
#include <stdio.h>
using std::map;
using std::pair;
struct Custom
{
int val;
Custom() {val=0;}
};
int main(int argC,char* argV[])
{
map<Custom*,char*> mMap;
Custom* test = new Custom;
mMap.insert(pair<Custom*,char*>(test,"Test"));
printf("%s\n",mMap[test]);
return 0;
}

std::map is great for looking up data by an ordered key, it is usually implemented as a balanced binary tree that gives O(log n) look-up time. If the look-up order doesn't matter then a std::hash_map will be a better choice with an O(1) look-up time.
The problem with using a pointer as your key in either container is that the they will index by the integer address of the pointer, not the value of what is pointed to.
std::string, however, has value semantics and implements the less-than operator which will let the container index by the value of the string.
You may also want to put your surface in a smart pointer for memory management purposes.
typedef std::tr1::shared_ptr<SDL_Surface> surface_pointer;
typedef pair<std::string, surface_pointer > surface_pair;
std::map<std::string, surface_pointer > mSurfaceMap;
mSurfaceMap.insert(surface_pair("..//..//gfx//testImage.png", surface_pointer(m_poSurfaceTest)));
A couple of other thoughts...
If you don't need the look-up functionality, and are just using a container for housekeeping, then a simple std::vector<std::pair<std::string, SDL_Surface*> > would probably suffice for what you need.
Or, if you're storing the surfaces as members already (assuming from the variable name) then you could store the member variables as a tr1::unique_ptr<SDL_Surface> and when the containing class is deleted so will the SDL_Surface be deleted. For this to work however you need to provide a custom deallocator for the tr1::unique_ptr, that will teach it how to free an SDL_Surface*.
struct SdlSurfaceDeleter {
void operator() (SDL_Surface*& surface) {
if (surface) {
SDL_FreeSurface(surface);
surface = NULL;
}
}
};
Then you would specify your members like this (a typedef makes it less verbose):
typedef std::tr1::unique_ptr<SDL_Surface, SdlSurfaceDeleter> surface_ptr;
class MyClass {
public:
MyClass(const std::string& path)
: m_poSurfaceTest(IMG_Load(path.c_str()) { }
surface_ptr m_poSurfaceTest;
};

Related

What's the best way to store a maya api object inside an std::map that will never become stale? c++

I have an std::map that I'm using to cache some objects info and I will be using that later, I'd like to have my object as a key so it takes as little time as possible to access it.
I was thinking of converting the UUID to string but I realised you can actually end up with duplicated uuids if the object gets brought to the scene as a reference multiple times.
I've also tried with adding an MDagPath but it won't allow me to store that into an std::map. I imagine I'd have to make it hashable but I can't think of a way to do that safely. Using a name I also think it's a big nono since it can be renamed.
Thanks for the help. I hope I was clear enough with my problem.
std::map isn't a hash map (you'd want unordered_map for that). As for adding an MDagPath to a std::map, you could do it via something along these lines:
// I don't think this is defined for dagpath?
// So you should be able to define it for MDagPath.
static inline bool operator < (const MDagPath& a, const MDagPath& b) {
return a.fullPathName() < b.fullPathName();
}
std::map<MDagPath, MyObjectInfo> myMap;
Alternatively, if you want to generate a lookup based on the object, then you can use MObjectHandle. It may still go stale, but at least it has the isAlive() and isValid() methods to tell you when it is stale.
You could insert that into an unordered_map
namespace std {
// override the std::hash for the MObjectHandle
template <>
struct hash< MObjectHandle >
{
std::size_t operator()(const MObjectHandle& k) const
{
return k.hashCode();
}
};
}
std::unordered_map<MObjectHandle, MyObjectInfo> myMap;
(code is untested - I don't have access to Maya at the moment)

C++ what is proper way to include STL container in my class?

To begin with, I'm new to C++/OOP.
I want to include a std::map in my class and am wondering about how to provide users of my class the map typedefs and capabilities. Do I need to do as in the simple example below? (I've only shown a subset to indicate what I'm trying to do)
It doesn't feel right that I have to do this for any class where I've included a container (even for a subset of map methods).
It also seems like a class maintenance issue (e.g. might not need some map method today, but it becomes needed in the future)
p.s. aside from replying to this question, any other corrections/feedback to the example below are appreciated.
#include <map>
#include <string>
class Inventory {
public:
typedef std::string key_type;
typedef std::string mapped_type;
typedef std::map<key_type, mapped_type>::value_type value_type;
Inventory() { }
Inventory(int lotNum) : lotNum_(lotNum) { }
void insert(const value_type& el) { cars_.insert(el); }
//
// TODO: iterators, erase, etc
//
private:
int lotNum_;
std::map<key_type, mapped_type> cars_;
};
int main() {
Inventory ourCars(1);
ourCars.insert( Inventory::value_type( "BMW","ABC123" ) );
return 0;
}
Here is how I would think about this problem. Think of your class interface and implementation separately. The user shouldn't need to know what you're doing behind the scenes - what containers you're using etc. Your class itself should have some functionality that you provide through its interface. I'm not sure what your class is supposed to do, but if you want a function to insert two strings you should just provide that function. That's your starting point. Then you decide that you're going to store your strings in a map or whatever. In summary, the types that go into the map will be decided by your class interface. What you're doing is the opposite - deciding how you're implementing it and then exposing the types of your map in the interface.

C++ store multiple data types in one collection

Problem: I want disparate sections of my code to be able to access a common collection that stores objects of different types in such a way that the type of each object is known and, crucially, retrieval from the collection should be type checked at compile time. (I realise this is close to questions asked before, but please read on, this is somewhat more specific.)
To give a concrete example, I would like something that does the following:
// Stuff that can go in the collection:
enum Key { NUM_APPLES /* (unsigned int) */, APPLE_SIZE /* (double) */ }
map<Key, Something> collection;
unsigned int * nApples = collection.find(NUM_APPLES);
int * appleSize = collection.find(APPLE_SIZE); // COMPILATION ERROR - WRONG TYPE
My solution: So far I have devised the following solution using boost::any:
The key:
using namespace std;
using namespace boost::any;
struct KeySupertype
{
protected:
// Can't create an instance of this type
KeySupertype() {}
private:
// Can't copy
KeySupertype& operator = (const KeySupertype& other) {}
KeySupertype(const KeySupertype& other) {}
};
template <typename Type>
struct Key : public KeySupertype
{
public:
Key() {}
};
The collection:
class PropertiesMap
{
public:
template<typename T>
T * find(Key<T> & key);
/* Skipping erase, insert and other methods for brevity. */
private:
map<const KeySupertype *, any> myAnyMap;
};
template <typename T>
T * PropertiesMap::find(Key<T> & key)
{
const map<const KeySupertype *, any>::iterator it = myAnyMap.find(&key);
if(it == myAnyMap.end())
return NULL;
return any_cast<T>(&it->second);
}
Usage:
static const Key<unsigned int> NUM_APPLES;
static const Key<double> APPLE_SIZE;
PropertiesMap collection;
/* ...insert num apples and apple size into collection ...*/
unsigned int * const nApples = collection.find(NUM_APPLES);
int * const nApples = collection.find(NUM_APPLES); // COMPILATION ERROR
This way type information is encoded with each Key according to its template parameter so the type will be enforced when interacting with the collection.
Questions:
1) Is this a reasonable way to achieve my goal?
2) A point of nastyness is that the collection uses the address of Key objects as the internal std::map key. Is there a way around this? Or at least a way to mitigate misuse? I've tried using a unique int in each Key that was generated from a static int (and making the std::map key type an int), but I'd like to avoid statics if possible for threading reasons.
3) To avoid using boost::any would it be reasonable to have the std::map be of type <const KeySupertype *, void *> and use a static_cast<T> instead of any_cast?
1) Looks nice to me, a clever solution
2) I guess you're afraid that someone will copy the key and its address will change. If that's your concern, keep an "original address" field in your KeySuperType. During construction set the original address to this, during copying set the original address to the original address of the right hand (source). Use this original address to access the map contents. I really couldn't think of a compile time solution to this, since at compile time, compilation units will not know about each other. You could assign unique ID's to the keys earliest in link time, and getting the address of global variables is sort of equivalent to that. The only weak point I can see with this solution is if you define the same key in two dynamic shared libraries without extern, they'll silently have their own versions of the key with different addresses. Of course, if everything goes into the same binary, you won't have that problem, since two declarations without extern will cause a "Multiple Declaration" linker error.
3) If your problem with boost::any is depending on boost (which is more OK then you think), then implement any yourself, it's surprisingly simple. If the problem is performance, then static_cast<> also seems OK to me, as long as you keep the internals of your PropertiesMap
away from those that don't know what they're doing...

Extending a thrift generated object in C++

Using the following .thrift file
struct myElement {
1: required i32 num,
}
struct stuff {
1: optional map<i32,myElement> mymap,
}
I get thrift-generated class with an STL map. The instance of this class is long-lived
(I append and remove from it as well as write it to disk using TSimpleFileTransport).
I would like to extend myElement in C++, the extenstions should not affect
the serialized version of this object (and this object is not used in any
other language). Whats a clean way to acomplish that?
I contemplated the following, but they didn't seem clean:
Make a second, non thrift map that is indexed with the same key
keeping both in sync could prove to be a pain
Modify the generated code either by post-processing of the generated
header (incl. proprocessor hackery).
Similar to #2, but modify the generation side to include the following in the generated struct and then define NAME_CXX_EXT in a forced-included header
#ifdef NAME_CXX_EXT
NAME_CXX_EXT ...
#endif
All of the above seem rather nasty
The solution I am going to go with for now:
[This is all pseudo code, didn't check this copy for compilation]
The following generated code, which I cannot modify
(though I can change the map to a set)
class GeneratedElement {
public:
// ...
int32_t num;
// ...
};
class GeneratedMap {
public:
// ...
std::map<int32_t, GeneratedElement> myGeneratedMap;
// ...
};
// End of generated code
Elsewhere in the app:
class Element {
public:
GeneratedElement* pGenerated; // <<== ptr into element of another std::map!
time_t lastAccessTime;
};
class MapWrapper {
private:
GeneratedMap theGenerated;
public:
// ...
std::map<int32_t, Element> myMap;
// ...
void doStuffWIthBoth(int32_t key)
{
// instead of
// theGenerated.myGeneratedMap[key].num++; [lookup in map #1]
// time(&myMap[key].lastAccessTime); [lookup in map #2]
Element& el=myMap[key];
el.pGenerated->num++;
time(&el.lastAccessTime);
}
};
I wanted to avoid the double map lookup for every access
(though I know that the complexity remains the same, it is still two lookups ).
I figured I can guarantee that all insertions and removals to/from the theGenerated)
are done in a single spot, and in that same spot is where I populate/remove
the corresponding entry in myMap, I would then be able to initialize
Element::pGenerated to its corresponding element in theGenerated.myGeneratedMap
Not only will this let me save half of the lookup time, I may even change
myMap to a better container type for my keytype (say a hash_map or even a boost
multi index map)
At first this sounded to me like a bad idea. With std::vector and std::dqueue I can
see how this can be a problem as the values will be moved around,
invalidating the pointers. Given that std::map is implemented with a tree
structure, is there really a time where a map element will be relocated?
(my above assumptions were confirmed by the discussion in enter link description here)
While I probably won't provide an access method to each member of myElement or any syntactic sugar (like overloading [] () etc), this lets me treat these elements almost a consistent manner. The only key is that (aside for insertion) I never look for members of mymap directly.
Have you considered just using simple containership?
You're using C++, so you can just wrap the struct(s) in some class or other struct, and provide wrapper methods to do whatever you want.

Storing a list of arbitrary objects in C++

In Java, you can have a List of Objects. You can add objects of multiple types, then retrieve them, check their type, and perform the appropriate action for that type.
For example: (apologies if the code isn't exactly correct, I'm going from memory)
List<Object> list = new LinkedList<Object>();
list.add("Hello World!");
list.add(7);
list.add(true);
for (object o : list)
{
if (o instanceof int)
; // Do stuff if it's an int
else if (o instanceof String)
; // Do stuff if it's a string
else if (o instanceof boolean)
; // Do stuff if it's a boolean
}
What's the best way to replicate this behavior in C++?
boost::variant is similar to dirkgently's suggestion of boost::any, but supports the Visitor pattern, meaning it's easier to add type-specific code later. Also, it allocates values on the stack rather than using dynamic allocation, leading to slightly more efficient code.
EDIT: As litb points out in the comments, using variant instead of any means you can only hold values from one of a prespecified list of types. This is often a strength, though it might be a weakness in the asker's case.
Here is an example (not using the Visitor pattern though):
#include <vector>
#include <string>
#include <boost/variant.hpp>
using namespace std;
using namespace boost;
...
vector<variant<int, string, bool> > v;
for (int i = 0; i < v.size(); ++i) {
if (int* pi = get<int>(v[i])) {
// Do stuff with *pi
} else if (string* si = get<string>(v[i])) {
// Do stuff with *si
} else if (bool* bi = get<bool>(v[i])) {
// Do stuff with *bi
}
}
(And yes, you should technically use vector<T>::size_type instead of int for i's type, and you should technically use vector<T>::iterator instead anyway, but I'm trying to keep it simple.)
Your example using Boost.Variant and a visitor:
#include <string>
#include <list>
#include <boost/variant.hpp>
#include <boost/foreach.hpp>
using namespace std;
using namespace boost;
typedef variant<string, int, bool> object;
struct vis : public static_visitor<>
{
void operator() (string s) const { /* do string stuff */ }
void operator() (int i) const { /* do int stuff */ }
void operator() (bool b) const { /* do bool stuff */ }
};
int main()
{
list<object> List;
List.push_back("Hello World!");
List.push_back(7);
List.push_back(true);
BOOST_FOREACH (object& o, List) {
apply_visitor(vis(), o);
}
return 0;
}
One good thing about using this technique is that if, later on, you add another type to the variant and you forget to modify a visitor to include that type, it will not compile. You have to support every possible case. Whereas, if you use a switch or cascading if statements, it's easy to forget to make the change everywhere and introduce a bug.
C++ does not support heterogenous containers.
If you are not going to use boost the hack is to create a dummy class and have all the different classes derive from this dummy class. Create a container of your choice to hold dummy class objects and you are ready to go.
class Dummy {
virtual void whoami() = 0;
};
class Lizard : public Dummy {
virtual void whoami() { std::cout << "I'm a lizard!\n"; }
};
class Transporter : public Dummy {
virtual void whoami() { std::cout << "I'm Jason Statham!\n"; }
};
int main() {
std::list<Dummy*> hateList;
hateList.insert(new Transporter());
hateList.insert(new Lizard());
std::for_each(hateList.begin(), hateList.end(),
std::mem_fun(&Dummy::whoami));
// yes, I'm leaking memory, but that's besides the point
}
If you are going to use boost you can try boost::any. Here is an example of using boost::any.
You may find this excellent article by two leading C++ experts of interest.
Now, boost::variant is another thing to look out for as j_random_hacker mentioned. So, here's a comparison to get a fair idea of what to use.
With a boost::variant the code above would look something like this:
class Lizard {
void whoami() { std::cout << "I'm a lizard!\n"; }
};
class Transporter {
void whoami() { std::cout << "I'm Jason Statham!\n"; }
};
int main() {
std::vector< boost::variant<Lizard, Transporter> > hateList;
hateList.push_back(Lizard());
hateList.push_back(Transporter());
std::for_each(hateList.begin(), hateList.end(), std::mem_fun(&Dummy::whoami));
}
How often is that sort of thing actually useful? I've been programming in C++ for quite a few years, on different projects, and have never actually wanted a heterogenous container. It may be common in Java for some reason (I have much less Java experience), but for any given use of it in a Java project there might be a way to do something different that will work better in C++.
C++ has a heavier emphasis on type safety than Java, and this is very type-unsafe.
That said, if the objects have nothing in common, why are you storing them together?
If they do have things in common, you can make a class for them to inherit from; alternately, use boost::any. If they inherit, have virtual functions to call, or use dynamic_cast<> if you really have to.
I'd just like to point out that using dynamic type casting in order to branch based on type often hints at flaws in the architecture. Most times you can achieve the same effect using virtual functions:
class MyData
{
public:
// base classes of polymorphic types should have a virtual destructor
virtual ~MyData() {}
// hand off to protected implementation in derived classes
void DoSomething() { this->OnDoSomething(); }
protected:
// abstract, force implementation in derived classes
virtual void OnDoSomething() = 0;
};
class MyIntData : public MyData
{
protected:
// do something to int data
virtual void OnDoSomething() { ... }
private:
int data;
};
class MyComplexData : public MyData
{
protected:
// do something to Complex data
virtual void OnDoSomething() { ... }
private:
Complex data;
};
void main()
{
// alloc data objects
MyData* myData[ 2 ] =
{
new MyIntData()
, new MyComplexData()
};
// process data objects
for ( int i = 0; i < 2; ++i ) // for each data object
{
myData[ i ]->DoSomething(); // no type cast needed
}
// delete data objects
delete myData[0];
delete myData[1];
};
Sadly there is no easy way of doing this in C++. You have to create a base class yourself and derive all other classes from this class. Create a vector of base class pointers and then use dynamic_cast (which comes with its own runtime overhead) to find the actual type.
Just for completeness of this topic I want to mention that you can actually do this with pure C by using void* and then casting it into whatever it has to be (ok, my example isn't pure C since it uses vectors but that saves me some code). This will work if you know what type your objects are, or if you store a field somewhere which remembers that. You most certainly DON'T want to do this but here is an example to show that it's possible:
#include <iostream>
#include <vector>
using namespace std;
int main() {
int a = 4;
string str = "hello";
vector<void*> list;
list.push_back( (void*) &a );
list.push_back( (void*) &str );
cout << * (int*) list[0] << "\t" << * (string*) list[1] << endl;
return 0;
}
While you cannot store primitive types in containers, you can create primitive type wrapper classes which will be similar to Java's autoboxed primitive types (in your example the primitive typed literals are actually being autoboxed); instances of which appear in C++ code (and can (almost) be used) just like primitive variables/data members.
See Object Wrappers for the Built-In Types from Data Structures and Algorithms with Object-Oriented Design Patterns in C++.
With the wrapped object you can use the c++ typeid() operator to compare the type.
I am pretty sure the following comparison will work:
if (typeid(o) == typeid(Int)) [where Int would be the wrapped class for the int primitive type, etc...]
(otherwise simply add a function to your primitive wrappers that returns a typeid and thus:
if (o.get_typeid() == typeid(Int)) ...
That being said, with respect to your example, this has code smell to me.
Unless this is the only place where you are checking the type of the object,
I would be inclined to use polymorphism (especially if you have other methods/functions specific with respect to type). In this case I would use the primitive wrappers adding an interfaced class declaring the deferred method (for doing 'do stuff') that would be implemented by each of your wrapped primitive classes. With this you would be able to use your container iterator and eliminate your if statement (again, if you only have this one comparison of type, setting up the deferred method using polymorphism just for this would be overkill).
I am a fairly inexperienced, but here's what I'd go with-
Create a base class for all classes you need to manipulate.
Write container class/ reuse container class.
(Revised after seeing other answers -My previous point was too cryptic.)
Write similar code.
I am sure a much better solution is possible. I am also sure a better explanation is possible. I've learnt that I have some bad C++ programming habits, so I've tried to convey my idea without getting into code.
I hope this helps.
Beside the fact, as most have pointed out, you can't do that, or more importantly, more than likely, you really don't want to.
Let's dismiss your example, and consider something closer to a real-life example. Specifically, some code I saw in a real open-source project. It attempted to emulate a cpu in a character array. Hence it would put into the array a one byte "op code", followed by 0, 1 or 2 bytes which could be a character, an integer, or a pointer to a string, based on the op code. To handle that, it involved a lot of bit-fiddling.
My simple solution: 4 separate stacks<>s: One for the "opcode" enum and one each for chars, ints and string. Take the next off the opcode stack, and the would take you which of the other three to get the operand.
There's a very good chance your actual problem can be handled in a similar way.
Well, you could create a base class and then create classes which inherit from it. Then, store them in a std::vector.
The short answer is... you can't.
The long answer is... you'd have to define your own new heirarchy of objects that all inherit from a base object. In Java all objects ultimately descend from "Object", which is what allows you to do this.
RTTI (Run time type info) in C++ has always been tough, especially cross-compiler.
You're best option is to use STL and define an interface in order to determine the object type:
public class IThing
{
virtual bool isA(const char* typeName);
}
void myFunc()
{
std::vector<IThing> things;
// ...
things.add(new FrogThing());
things.add(new LizardThing());
// ...
for (int i = 0; i < things.length(); i++)
{
IThing* pThing = things[i];
if (pThing->isA("lizard"))
{
// do this
}
// etc
}
}
Mike