tags:

views:

88

answers:

3

Here is what I'm trying to do:

//ImageCache.h:
#include <map>
#include <SDL.h>

typedef pair<const wchar_t*, SDL_Surface*> ImageNameAndSurface;
class ImageCache {
// Functions
    public:
        ImageCache();
        ~ImageCache();
        SDL_Surface* getImage(const wchar_t* imageFilename);
// Variables
    private:
        map<const wchar_t*, SDL_Surface*> imageFileMap;
        void freeImage(const pair<const wchar_t*, SDL_Surface*>& pr); //function for_each() is to operate on
};

//ImageCache.cpp:
#include "ImageCache.h"
#include <algorithm>
#include <SDL_image.h>

ImageCache::ImageCache() {}
void ImageCache::freeImage(const pair<const wchar_t*, SDL_Surface*>& pr)
{
  wcout << "Freeing " << pr.first << endl;
  SDL_FreeSurface(pr.second);
}

ImageCache::~ImageCache() {
    for_each(imageFileMap.begin(), imageFileMap.end(), freeImage);
}

I'm using MSVC 2005 (compiling for Windows CE 5.0) and I get the following error:

error C3867: 'ImageCache::freeImage': function call missing argument list; use '&ImageCache::freeImage' to create a pointer to member

I understand that the function argument of for_each() expects a static function (and all of this works if I declare freeImage as static) but I'd like to know how to do this for non-static member functions. I don't understand how the implied "this" pointer is not getting passed to the call to freeImage(). Any help is greatly appreciated! I've Googled for an hour and haven't found quite this same situation for some reason.

I should add I'm trying to avoid overloading the () operator as this seems unnecessarily verbose and other similar, but obviously not compilable methods avoid this as well.

+2  A: 

If you don't want to make ImageCache::freeImage a static member function, then you need to pass the this pointer. If you don't want to make a little helper class with operator () overloaded, you can use boost::bind to create the functor for you on the fly:

for_each(imageFileMap.begin(), imageFileMap.end(),
         boost::bind(&ImageCache::freeImage, this, _1, _2));
Jesse Beder
don't you need to pass `*this` (ie a reference instead of a pointer) ? I am not experienced with `boost::bind`.
Matthieu M.
@Matthieu, you can actually pass either, but if you pass '*this', it will make a copy of your object (since 'boost::bind' only passes by value). If you want to pass a reference, you can use 'boost::ref(*this)'.
Jesse Beder
@Jesse: Thanks for the precision.
Matthieu M.
+1  A: 

"for_each" is a free standing function that isn't a member of your class, so it doesn't know to pass the "this" pointer or call using member function syntax.

On that platform you'll probably need mem_fn (to make the this pointer explicit) along with bind1st (to pass the this pointer). tr1::bind (formerly boost.bind) I don't think is available to you, but if it is it's a superior solution and supersedes bind1st et al.

Terry Mahaffey
Ahhh, that's the issue then. Makes perfect sense to me now (the problem anyway). As for the solution, I don't have boost or tr1 available, but bind1st and mem_fun seem to be available. How would I work those into the function call?Thanks!
RotsiserMho
To clarify, mem_fn is not available it seems, but mem_fun is. Am I out of luck? It seems like this should be simpler...
RotsiserMho
Yes, I meant mem_fun (the old one). mem_fn is a confusingly named new version.
Terry Mahaffey
Ha ha OK. But I still don't know how to use it...
RotsiserMho
+1  A: 

NOT

for_each(imageFileMap.begin(), imageFileMap.end(), freeImage);

BUT

for_each(imageFileMap.begin(), imageFileMap.end(),&ImageCache::freeImage);

for the error in question

but you will still have problems since ImageCache::freeImage is a non static (though it could be static) member function.

Making freeImage static and the change above should help.

nbourbaki
I can verify this works.
C Johnson
Yup, that works. I was just hoping for a way to avoid making it static since I plan to add functions that utilize member variables later on. Thanks.
RotsiserMho