0

I am trying to write the singleton pattern in the person class which gives me the ability to create just one instance for that class and I can use it in any place in my program.

The following is the class:

// The declaration
class Person {
    static unique_ptr<Person> instance;
    Person() = default;
    Person(Person&) = delete;
    Person& operator=(const Person&) = delete;
    ~Person() = default;
public:
    static unique_ptr<Person> getInstance();
};

// The implementation   
unique_ptr<Person> instance = NULL;
unique_ptr<Person> Person::getInstance() {
    if (instance == NULL) {
        instance = unique_ptr<Person>(new Person());
    }
    return instance;
}

But the problem that it gives me this error: Error C2280 'std::unique_ptr<Person,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': attempting to reference a deleted function

Unfortunately, I don't understand that problem and I don't know how to solve?

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Lion King
  • 32,851
  • 25
  • 81
  • 143
  • 2
    What are you hoping to get from returning a `unique_ptr` that a `Person&` wouldn't provide you? The **"unique"** in `unique_ptr` means that attempts to **copy** it will fail. – Drew Dormann May 04 '18 at 22:15
  • 1
    `std::unique_ptr` has an explicitly deleted copy constructor. It can't be copied, but you can take a reference to `*uniquePtr` or you can move the `std::unique_ptr` – Justin May 04 '18 at 22:16
  • @Justin Think on what happens if you `move` the singleton. – user4581301 May 04 '18 at 22:17
  • @user4581301 I know exactly what happens. I was giving the OP a direct translation of the error message – Justin May 04 '18 at 22:18
  • This is one of those cases where the right way is probably to do something else. Here is a link to a great write-up on one of the better alternatives: https://stackoverflow.com/a/1008289/4581301 . – user4581301 May 04 '18 at 22:19
  • @Justin point taken, but your comment can be read as a suggestion to do something that will go very wrong. – user4581301 May 04 '18 at 22:22
  • Thanks, everyone for the clarification. – Lion King May 04 '18 at 22:45
  • fwiw, you dont need a singleton to be able to create just one instance and use it in any place in your program. All you need to do is to create one instance and use it everywhere – 463035818_is_not_an_ai May 04 '18 at 22:48
  • @user463035818: Quote: `All you need to do is to create one instance and use it everywhere`. That point needs some clarification because it's important to me. – Lion King May 04 '18 at 22:52
  • if you are fine with a global then just use a global, singleton is for when you need to make sure that the type allows only a single instance, but if you ever create only a single instance, then most of the time there is no need for this extra "safety" of not being able to create a second one – 463035818_is_not_an_ai May 04 '18 at 22:55
  • btw sorry for spoiling this rare case of a question about a singleton without a discussion whether singletons are nice or not ;) – 463035818_is_not_an_ai May 04 '18 at 23:00

1 Answers1

6

The copy constructor of std::unique_ptr is implicitly deleted since it has an explicitly defined move constructor.

From the C++11 Standard, 12.8 Copying and moving class objects:

7 If the class definition does not explicitly declare a copy constructor, one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted; otherwise, it is defined as defaulted ([dcl.fct.def]).

You can solve your problem by:

  1. Returning a reference to a Person.

    static Person& getInstance();
    
    
    Person& Person::getInstance()
    {
       static Person p;
       return p;
    }
    
  2. Returning a shared_ptr<Person>.

    static std::shared_ptr<Person> getInstance();
    
    
    std::shared_ptr<Person> Person::getInstance()
    {
       static std::shared_ptr<Person> p(new Person);
       return p;
    }
    

I recommend the first solution since it is simpler.

PS Please note that neither of them requires use of the static member variable instance.

R Sahu
  • 204,454
  • 14
  • 159
  • 270