#include <iostream>
#include <memory>
#include <stdexcept>

class Resource {
public:
    explicit Resource(const std::string& str): str_(str) {}

    const std::string& str() const {
        return str_;
    }

private:
    std::string str_;
};

class Converter {
public:
    Converter() = default;

    // Rule of 5
    virtual ~Converter() = default;
    Converter(const Converter& other) = default;
    Converter(Converter&& other) = default;
    Converter& operator=(const Converter& other) = default;
    Converter& operator=(Converter&& other) = default;

    virtual void Convert(const std::unique_ptr<Resource>& resource) const = 0;
};

class CurlyBracketConverter : public Converter {
public:
    void Convert(const std::unique_ptr<Resource>& resource) const override {
        std::cout << "{" << resource->str() << "}\n";
    }
};

class SquareBracketConverter : public Converter {
public:
    virtual void Convert(const std::unique_ptr<Resource>& resource) const override{
        std::cout << "[" << resource->str() << "]\n";
    }
};

class Printer {
public:
    explicit Printer(std::unique_ptr<Converter>&& converter) noexcept : converter_(std::move(converter)) {}

    void Print(const std::unique_ptr<Resource>& resource) const {
        converter_->Convert(resource);
    }

private:
    std::unique_ptr<Converter> converter_;
};

struct Foo {
    Foo(std::unique_ptr<int> ptr);
};

struct Bar {
    use(std::unique_ptr<Foo> ptr);
};

struct MockFoo {};

TEST() {
    std::unique_ptr<MockFoo> mock;
    MockFoo* mock_ptr = mock.get();
    Bar bar;
    bar.use(std::move(mock));

    EXPECT_CALL(mock_ptr, use);
}

int main() {
    auto resource = std::make_unique<Resource>("Ala has a cat");
    Printer printer(std::make_unique<SquareBracketConverter>());
    Printer printer2(std::make_unique<CurlyBracketConverter>());
    printer.Print(resource);
    printer2.Print(resource);

    return 0;
}