[accumulator] extract_result during initialization

Hi All, I have an accumulator (a) that takes an initial value (x_), and another (b), whose initial value (x_) depends on that of (a). I would have thought that this is feasible because accumulator_set initializes (a) before (b), but apparently b.x_ is initialized with a garbage value. namespace impl { template<typename Sample,typename Id> class accu_a_impl : public accumulator_base { public: typedef Sample result_type; template<typename Args> accu_a_impl(Args const &args) :x_( args[kwd<Id>::value] ) { } result_type result(dont_care) const { return x_; } private: result_type x_; }; } namespace tag { template <typename Id = mpl::void_> struct accu_a : depends_on<> { typedef accumulators::impl::accu_a_impl<mpl::_1,Id> impl; }; } namespace impl { template<typename Sample,typename Id0,typename Id1> class accu_b_impl : public accumulator_base { typedef tag::accu_a<Id1> a_type; public: typedef Sample result_type; template<typename Args> accu_b_impl(Args const &args) :x_( extract_result<a_type>(args[accumulator]) // faulty? ) { } template<typename Args> void operator ()(Args const &args) { // overrides initialization for the sake of testing x_ = extract_result<a_type>(args[accumulator]); } private: result_type x_; }; } namespace tag { template <typename Id0,typename Id1=mpl::void_> struct accu_b : depends_on<tag::accu_a<Id1> > { typedef accumulators::impl::accu_b_impl<mpl::_1,Id0,Id1> impl; }; } *.cpp typedef mpl::size_t<0> id0; typedef mpl::size_t<1> id1; typedef double value_type; typedef tag::accu_a<id0> a_type; typedef tag::accu_b<id1,id0> b_type; typedef accumulator_set< value_type, stats< b_type > > set_type; set_type set( ( kwd<id0>::value = 0.9 ) ); std::cout << "a.x_=" << extract_result<a_type>(set) << std::endl; std::cout << "b.x_=" << extract_result<b_type>(set) << std::endl; set(0); std::cout << "b.x_=" << extract_result<b_type>(set) << std::endl; //Output: //a.x_=0.9 //b.x_=0.1 // where 0.9 is expected //b.x_=0.9

er wrote: I would have
thought that this is feasible because accumulator_set initializes (a) before (b), but apparently b.x_ is initialized with a garbage value.
Still trying to figure it out ... Also did the following check (OK) : typedef set_type::accumulators_mpl_vector::type wrapped_features; typedef mpl::transform< wrapped_features, accumulators::detail::feature_tag<mpl::_1>
::type features;
BOOST_STATIC_ASSERT(( mpl::equal_to< mpl::size_t<2>, mpl::size<features>::type >::value )); //OK typedef mpl::back<features>::type actual_back; BOOST_STATIC_ASSERT(( is_same<b_type,actual_back>::value )); //OK

er wrote:
er wrote: I would have
thought that this is feasible because accumulator_set initializes (a) before (b), but apparently b.x_ is initialized with a garbage value. <snip>
It's not going to work without major surgery. The accumulator_set has one data member, which is a Fusion list of all the accumulators in the set. It is not initialized in-place; rather, a separate routine creates and initializes a Fusion list, which is then copied into the accumulator_set in the last step. That means you'll get garbage if you try to extract results from an accumulator_set while it's being constructed. It would be nice if the list were initialized in-place, but I'm not sure how to do that, and I don't have the time to look into it. Please file a feature request. In the mean time, is there any way you can change your design so that it doesn't depend on the ability to extract results from a partially constructed accumulator set? It seems dodgy at best to rely on this behavior. -- Eric Niebler BoostPro Computing http://www.boostpro.com

Eric Niebler wrote:
er wrote:
er wrote: I would have
thought that this is feasible because accumulator_set initializes (a) before (b), but apparently b.x_ is initialized with a garbage value. <snip>
It's not going to work without major surgery. The accumulator_set has one data member, which is a Fusion list of all the accumulators in the set. It is not initialized in-place; rather, a separate routine creates and initializes a Fusion list, which is then copied into the accumulator_set in the last step. That means you'll get garbage if you try to extract results from an accumulator_set while it's being constructed.
Thanks , that will save me trying un-necessarily.
It would be nice if the list were initialized in-place, but I'm not sure how to do that, and I don't have the time to look into it. Please file a feature request.
OK. In the mean time, is there any way you can change your
design so that it doesn't depend on the ability to extract results from a partially constructed accumulator set?
Actually, I extracted the backbone of Accumulators to manage more general dependent features. Amongst other things, I dropped the dependency on RealType and the new definition of visitor is visitor::operator()(feature) calls f(feature,args), where f and args are passed in the constructor of visitor. I simply delay initialization until the set is constructed: set_type set; set.initialize(args) forwards to set.visit(initialize_op(),params()(*this,args)), where initialize_op::operator()(feature,args) calls feature.initialize(args) but instead, I could probably remove the burden of having to define initialize for each feature with something like: feature = feature_type(args);
participants (2)
-
er
-
Eric Niebler