[traits/function_types/generic] Can F be called with {a0, ..., aN}?

Hello, I have been trying to achieve assignment to a variant of functions, typedef boost::variant< boost::function< int >, boost::function< int, int >
variant_type;
which is nice until you try to assign an ambiguous callable object to it, especially if the callable object has templates or similar. This has lead to my question: is there a way to know (without the "no matching function call" compiler error if {a0,...,aN} in F(a0,a1,...,aN) are permissible arguments to callable object/function F? I thought I had a nice solution by overriding boost::result_of< F(a0,a1..,aN)>::type in such way that it doesn't give compile errors if a type doesn't exist, but mpl::na (in conjunction with a has_result_of<T> meta-function). Then, writing functors like struct some_func { template< typename Sig > struct result { // no type defined here, so result_of<>::type is not defined } template< ... > struct result< enable_if arguments are acceptable > { typedef ... type; } R operator()( ... ) {} }; gives you the ability to answer the question for those particular functors. However, some widely used stuff like boost::bind always has a result_type, so this trick was a dead end. So, in short, does anyone know of a generic trick to know if F can be called with a set parameters {a0,...,aN} (without the compile error)? Thanks, Cheers, Rutger

Rutger ter Borg
So, in short, does anyone know of a generic trick to know if F can be called with a set parameters {a0,...,aN} (without the compile error)?
Not sure if this is what you want, but I was pointed to the following previously: http://www.boost.org/doc/libs/1_42_0/doc/html/proto/appendices.html#boost_pr... pendices.implementation.function_arity This works for most function objects, but not for function pointers. To implement those, I ended up doing a dispatch and determining if the arguments were convertible. Here is a link to my (inelegant) solution: http://svn.econtoolkit.com/libraries/trunk/etk/etk/meta/function_traits.hpp And my test file: http://svn.econtoolkit.com/libraries/trunk/etk/tests/meta/test_function_trai... Also: I found that this worked fine with C++0X lambdas on Intel 11.1 but didn't work with Phoneix, boost::lambda, or std::bind. I posted a question on this problem for phoenix a little while ago, but didn't find a solution.

Jesse Perla wrote:
Not sure if this is what you want, but I was pointed to the following previously:
http://www.boost.org/doc/libs/1_42_0/doc/html/proto/appendices.html#boost_pr...
pendices.implementation.function_arity
Exactly what I was looking for! I knew there had to be some nifty trick.. Thanks!
This works for most function objects, but not for function pointers. To implement those, I ended up doing a dispatch and determining if the arguments were convertible.
Please find attached my take on it. It should work for function pointers, function references, member function pointers, and function objects. Perhaps we can shave it up a bit further and propose to type_traits lib or the like.. Cheers, Rutger

Rutger ter Borg
Please find attached my take on it. It should work for function pointers, function references, member function pointers, and function objects.
Far prettier, as I expected. I suppose one day I will have to learn about doing this kind of stuff boost preprocessor and MPL.
Perhaps we can shave it up a bit further and propose to type_traits lib or the like..
Yup. I think it is very useful. Though without getting it to work with phoenix or std::tr1::bind, I think it have limited appeal. I also would guess (though haven't tested) that the trick fails with boost::function as well.

Jesse Perla wrote:
Yup. I think it is very useful. Though without getting it to work with phoenix or std::tr1::bind, I think it have limited appeal. I also would guess (though haven't tested) that the trick fails with boost::function as well.
I have it working in conjunction with Boost.Function. I extended boost::function_types::parameter_types<T> to also work for boost::function. Then, if the expression is_callable< some_unknown_functor, boost_function_parameter_types > evaluates to true, then I can do the assignment (the right one from a variant of functions), boost::function< known_signature > = some_unknown_functor this works fine (the parameter types come from the boost::function). What do you mean exactly by support for bind? As long as you supply the parameters, it should work. I.e., is_callable< unknown_bind_expression, known_parameters > should also work. Could you provide an example / test case? Thanks, Rutger

Jesse Perla wrote:
Yup. I think it is very useful. Though without getting it to work with phoenix or std::tr1::bind, I think it have limited appeal. I also would guess (though haven't tested) that the trick fails with boost::function as well.
Perhaps this is because void some_f( int ) {} boost::bind( &some_f, _1 )( 1, 1, 1, 1, 1 ); compiles and works? But you probably mean that boost::bind( &some_f, _1 )( "some_other_type" ); doesn't compile, whereas is_callable< BOOST_TYPEOF( boost::bind( &some_f, _1 ) ), boost::mpl::vector< std::string > > is true_. I see. I will check if this indirection can be detected somewhere... Cheers, Rutger

Rutger ter Borg
is_callable< BOOST_TYPEOF( boost::bind( &some_f, _1 ) ), boost::mpl::vector< std::string > > is true_.
Yup. The other problem I found was that it couldn't successfully detect if the 'arity mismatched and return false. You can see my test cases with my old implementation in: http://svn.econtoolkit.com/libraries/trunk/etk/tests/meta/test_function_trai... I put in comments for the static asserts that didn't work. See the "test_unary_function_compatibility" in particular.
I see. I will check if this indirection can be detected somewhere...
I was mainly using std::tr1::bind here rather than boost bind, but since people keep telling me to move to phoenix rather than boost::bind and boost::lambda I was mainly worried about those cases. I also found that boost::lambda wouldn't even compile with the "trick" which is why I ended up returning true_ for now.
participants (2)
-
Jesse Perla
-
Rutger ter Borg