1
votes

I try to create a singleton object using shared_ptrs. However the code does not compile when the constructors/destructor are private for the specific object The code is below.h

//ThreadPool.h
class ThreadPool
{
  public:
  static std::shared_ptr<ThreadPool> & getInstance();
  inline static std::shared_ptr<ThreadPool> m_threadPoolInstance;
  private:
  ThreadPool() =default;
~ ThreadPool() = default;
  ThreadPool(ThreadPool const  &) = default;
 };
 //ThreadPool.cpp
#include "pch.h"
#include <ThreadPool.h>

std::shared_ptr<ThreadPool> & ThreadPool::getInstance()
{
    if (! m_threadPoolInstance)
    {
        ThreadPool * p_ThreadPool = new ThreadPool();
        m_threadPoolInstance.reset(p_ThreadPool);
    }
    return m_threadPoolInstance;
}

I am using VS17 compiler The error that is created is the following

error C2440: '': cannot convert from '_Ux *' to 'std::shared_ptr' with [ _Ux=ThreadPool ] include\memory(1462): note: No constructor could take the source type, or constructor overload resolution was ambiguous threadpool.cpp(9): note: see reference to function template instantiation 'void std::shared_ptr::reset(_Ux *)' being compiled with [ _Ux=ThreadPool ] threadpool.cpp(9): note: see reference to function template instantiation 'void std::shared_ptr::reset(_Ux *)' being compiled with [ _Ux=ThreadPool ]

When I set the constructors/destructor in public section, the compilation is succesfull.

However running the same code using gcc compiler , compiles succesfully

1
You don't need a shared pointer here. - Maxim Egorushkin
...because the whole point of a shared pointer is to free the object when it's not needed anymore. But that's never a problem for a singleton object. - Solomon Slow
This is true, but the question still exists. Why does not compile using VS2017 - getsoubl

1 Answers

0
votes

The conversion fails because your ThreadPool class has a private destructor.

Calling .reset(ptr) will use the delete expression (delete ptr;) as the deleter, which requires that the destructor be public.

Refer to overload (2) here: https://en.cppreference.com/w/cpp/memory/shared_ptr/reset

2-4) Replaces the managed object with an object pointed to by ptr. Y must be a complete type and implicitly convertible to T. Additionally:

2) Uses the delete expression as the deleter. A valid delete expression must be available, i.e. delete ptr must be well formed, have well-defined behavior and not throw any exceptions. Equivalent to shared_ptr(ptr).swap(*this);.

You either need to make the destructor public or provide a custom deleter.