Search code examples
c++lambdac++11factory-pattern

C++ lambda; class factory adaptor


Given a class factory

struct C {
    C Factory(A a, B b, ...) { ... }
};

I want to transform it into a function that returns a shared pointer in an automated way. Something like:

template<T (*f)(Args...), typename T, typename... Args>
boost::shared_ptr<T> blah(Args... args) {
  return boost::shared_ptr<T>(new T(f(args...)));
}

that I can use like:

shared_ptr<C> c = blah<C::Factory>(a, b, ...);

I am using gcc4.4, but I can upgrade to 4.5 for lambdas if necessary. I'm doing this because after I asked this question, I now need to convert my class factories to return shared_ptr, but I don't want to change my class definitions — just build an adaptor.


Solution

  • not sure I understand the quesiton but a few points:

    1) The factories should return pointers to dynamically allocated objects if you want to use them with boost::smart_ptr. Using smart pointers (which will attempt to delete objects when they go out of scope and no other smart_ptr has ownership of the object) with statically allocated variables makes no sense.

    2) When you do return a pointer (your struct code would look something like this)

    struct C {
        C() { ... };
        static C* Factory(A a, B b) { 
            ...;
            return new C;
        }
    };
    

    then you can just do

    boost::shared_ptr<C> p_C(C::Factory(a,b));
    

    so I am not really sure if this (possibly very complicated) template function would be so useful. (To me this use of the factory pattern also seems strange - AFAIK you usually want to abstract the exact type of object being created, but that is another point).

    Edit: (Reply to comment, since you can't format comments...)

    I am pretty sure that using shared_ptr's which point to statically allocated variables will lead to double delete errors (at least if the objects destructors are deleting anything).. it is surely a dangerous path

    Can't you just do (copy from linked question)

    shared_ptr<MyClass> CreateWithList(list lst) 
    {
       return shared_ptr<MyClass>(new MyClass(lst)); // construct with a list here
    }
    
    shared_ptr<MyClass> CreateWithPyArrayObject(PyArrayObject* obj)
    {
        return shared_ptr<MyClass>(new MyClass(obj)); // construct with numpy array here
    }
    

    ? I mean I'm sure the real case is more complicated then that, but right now it seems easier than the template stuff.

    Btw: If you are just after C-type speeds in python, give Cython a try, it's really cool (even if it's not applicable now, it might be in the future...)