1

Because of RAII features i want my objects to be placeable only on the stack and also as object creation should be delegated to specialised factories i dont want ocpy constructor to be accessible for use.

So i did something like this.

template<typename Product, Args ... >
class Creator : public Product
{
    public:
        static Product create(Args ... args)
        {
            return Product(args ... );
        }
};

class ProtectedClass
{
        ProtectedClass(const ProtectedClass& aThat)=delete;
        ProtectedClass& operator=(const ProtectedClass& aThat)=delete;
    protected:
        ProtectedClass(){}
};

class Spawner
{
    public:
        ProtectedClass getProtectedClass()
        {
            return Creator<ProtectedClass>::create();
        }
}

int main()
{
    Spawner spawner;
    //I need protectedClass to be enclosed within this frame
    ProtectedClass protectedClass = spawner.getProtectedClass(); // err copy constructor is delted
}

I can do something like this

template<typename Product, Args ... >
class Creator : public Product
{
    public:
        Creator(Args ... args) : product_(args ...){}
        Product& get() const
        {
            return product_;
        }
    private:
        Product product_;
};

class Spawner
{
    public:
        std::unique_ptr<Creator<ProtectedClass>> getProtectedClassCreator()
        {
            return new Creator<ProtectedClass>();
        }
}

int main()
{
    Spawner spawner;
    std::unique_ptr<Creator<ProtectedClass>> creator = std::move(spawner.getProtectedClassCreator());
    ProtectedClass& protectedClass = creator->get();
}

But it doesn't seems to look right.

What are other ways to deal with that?

user1079475
  • 379
  • 1
  • 5
  • 17

1 Answers1

1

The way I would do this would be to delete copies, enable moves and allow construction via any class that can create a construction key.

// forward declare any factories
class Spawner;

struct ProtectedClass
{
    class PermissionKey {
        // this is a private constructor
        PermissionKey() {};

        // make friends of the factories
        friend Spawner;
    };

    // all this is now public.
    // because we have declared a constructor, the default constructor
    // is deleted.    
    ProtectedClass(PermissionKey) {}

    // disable copies
    ProtectedClass(const ProtectedClass& aThat)=delete;
    ProtectedClass& operator=(const ProtectedClass& aThat)=delete;

    // enable moves so the factory can return it
    ProtectedClass(ProtectedClass&& aThat)=default;
    ProtectedClass& operator=(ProtectedClass&& aThat)=default;
};

class Spawner
{
public:
    ProtectedClass getProtectedClass()
    {
        // construct our spawned object - we can create keys
        return ProtectedClass(ProtectedClass::PermissionKey());
    }
};

int main()
{
    Spawner spawner;
    //I need protectedClass to be enclosed within this frame
    auto protectedClass = spawner.getProtectedClass(); // ok now
}
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142
  • In the end i went for unique_ptr. There were to much issues comming up when dtors where involved in every move operation. – user1079475 Dec 12 '16 at 08:29
  • @user1079475 you know the use case better than me. But I thought you wanted the objects on the stack? – Richard Hodges Dec 12 '16 at 08:41
  • Yes i did but there were too much hustle with moving objects from method scope to invocation scope. These objects had mutex attributes and it would require to move these mutexes on the heap an so on so on. Too much trouble in the end for little gain – user1079475 Dec 22 '16 at 09:53