I want to start throwing some interfaces into my C++ code to make it easier for me to unit test using mocks.
The problem with this is returning abstract classes from a method in C++ is a pain. You can't return by value so you need to return a pointer or a reference.
Given all of the developments in C++ in the last six or seven years, I thought I'd ask if maybe we had a better way to return an abstract base class. An interface without the noise would look something like this, but I'm sure this isn't possible.
IBaseInterface getThing() {return DerivedThing{};}
The way that I remember doing this in the past is to use a pointer (probably a smart pointer now):
std::unique_ptr<IBaseInterface> getThing() {return std::make_unique<DerivedThing>();}
The problem with the pointer is that I'm never actually planning to take advantage of nullptr so the overhead and noise of dealing with a pointer rather than a value gains me no value as a reader.
Is there a better way that I don't know to handle this?
EDIT: provides complete example, including making the polymorphic handle copyable.
#include <iostream>
#include <utility>
#include <memory>
struct IBaseInterface {
IBaseInterface() = default;
IBaseInterface(IBaseInterface const&) = default;
IBaseInterface(IBaseInterface &&) = default;
IBaseInterface& operator=(IBaseInterface const&) = default;
IBaseInterface& operator=(IBaseInterface &&) = default;
virtual ~IBaseInterface() = default;
virtual std::unique_ptr<IBaseInterface> clone() const = 0;
virtual void do_thing() = 0;
};
struct handle
{
handle(std::unique_ptr<IBaseInterface> ptr)
: _impl(std::move(ptr))
{}
handle(handle const& r)
: _impl(r._impl->clone())
{}
handle(handle && r)
: _impl(std::move(r._impl))
{}
handle& operator=(handle const& r)
{
auto tmp = r;
std::swap(_impl, tmp._impl);
return *this;
}
handle& operator=(handle && r)
{
_impl = std::move(r._impl);
return *this;
}
// interface here
void do_thing() { _impl->do_thing(); }
private:
std::unique_ptr<IBaseInterface> _impl;
};
struct DerivedThing : IBaseInterface
{
std::unique_ptr<IBaseInterface> clone() const override
{
return std::make_unique<DerivedThing>(*this);
}
void do_thing() override
{
std::cout << "I'm doing something" << std::endl;
}
};
handle make_thing()
{
return handle(std::make_unique<DerivedThing>());
};
int main()
{
auto a = make_thing();
auto b = a;
a.do_thing();
b.do_thing();
return 0;
}
Now use your handle as if it had (moveable) value semantics
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With