Boost logo

Boost :

From: Marco Costalba (mcostalba_at_[hidden])
Date: 2007-09-15 11:25:07


In a object factory I'm converting to using boost::fusion I have a
problem with passing argument by reference with a fusion vector.

Let's explaing a bit...

UI function to get an object from a name and a list of c'tor arguments
is something like

template<typename T1> /* one argument case */
static Base* object(detail::KeyRef nm, T1 a1) {
        typedef boost::fusion::vector<T1> values;
        values v(boost::fusion::vector_tie(a1));
        return detail::Factory_p<Base>::instance(). template doObject<values>(nm, v);
}

template<typename T1, typename T2> /* two arguments case */
static Base* object(detail::KeyRef nm, T1 a1, T2 a2) {
        typedef boost::fusion::vector<T1, T2> values;
        values v(boost::fusion::vector_tie(a1, a2));
        return detail::Factory_p<Base>::instance(). template doObject<values>(nm, v);
}

I want to easy the user from the burden to specifying template
parameters, so use template parameters deduction.

Because of function templates does not support template default
arguments we are forced to use one of the above template for each
number of arguments.

Although we have many UI 'object()' templates I would like to use only
one doObject<> template to avoid duplicating all the inner workings of
the factory for each argument number.

To do this input arguments are 'packed' in a fusion vector and
unpacked just before to invoke the function object that actually
creates the object:

template<typename Values>
Base* doObject(KeyRef nm, Values& v) const {

--- cut--

const SignatureClass<Base, Values>* p = this->find<Values>(r);
if (p)
    return (*p)(v);

-- cut ---
}

Where the operator() in (overloaded) SignatureClass is defined as:

template<typename Base, typename Values typename FnType>
struct CreatorClass: public SignatureClass<Base, Values> {

        typedef typename FnType::result_type result_type;

        CreatorClass(const FnType& fn) : functor(fn) {}

        virtual result_type operator()(Values& v) const {

                return boost::fusion::invoke_function_object(functor, v);
        }

        FnType functor;
};

Now the problem is that I'm not able to find a way to pass arguments
by reference.

As example, if I have a class:

class Test { public:
        Test(int& cnt) { cnt++; }
};

 trying the following will fail:

int objCnt = 6;
Test* t = Factory::object(objCnt);

cout << objCnt; // Is still 6 not 7!!

This is expected since I pass by copy in object(detail::KeyRef nm, T1 a1)

But it fails to update objCnt also if I explicitly set the template
parameter type:

Test* t = Factory::object<int&>(objCnt);

How can I modify the code above to let pack arguments in a vector,
handling always passing the packed vector by reference and finally
call invoke_function_object() ?

Thanks
Marco


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk