Proxy to hide singleton implementation I have a resource (e.g., current program configuration) that I want to handle in a single class instance, but want to hide the fact that there is, in effect, a singleton class by using a proxy class.

Reasons for not using a singleton directly include: don't want users of the class to have to change code if I move away from singleton implementation, and want to be able to have control over initialization and destruction order (which would be difficult with static classes, for example).

Additionally, this is a multithreaded application, so new instances of the Proxy class may be created at the same time (thus the mutex protecting creation of the Implementation).

The Proxy class is the proxy, and Impl class is the hidden singleton implementation. Note that I don't do anything special to Impl to make it a singleton. It is only a singleton because I track its existence in Proxy with a static member variable.

Proxy.h

#pragma once
#include &lt;memory&gt;
class Proxy {
 public:
   Proxy();
   void method1() //inline dispatch to hidden single class
   {
      data_-&gt;method1();
   }
 private:
   class Impl { //this class will be created once only
   public:
      void method1();
      Impl();
      ~Impl() = default;
   };
   std::shared_ptr&lt;Impl&gt; Make_Impl() const;
   const std::shared_ptr&lt;Impl&gt; data_{};
   inline static std::weak_ptr&lt;Impl&gt; impls_{}; //tracks whether Impl is created
};


Proxy.cpp

#include "Proxy.h"
#include &lt;mutex&gt;

Proxy::Proxy() : data_(Make_Impl()) {}

std::shared_ptr&lt;Proxy::Impl&gt; Proxy::Make_Impl() const
{ // note that impls_ may be accessed by another thread with non-const member function
  // (assignment) if it is running slightly ahead of this thread with an uninitialized impls_ so
  // need mutex before shared_ptr.lock call. if we use an atomic weak pointer (C++20) can call
  // shared_ptr.lock before mutex, check for success, and only run mutex (and try lock again) after
  // failure
   static std::mutex mtx;
   auto lock = std::lock_guard(mtx);
   std::shared_ptr&lt;Impl&gt; internal_data = impls_.lock(); //if implementation exists, assign to shared_ptr
   if (!internal_data) { //need to create implementation
      const auto new_impl(std::make_shared&lt;Impl&gt;());
      internal_data = new_impl;
      impls_ = new_impl;
   }
   return internal_data;
}

Proxy::Impl::Impl()
{
   // constructor for Impl here
}

void Proxy::Impl::method1()
{
   // the real method1 for the implementation
}


General comments welcome. Specific questions include: 


is there a way to eliminate the pointer dereference that will occur with each call intended for the underlying implementation? (For example, When Proxy::method1 is called, that redirects to the underlying singleton class.)
Instead of using a static weak_ptr, is there a better way of tracking whether the Implementation exists?
Have others done anything like this? I'm concerned that I haven't seen this pattern (with smart pointers) documented anywhere. It makes me feel like I've gone "off the rails" with this code and have overlooked some problems with this approach.
Without locking, this works for me:

class proxy
{
public:
    proxy()
      : m_impl(make_impl()) {}

    void method()
    {
        m_impl.method();
    }
private:
    struct Impl
    {
        Impl() {}
        ~Impl() {}
        void method() {}
    };

    Impl&amp; m_impl;
    Impl&amp; make_impl()
    {
        static Impl impl;
        return impl;
    }
};


When locking, you need to synchronize access to the static impl in make_impl and you need to secure the call to m_impl.method().