[interprocess][general] Perfect forwarding through functors

Hi to all, These days I've been thinking about adding perfect forwarding benefits to Boost Interprocess: 1)Adding "emplace" functions to containers 2)Interprocess has several functions taking an "arbitrary" number of parameters (e.g.: to construct an object in shared memory forwarding all constructor parameters). Currently, I've just used the preprocessor or manual repetition to implement some of those features, but now I want to take advantage of compilers (such as gcc 4.3 with -std=gnu++0x) that have both rvalue references and variadic templates. One solution would be write new functions with variadic templates, just as most containers use templatized range insertion functions. One option to avoid code duplication between range and emplace code is just to pack both range insertion and variadic construction logic in a function object that packs the needed code (function) and data (arguments). However, I also want to minimize both compilation time and code size. This can be achieved encapsulating those object function calls behind virtual functions, so that the main code is not heavily templatized and calls virtual functions that perform the parameter dependent job. An example: class container { struct insert_callbacks { //One possible callback virtual copy_all_to_pos(iterator pos) = 0; } template<class FwdIt> struct fwd_it_callbacks : public insert_callbacks { fwd_it_callbacks(FwdIt first, FwdIt last) : first_(first), last_(last) {} virtual copy_all_to_pos(iterator pos) { std::copy(first, last, pos); } private: FwdIt first_, last_; } template<class ...Args> struct emplace_callbacks : public insert_callbacks { emplace_callbacks(Args&& ...args) : packed_args_(args...) {} virtual copy_all_to_pos(iterator pos) { *pos = T(unpack_somehow(packed_args_)); } private: something_to_pack packed_args_; } template<class FwdIt> void insert(iterator pos, FwdIt first, FwdIt last) { this->insert_impl(pos, fwd_it_callbacks(first, last); } template<class ...Args> void insert(iterator pos, Args &&...args) { this->insert_impl (pos, insert_callbacks(std::forward<Args>(args)...); } void insert_impl(iterator pos, insert_callbacks &cb) { //Make room for new data //... //Prepare exception handling rollbacks.. //... //Call, input-dependent code: cb.copy_all_to_pos(pos); //More code //... } }; Using this approach insert_impl avoids template arguments, generating exactly the same code for all foward iterator types and emplace functions. However, we need a function object that somehow packs arguments and forwards them perfectly to implement emplace functions this way. Since bind() copies arguments (and boost::bind does not use variadic templates yet) and reference_wrapper does not support rvalue references (at least not the latest std draft n2691), I've just started playing with gcc and using Doug Gregor's variadic templates papers' code. I've come up with a solution but that does of calling another function passing the arguments perfectly (code attached). You can use std::tr1::tuple to pack references and the expansion operator (...) to convert those packed arguments again to a function call. In the attached code we can avoid using std::tr1::tuple with a define (a compiler might have perfect forwarding but maybe the standard library is not updated yet, so I shouldn't rely on std::tr1::tuple). All this effort has been very useful to me to start playing with variadic templates, tuples, etc... but I think many boost library implementers will try to do something similar (perfect forwarding through an object function) in the future. The aim of this post is to know if any other boost library writer is playing with variadic templates and he/she has solved this issue in a simpler way. Regards, Ion P.S.: To compile attached code you need gcc 4.3 and activate c++0x support.
participants (1)
-
Ion Gaztañaga