0
votes

I am trying to pass a pointer to a function that then sets a unique_ptr inside a struct to the pointer passed in. However, I get the following compile error on the last line of the function.

error C2280: 'std::unique_ptr< ALLEGRO_BITMAP,std::default_delete< ALLEGRO_BITMAP>>::unique_ptr(const std::unique_ptr< ALLEGRO_BITMAP,std::default_delete< ALLEGRO_BITMAP>> &)' : attempting to reference a deleted function

c:\program files (x86)\microsoft visual studio 12.0\vc\include\memory(1486) : see declaration of 'std::unique_ptr< ALLEGRO_BITMAP,std::default_delete< ALLEGRO_BITMAP>>::unique_ptr'

This diagnostic occurred in the compiler generated function 'Skin::Skin(const Skin &)'

Judging from the errors I believe it has something to do with me adding the delete template for ALLEGRO_BITMAP to namespace std, but I don't know why or how to fix it.

using namespace std;

namespace std {
template<>
class default_delete < ALLEGRO_BITMAP > {
public:
    void operator()(ALLEGRO_BITMAP* ptr) {
        al_destroy_bitmap(ptr);
    }
};
}

typedef struct {
    unique_ptr<ALLEGRO_BITMAP> img;
} Skin;

typedef struct {
    Skin skins[MAX_ENTITY_COUNT];
} World;

unsigned int createBlock(World world, ALLEGRO_BITMAP* img) {
    unsigned int entity = newEntityIndex(world);
    world.skins[entity].img = make_unique<ALLEGRO_BITMAP>(img);
    return entity;
} // error on this line

Any help is appreciated. Thanks.

1
1) The example given is not self-contained. 2) unique_ptr has certain requirements (see stackoverflow.com/a/6089065/2549876).Hector
You should not be using make_unique here. ALLEGRO_BITMAP should only be used through an opaque pointer. You should not directly create ALLEGRO_BITMAP objects, which is what make_unique will do. You should just use the unique_ptr constructor.Benjamin Lindley

1 Answers

3
votes

In your createBlock function you take World by value which means that it will be copied. However, you can't copy a unique_ptr so that is where your error comes from. This would also mean that setting the unqiue_ptr in the function wouldn't have any effect.

Instead you should take World by reference:

unsigned int createBlock(World& world, ALLEGRO_BITMAP* img) {
    unsigned int entity = newEntityIndex(world);
    world.skins[entity].img = make_unique<ALLEGRO_BITMAP>(img);
    return entity;
}

Note that the same is true for the call to newEntityIndex and that the arguments to make_unique will be passed to the ALLEGRO_BITMAP constructor.

So what you probably want is:

world.skins[entity].img.reset(img);