State pattern error in C++ (no suitable constructor)

class Tool {
public:
    virtual void mouseUp();
    virtual void mouseDown();
    virtual ~Tool();
};

class SelectionTool : public Tool {
    void mouseDown() override {
        std::cout << "SelectionTool iconn";
    }

    void mouseUp() override {
        std::cout << "Draw a dashed rectanglen";
    }
};

class BrushTool : public Tool {
    void mouseDown() override {
        std::cout << "BrushTool iconn";
    }

    void mouseUp() override {
        std::cout << "Draw linen";
    }
};

class Canvas {
    Tool _currentTool;
public:
    void mouseDown() {
        _currentTool.mouseDown();
    }

    void mouseUp() {
        _currentTool.mouseUp();
    }

    Tool getCurrentTool(){
        return this->_currentTool;
    }

    void setCurrentTool(Tool currentTool) {
        this->_currentTool = currentTool;
    }
};

int main(int argc, char *argv[]){
    auto george = std::make_unique<Canvas>();
    george->setCurrentTool(std::make_unique<BrushTool>());
    george->mouseDown();
    george->mouseUp();
    return 0;
}

No suitable user-defined conversion from “std::unique_ptr<Brush, std::default_delete>” to “Tool” exists.

I am following youtube course where that kind of polymorphism is used in Java and I tried to implement it in C++ but it doesnt work. Whats wrong with that code?

Answer

I suspect the polymorphism video you were using didn’t use smart pointer types.

You can’t just use std::shared_ptr<T> as if it were the underlying type. They have get and set interfaces, but they are not a seamless replacement. If they were, they couldn’t do their job!

Using std::unique_ptr adds more conditions that you may not want to deal with right now. I’m just going to use std::shared_ptr here.

If you want shared pointers, I’d suggest making a typedef to the shared pointer type and use that everywhere. You can assign std::shared_ptr<derived> to std::shared_ptr<base> similar to the inheritance rules for raw pointers. Just be sure you have a virtual base destructor, which you do.

#include <iostream>
#include <algorithm>

class Tool {
public:
    virtual void mouseUp() {}
    virtual void mouseDown() {}
    virtual ~Tool() {}
};

typedef std::shared_ptr<Tool> shared_tool_type;

class SelectionTool : public Tool {
    void mouseDown() override {
        std::cout << "SelectionTool iconn";
    }

    void mouseUp() override {
        std::cout << "Draw a dashed rectanglen";
    }
};

class BrushTool : public Tool {
    void mouseDown() override {
        std::cout << "BrushTool iconn";
    }

    void mouseUp() override {
        std::cout << "Draw linen";
    }
};

class Canvas {
    shared_tool_type _currentTool;
public:
    void mouseDown() {
        _currentTool.get()->mouseDown();
    }

    void mouseUp() {
        _currentTool.get()->mouseUp();
    }

    std::shared_ptr<Tool> getCurrentTool() {
        return this->_currentTool;
    }

    void setCurrentTool(shared_tool_type currentTool) {
        this->_currentTool = currentTool;
    }
};

int main(int argc, char* argv[]) {
    auto george = std::make_shared<Canvas>();
    george->setCurrentTool(std::make_shared<BrushTool>());
    george->mouseDown();
    george->mouseUp();
    return 0;
}