0

I have a class which accepts an interface:

class interface {
   public:
    virtual ~interface() = default;
    virtual void foo() = 0;
};

class user {
    interface& impl_;

   public:
    user(interface& impl) : impl_(impl) {}

    void foo_user() { impl_.foo(); }
};

One of the implementations of this interface is required to be a singleton for third-party reasons. I also have a simulated implementation, which has no need to be a singleton:

#include <cstdio>

class singleton_impl : public interface {
    singleton_impl() = default;

   public:
    static singleton_impl& instance() {
        static singleton_impl i;
        return i;
    }

    void foo() override { std::printf("foo\n"); };
};

class mock_impl : public interface {
    void foo() override { std::printf("mock foo\n"); };
};

Whoever uses user needs to provide one of those, based on some runtime criteria:

#include <cstring>

int main(int argc, char** argv) {
    bool is_sim = argc > 1 && strcmp(argv[1], "--sim") == 0;

    interface* impl = nullptr;

    if (is_sim)
        impl = new mock_impl;
    else
        impl = &singleton_impl::instance();

    user u{*impl};

    u.foo_user();

    if (is_sim) delete impl;

    return 0;
}

godbolt link

What's the simplest way to avoid the raw pointer/delete here, while avoiding turning mock_impl into a singleton itself (my current solution)? I want some kind of smart pointer that either owns or doesn't own its underlying object.

I could also always construct the mock object and then just conditionally pass it to the user, but I feel that I shouldn't need to keep a random object around.

MHebes
  • 2,290
  • 1
  • 16
  • 29
  • This article seems to offer a few solutions, none of which are particularly appealing but could be improved with templates: https://japreiss.wordpress.com/2013/07/21/dependency-injection-in-c/ – MHebes May 11 '23 at 22:05

0 Answers0