ruipacheco
ruipacheco

Reputation: 16402

How to populate interface for existing object?

I have an interface:

struct result {
  virtual ~result() = 0;
  virtual auto getName() -> std::string = 0;

  protected:
    result() = default;
    result(const result &) = default;
    auto operator=(const result &) -> result & = default;
}

and an implementation:

struct abstract_result : public result {
  auto getName() -> std::string override;
  std::string m_name;
}

I'm currently using an instance of abstract_result within my code to be populated by a number of algorithms but I want the end user to receive a pointer to the interface so I can hide the implementation.

How can I turn an instance of abstract_result into a std::unique_ptr<result>?

Upvotes: 0

Views: 90

Answers (2)

einpoklum
einpoklum

Reputation: 131475

If I understand you correctly, what you want to do is pretty similar to what @user463035818 says, but with the populated structure, i.e.:

std::unique_ptr<result> pointer_to_result {&my_populated_abstract_result };

And this is fine since, again, an abstract_result is-a result. But you might not want to do this at all if your my_populated_abstract_result is not dynamically allocated. std::unique_ptr is not generally intended for use with objects on the stack (e.g. local variables). If my_populated_abstract_result is a local variable - don't put in a unique_ptr at all (nor in an std::shared_ptr), and don't try to hold on to it once my_populated_abstract_result goes out of scope.

PS :

  • Doesn't it make more sense for the pure-virtual base class to be called abstract_result, with the concrete classes being foo_result, bar_result, baz_result?
  • Perhaps it's a good idea to use a namespace if you really have a lot of names with _result in them? That way you'll have result::abstract (or result::base) and then result::foo, result::bar, result::baz.

Upvotes: 2

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 122133

An abstract_result is-a result (btw your naming seems to be the wrong way around) so a pointer to a abstract_result is-a pointer to a result. So you just need to construct the unique_ptr, eg

auto x = unique_ptr<result>(new abstract_result());

In case the instance is on the stack and you are worried about unique_ptr trying to delete an instance with automaitc storage, you can use a deleter that does nothing, as in

template <typename T>
struct no_deleter {
    void operator()(T*){}
};

abstract_result x;
std::unique_ptr<result> x_ptr{ &x, no_deleter<result>() };

However, in that case I wonder why you want to use a unique_ptr in the first place. There is nothing wrong about using raw pointers as long as they do not own the object (ie whoever holds the pointer is not responsible for deleting the object), while a unique_ptr is usually meant to own the object it points to.

PS

I have to admit that I dont fully understand what is your problem...

but I want to turn a populated instance of abstract_result into a pointer to result

As mentioned above, a pointer to a abstract_result is (sloppy-speaking) already a pointer to a result. A simpler example:

abstract_result x;
result* pointer_to_result = &x;

Upvotes: 3

Related Questions