4

how to prevent people from creating an instance of class, but only create a shared pointer? I am doing something like:

class OnlyShred
{
public:
    friend std::shared_ptr<OnlyShred> make_shared()
    {
        return std::make_shared<OnlyShred>();  
    };

private:
    OnlyShred() = default;
    OnlyShred(const OnlyShred&) = delete;
    OnlyShred(const OnlyShred&&) = delete;
    OnlyShred& operator=(const OnlyShred&) = delete;
};

Could you please confirm if this is ok? And if you can think of a downside doing this? The instance can not be copied/moved so this must gurantee that only shared pointer is around when someone uses this class?

Vero
  • 313
  • 2
  • 9
  • `friend static` ?!? – 463035818_is_not_an_ai May 11 '22 at 19:27
  • just friend, sorry, I updated – Vero May 11 '22 at 19:27
  • 1
    please post a [mcve]. Something that actually compiles. How is `std::make_shared` supposed to create the instance when the constructor is `private` ? – 463035818_is_not_an_ai May 11 '22 at 19:30
  • 3
    [std::make_shared private ctor issue](https://stackoverflow.com/questions/8147027/how-do-i-call-stdmake-shared-on-a-class-with-only-protected-or-private-const/8147213#8147213) – Quimby May 11 '22 at 19:31
  • I thought friend will pass to shared, will compile this sorry! – Vero May 11 '22 at 19:31
  • @463035818_is_not_a_number You are right. I can make shared ptr a friend too? But very ugly – Vero May 11 '22 at 19:35
  • @Vero No, you cannot, or you can, but it won't work because the construction is surely delegated to some implementation-defined method; it would be that method you had to make a friend. – Quimby May 11 '22 at 19:42
  • 1
    @Quimby Thanks very much, I think I won't find better than the link you attached. I will go through it. In the mean time please if someone can think of better solution than the belows feel free :) Thanks very much! – Vero May 11 '22 at 19:46

1 Answers1

5

You can use new to allocate the class and then wrap it in std::shared_ptr, since std::make_shared<OnlyShred> will not have access to the constructor. A way you can do this is:

class OnlyShred
{
public:

    static std::shared_ptr<OnlyShred> make_shared()
    {
        return std::shared_ptr<OnlyShred>(new OnlyShred);  
    };

private:
    OnlyShred() = default;
    OnlyShred(const OnlyShred&) = delete;
    OnlyShred(const OnlyShred&&) = delete;
    OnlyShred& operator=(const OnlyShred&) = delete;
};

int main() {
    auto ptr = OnlyShred::make_shared();
    return 0;
}
Lala5th
  • 1,137
  • 7
  • 18
  • Just a nitpick, but `std::make_shared` only makes one allocation, this does more than one due to separate allocation of the bookkeeping table in the pointer. But it might be the simplest answer. – Quimby May 11 '22 at 19:41
  • Thanks, performance is ok I guess, I will only create instances before the main program start. Thanks a lot, I will use this :) – Vero May 11 '22 at 19:49