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::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 {
typedef T type;
};
// Reference type needed for bf::transform_view
template <typename T>
struct result {
typedef T type;
};
// Non-reference type needed for bf::vector
template <typename T>
struct result {
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::transformmpl::_1,
mpl::back_inserter > >::type wrapped_parameter_types;
typedef typename bf::result_of::as_vector::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::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