Boost logo

Boost Users :

Subject: [Boost-users] [Fusion] Building parameter list for fusion::invoke
From: Vivek (vivek_at_[hidden])
Date: 2011-01-21 16:52:55


I am building a library in which users pass in function pointers of any
type. I would like the library to determine the function's signature (using
function_types), build a fusion vector for the function's arguments,
populate the vector with data from a particular source, and then invoke the
function using fusion::invoke.

The kicker is that the argument types may not be default constructible.
Therefore I need a way of initializing a fusion vector from a source as it
is being created.

For example, the following won't work

namespace ft = ::boost::function_types;
namespace bf = ::boost::fusion;

struct non_def_type {
private:
  non_def_type();
};

void my_func(non_def_type);

template <typename FPTR>
void my_invoker(FPTR f) {
  typedef typename ft::parameter_types<FPTR>::type parameter_types;
  typedef typename bf::result_of::as_vector<parameter_types>::type
parameter_vector;
  parameter_vector params; // error if FPTR contains a parameter_type
that is not default-constructible
  //
  // ... do something to populate params from data source
  //
  bf::invoke(f, params);
}

int main() {
  my_invoker(my_func);
}

Any idea how I might initialize the fusion vector as it is being created? I
feel like there might be a way to transform parameter_types into a version
in which each type is wrapped in a default-constructible wrapper, then
transform that list into the final boost fusion list while at the same time
populating it with data, but I can't seem to get the functors to work. E.g.:

template <typename T>
struct type_wrapper { type_wrapper() {} };

template <typename T>
struct wrap { typedef type_wrapper<T> type; };

// Metafunction to unwrap types, and function to populate data
// (data should never need to be default-constructible)
struct fill {
  template <typename SIG> struct result;

  template <typename T>
  struct result<fill(const type_wrapper<T>&)> {
    typedef T type;
  };

  // Reference type needed for bf::transform_view
  template <typename T>
  struct result<fill(type_wrapper<T>&)> {
    typedef T type;
  };
  // Non-reference type needed for bf::vector
  template <typename T>
  struct result<fill(type_wrapper<T>)> {
    typedef T type;
  };

  template <typename T> T
  operator()(const type_wrapper<T>&) const {return data_source<T>().pop();}

};

template <typename FPTR>
void my_invoker(FPTR f) {
  typedef typename ft::parameter_types<FPTR>::type parameter_types;

  // Conversion 1: create a fusion vector with types wrapped in a
  // default-constructible wrapper
  typedef mpl::transform<parameter_types, wrap<mpl::_1>,
mpl::back_inserter<mpl::vector<> > >::type wrapped_parameter_types;
  typedef typename bf::result_of::as_vector<wrapped_parameter_types>::type
wrapped_parameter_vector;

  // Conversion 2: create a fusion vector with the unwrapped types
  // that is also populated with the data from the data_source
  // (without having to ever default_construct any of the parameter_types)
  typedef typename bf::result_of::transform<const wrapped_params,
fill>::type params_view;
  typedef typename bf::result_of::as_vector<const params_view>::type
params_t;

  // Finally: invoke the function with arguments
  bf::invoke(f, bf::as_vector(bf::transform(params_view(), fill())));

}

I can't seem to get the meta-function calls or the 'fill' metafunction
itself quite right, instead getting vast reams of compiler complaints. Am I
missing something? Or alternatively, is there a direct way to initialize a
fusion vector?

Many thanks,

Vivek



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net