[MPL] initialization of member that might be non-copyable

I'm working on something similar to the construct devised in the MPL book Section 9.5 (class composition). Some objects in the composed type might require initialization. I've solved this problem. However, in solving that problem I've now required that any type going into the composition must be copyable. However, since the original composition code doesn't make this requirement I've been trying to find a way to retain the ability to contain types that are non-copyable. Here's some code: template < typename Field > struct field_value { typedef Field field; typedef typename Field::type ftype; ftype value; field_value(ftype const& t) : value(t) {} field_value() : value() {} }; template < typename Field, typename ParamFields, typename Enable = void > struct initializer { template < typename Params > static typename Field::type apply(Params &) { return Field::type(); } }; template < typename Field, typename ParamFields > struct initializer<Field,ParamFields, typename boost::enable_if< boost::mpl::contains<typename Params::fields, typename FieldValue::field> >::type > { template < typename Params > static typename Field::type apply(Params & params) { return get<Field>(params); } }; template < typename FieldValue, typename Params > FieldValue init_field(Params & pars) { return initializer<typename FieldValue::field, typename Params::fields >::apply(pars); } template < typename FieldValue, typename More > struct record_base : FieldValue, More { template < typename Params > record_base(Params & pars) : FieldValue(init_field<FieldValue>(pars)) , More(pars) {} record_base() : FieldValue(), More() {} }; struct empty_record_base { template < typename Ignored > empty_record_base(Ignored&){} empty_record_base() {} }; template < typename MplSequence > struct build_record { typedef boost::mpl::placeholders::_1 _1; typedef boost::mpl::placeholders::_2 _2; typedef typename boost::mpl::fold < MplSequence , empty_record_base , record_base< field_value<_2>, _1 > >::type type; // type should be record_base< field_value<field0> // , record_base< field_value<field1> // , ... record_base<field_value<fieldN>, empty_record_base> // > ... // > }; It's at this point: template < typename Params > record_base(Params & pars) : FieldValue(init_field<FieldValue>(pars)) , More(pars) {} That I need to apply something, I know not what, to correctly initialize the field with either a parameter argument or nothing. I can't think of any construct that would make that possible but I don't necessarily know everything. Is there some way that this can be accomplished?

On 3/25/2011 1:48 PM, Noah Roberts wrote: [snip bad code] I posted bits that I'd been experimenting and reverted stuff without testing. Here's corrected version: template < typename Field > struct field_value { typedef Field field; typedef typename Field::type ftype; ftype value; field_value(ftype const& t) : value(t) {} field_value() : value() {} }; template < typename Field, typename Params, typename Enable = void > struct initializer { static typename Field::type apply(Params &) { return Field::type(); } }; template < typename Field, typename Params > struct initializer<Field,Params, typename boost::enable_if< boost::mpl::contains<typename Params::fields, Field> >::type > { static typename Field::type apply(Params & params) { return get<Field>(params); } }; template < typename FieldValue, typename Params > FieldValue init_field(Params & pars) { return initializer<typename FieldValue::field, Params >::apply(pars); } template < typename FieldValue, typename More > struct record_base : FieldValue, More { template < typename Params > record_base(Params & pars) : FieldValue(init_field<FieldValue>(pars)) , More(pars) {} record_base() : FieldValue(), More() {} }; struct empty_record_base { template < typename Ignored > empty_record_base(Ignored&){} empty_record_base() {} }; template < typename MplSequence > struct build_record { typedef boost::mpl::placeholders::_1 _1; typedef boost::mpl::placeholders::_2 _2; typedef typename boost::mpl::fold < MplSequence , empty_record_base , record_base< field_value<_2>, _1 > >::type type; // type should be record_base< field_value<field0> // , record_base< field_value<field1> // , ... record_base<field_value<fieldN>, empty_record_base> // > ... // > };

On 03/25/11 15:53, Noah Roberts wrote:
On 3/25/2011 1:48 PM, Noah Roberts wrote: [snip bad code]
I posted bits that I'd been experimenting and reverted stuff without testing. Here's corrected version:
template < typename Field > struct field_value { typedef Field field; typedef typename Field::type ftype; ftype value;
field_value(ftype const& t) : value(t) {} field_value() : value() {} };
template < typename Field, typename Params, typename Enable = void > struct initializer { static typename Field::type apply(Params &) { return Field::type(); } }; template < typename Field, typename Params > struct initializer<Field,Params, typename boost::enable_if< boost::mpl::contains<typename Params::fields, Field> >::type > { static typename Field::type apply(Params & params) { return get<Field>(params); } };
template < typename FieldValue, typename Params > FieldValue init_field(Params & pars) { return initializer<typename FieldValue::field, Params >::apply(pars); }
template < typename FieldValue, typename More > struct record_base : FieldValue, More { template < typename Params > record_base(Params & pars) : FieldValue(init_field<FieldValue>(pars)) , More(pars) {}
record_base() : FieldValue(), More() {} }; struct empty_record_base { template < typename Ignored > empty_record_base(Ignored&){} empty_record_base() {} };
template < typename MplSequence > struct build_record { typedef boost::mpl::placeholders::_1 _1; typedef boost::mpl::placeholders::_2 _2;
typedef typename boost::mpl::fold < MplSequence , empty_record_base , record_base< field_value<_2>, _1 > >::type type;
// type should be record_base< field_value<field0> // , record_base< field_value<field1> // , ... // , record_base<field_value<fieldN> // , empty_record_base> // > ... // };
Hi Noah, After comparing with Section 9.5 of the MPL book, it seems the correspondence between this code and the book's is: this_code the book --------- ---------- empty_record_base empty_base field_value wrap record_base inherit and the major difference is is field_value, which, I suppose will be used (after possibly some modification) to allow a non-copyable member. Is that right? Since record_base has no constructor taking this into account, I'm guessing you're really asking how to create such a constructor and maybe modifications to field_value to make this possible. Right? -regards, Larry BTW, there's no get template defined above. I assume it will be something like the get on p. 192 of the book?

On 03/25/11 15:53, Noah Roberts wrote:
On 3/25/2011 1:48 PM, Noah Roberts wrote: [snip bad code]
I posted bits that I'd been experimenting and reverted stuff without testing. Here's corrected version: [snip] Hi Noah,
Are you having any luck with this? I'd liks to see how you've done it and/or what difficulties you had doing it. TIA. -Larry

On 04/03/11 13:59, Larry Evans wrote:
On 03/25/11 15:53, Noah Roberts wrote:
On 3/25/2011 1:48 PM, Noah Roberts wrote: [snip bad code]
I posted bits that I'd been experimenting and reverted stuff without testing. Here's corrected version: [snip] Hi Noah,
Are you having any luck with this? I'd liks to see how you've done it and/or what difficulties you had doing it.
TIA.
-Larry
The code here: http://svn.boost.org/svn/boost/sandbox/variadic_templates/libs/composite_sto... has non-copyable template classes: template < unsigned I
struct charvec_double : charvec_u<I> { double d; charvec_double() : d(-1000.0-double(I)) {} charvec_double(char c) : charvec_u<I>(c) , d(-100.0-double(I)) {} charvec_double(double _d) : d(_d) {} charvec_double(char c,double _d) : charvec_u<I>(c) , d(_d) {} private: charvec_double(charvec_double const&) /**@brief * Disallow copy CTOR */ ; }; used as components in a heterogeneous container type: typedef pack::indexed_ctor_args_all_of_aligned < mpl::integral_c<index_numerals,index_0> , charvec_double<0> , charvec_double<1> , charvec_double<2> , charvec_double<3> > tagged_type ; and initialized, without using the copy CTOR's. Instead, it uses something like the named parameters syntax: http://en.wikipedia.org/wiki/Named_parameter where, in this case, the name for the parameters is their index template: index<index_numerals,index_I> In the test code mentioned, this appears as: index < index_numerals , index_0 > ndx0 ; index < index_numerals , index_3 > ndx3 ; tagged_type tagged_arg ( ndx3=double(1000.3) //show out-of-order initialization , ndx0='x' #if 1 , index<index_numerals,index_2>() = 'z' #else //This should produce compile-time error because of multiple index_0 associations. , ndx0='z' #endif ) ; Note the #else comments. If the same name is used more than once, a compile error (obscure, as usual) is produced. The output produced from the following print statements are: :project<index_0>=charvec_double<0>:id_get=12:v[0]=x:d=-100 :project<index_1>=charvec_double<1>:id_get=13:v[0]=a:d=-1001 :project<index_2>=charvec_double<2>:id_get=14:v[0]=z:d=-102 :project<index_3>=charvec_double<3>:id_get=15:v[0]=a:d=1000.3 Of course, in real code, the index_numerals would have more meaningful names. The heart of the solution is in: http://svn.boost.org/svn/boost/sandbox/variadic_templates/boost/composite_st... in templated CTOR: template < index_type... Keys , typename... CtorTypes > indexed_ctor_args_all_of_aligned ( index_component < index_type , Keys , CtorTypes >const&... ctor_args ) Here, the Keys... are the indices, and the CtorTypes... are the types of arguments to the components associated with the corresonding key in Keys.... The value of those componens are, obvious, retrieved using the my_comp member variable of the index_component<Key,CtorType> values. HTH. -Larry

On 03/25/11 15:48, Noah Roberts wrote:
I'm working on something similar to the construct devised in the MPL book Section 9.5 (class composition). Some objects in the composed type might require initialization. I've solved this problem.
However, in solving that problem I've now required that any type going into the composition must be copyable. However, since the original composition code doesn't make this requirement I've been trying to find a way to retain the ability to contain types that are non-copyable. [snip]
So, I guess you've looked at the other container types in boost, such as fusion's vector: http://www.boost.org/doc/libs/1_46_1/libs/fusion/doc/html/fusion/container/v... and found them lacking in this regard. IOW, with these other container types, all the contained types must be copyable? -Larry
participants (2)
-
Larry Evans
-
Noah Roberts