Thursday 27 June 2019

C++: make_unique friendship

I've previously posted about adding a friendship to the shared_ptr base class to allow a public static function containing a "make_shared" to access private constructors....

Well, here's the partial move I've started to make in my own code bases to do the same with a unique_ptr.

#include <iostream>
#include <memory>

class Item;
using ItemPtr = std::unique_ptr<Item>;
class Item
{
public:
    static ItemPtr Create()
    {
        return std::make_unique<Item>();
    }

    const int& Get() const
    {
        return value;
    }

private:
    friend std::unique_ptr<Item> std::make_unique<Item>();

    Item()
        : value(42)
    {
    }

    int value;
};

int main ()
{
auto i = Item::Crete();
std::cout << i->Get() << std::endl;
}

The secret sauce here is the friend, making the "make_unique" function a friend allows it to access the private constructor.

We could water-tight the "Item" class here by deleting the other constructors...

Item() = delete;
Item(const Item&) = delete;
Item(Item&&) = delete;
Item& operator=(const Item&) = delete;
Item& operator=(Item&&) = delete;

This way we stop any assignment to the type or construction except through the static "Create" function.

Nothing truly amazing here, but I challenge you all now to go add a parameter to the constructor... const int& incomingValue... perhaps and add it to the "Create" and try to set "value" to 100 instead of 42.

The template deduction for the type becomes a total mine-fiend, as the compiler wants to marry  up the "Type&& ..." underlying the parameters rather than treating it as a pure standard forward.

No comments:

Post a Comment