Dan
Dan

Reputation: 1248

"attempting to reference a deleted function" for copy constructor

I am trying to get my head around the Rule of 5.

I have a class Renderable, which defines a custom destructor, so it seemed like a good candidate for the Rule of 5. This class creates some resources in its constructor, so my first thought was that I should prevent copying:

class Renderable {

public:

    Renderable(const Sprite&) {
        // Allocate resources
    }

    ~Renderable() {
        // Free resources
    }

    // Prevent copying
    Renderable(const Renderable& other) = delete;

}

I have another class, Unit, which creates a Renderable in the initializer list of its constructor:

class Unit {

public:

    Unit(const Sprite& sprite) :
            renderable(Renderable(sprite)) {}

private:

    Renderable renderable;

}

I would expect this to call the regular Renderable constructor, but instead I get the error:

Renderable::Renderable(const Renderable &)': attempting to reference a deleted function

Why is this trying to call the copy constructor?

I even tried added debug lines to the copy constructor, but nothing is printed:

Renderable(const Renderable& other) : sprite(other.sprite) {
    std::cout << "copy constructor";
}

Upvotes: 0

Views: 878

Answers (3)

catnip
catnip

Reputation: 25388

In addition to what others have said, I think you meant to write:

Unit::Unit(const Sprite& sprite) :
    renderable(sprite) {}

This invokes the converting constructor Renderable(const Sprite&) to initialise renderable directly, no copying involved.

Live demo

Upvotes: 3

David Schwartz
David Schwartz

Reputation: 182769

First, Renderable(sprite) creates a Renderable. Then you try to construct renderable with that Renderable. Conceptually, what could that use other than a copy constructor?

Why are you creating a Renderable to initialize renderable? That step is not needed and won't work because you have no copy constructor. You've specifically said that you don't want code that conceptually uses a copy constructor to work.

Upvotes: 4

Sam Varshavchik
Sam Varshavchik

Reputation: 118340

Why is this trying to call the copy constructor?

Because

  renderable(Renderable(sprite)) {}

This constructs a temporary Renderable object, and then uses it to construct the renderable class members. That would be a

I even tried added debug lines to the copy constructor, but nothing is printed:

This is because this is one of the situations where compilers are permitted to do copy-elision. Even though the compiler optimizes away a temporary+copy construction, the constructor must still exist. Something about the class causes the default copy constructor to be deleted. There could be several reasons for that, but you did not provide sufficient information about your class in order to determine what that reason might be.

Upvotes: 1

Related Questions