Text:
I am trying to implement an MPI task pool. Therefore, I need some kind of RPC, but one that will work between different parts of my program, that is, processor A wants processor B to call function C with argument D. We cannot pass pointers to functions between processes, as we do with threads, so we need some kind of container container for storing pointers to each process instance. Everything inside one source file \ one program ... So I started to wonder about How to store functional objects with a different signature in the container . My idea of โโthe API was wrong then - itโs better to define all the functions in the function pool when building this pool (at least it will be much easier to implement). But during implementation, I ran into the following problem:
Problem:
Such simple code ( function_types , mpl :: vector , variant ):
#include <boost/function_types/function_type.hpp> #include <boost/mpl/vector.hpp> #include <boost/mpl/vector_c.hpp> #include <boost/variant.hpp> #include <iostream> #include <string> template <class T> int append(T val) { std::cout << "hello"; return 0; } int main() { boost::variant<boost::function_types::function_type< boost::mpl::vector<int,int> >::type , boost::function_types::function_type< boost::mpl::vector<int,std::string> >::type > a; return 0; }
Will not compile with:
Error 1 error C2066: cast to function type is illegal c:\program files\boost\include\boost\variant\variant.hpp 1231 1
And looking at the source , we see:
this code block:
variant() { // NOTE TO USER : // Compile error from here indicates that the first bound // type is not default-constructible, and so variant cannot // support its own default-construction. // new( storage_.address() ) internal_T0(); indicate_which(0); // zero is the index of the first bounded type }
So, I am wondering: how to get around this error?
Also I tried:
#include <boost/function_types/function_type.hpp> #include <boost/mpl/vector.hpp> #include <boost/mpl/vector_c.hpp> #include <boost/variant.hpp> #include <boost/function.hpp> #include <iostream> #include <string> template <class T> int append(T val) { std::cout << "hello"; return 1; } int main() { boost::variant< boost::function<int (std::string) >, boost::function<int (int) > > a; a= &append<int>; return 0; }
Failure:
Error 1 error C2668: 'boost::detail::variant::make_initializer_node::apply<BaseIndexPair,Iterator>::initializer_node::initialize' : ambiguous call to overloaded function c:\program files\boost\include\boost\variant\variant.hpp 1330
Any ideas on how to make boost.variant hold functions?
Of course, we can play with common pointers to such functors:
#include <boost/variant.hpp> #include <boost/shared_ptr.hpp> #include <iostream> #include <string> template <class in, class out> struct s_append { out operator()(in val) { std::cout << "hello"; return out(); } }; int main() { boost::variant<boost::shared_ptr<s_append<int, int> >, boost::shared_ptr< s_append<std::string, int> > > a; boost::shared_ptr<s_append<int, int> > b(new s_append<int, int> ); a=b; return 0; }
and it will compile, but as a result of the API sucks - you need 1) to create functors for all the functions that you want to use (which means limiting the use of the current process area); 2) use shared_pointers, and therefore I donโt even understand how to call functions nested this way (a simple first guess (*a)(22); just wonโt compile = (and the API will start to be as bad as we would use Boost .Any).