Use Boost to get arity and paramerter types of member function? (boost::function_traits)
It works just fine, for plain vanilla functions. The code below works just fine. It prints just what is should:
int __cdecl(int, char)
2
int,char
#include <boost/type_traits.hpp>
#include <boost/function.hpp>
#include <boost/typeof/std/utility.hpp>
#include <iostream>
using std::cout;
using std::endl;
int foo(int, char) {
return 0;
}
int main() {
typedef BOOST_TYPEOF(foo) foo_type;;
typedef boost::function_traits<foo_type> function_traits;
cout << typeid(foo_type).name() << endl;
cout << function_traits::arity << endl;
cout << typeid(function_traits::arg1_type).name() << ",";
开发者_JAVA技巧 cout << typeid(function_traits::arg2_type).name() << endl;
return 0;
}
So, the question is, how can one do this if foo is a member function of class bar?
struct bar {
int foo(int, char) { return 0; }
};
I have tried countless combinations of these constructs: BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() BOOST_TYPEOF_REGISTER_TYPE() boost::ref boost::remove_pointer boost::bind boost::mem_fn
etc., etc... No joy.
Boost Function Types would probably be the natural solution:
#include <boost/function_types/function_type.hpp>
#include <boost/function_types/parameter_types.hpp>
#include <boost/function_types/function_arity.hpp>
#include <boost/typeof/std/utility.hpp>
#include <boost/typeof/typeof.hpp>
#include <iostream>
struct bar {
int foo(int, char) { return 0; }
};
int main() {
typedef BOOST_TYPEOF(&bar::foo) foo_type;
std::cout << typeid(foo_type).name() << std::endl;
std::cout << boost::function_types::function_arity<foo_type>::value << std::endl;
std::cout << typeid(boost::mpl::at_c<boost::function_types::parameter_types<foo_type>,1>::type).name() << ",";
std::cout << typeid(boost::mpl::at_c<boost::function_types::parameter_types<foo_type>,2>::type).name() << ",";
return 0;
}
Kornel Kisielewicz nailed it. Here it is with the solution separated from the test-messages.
#include <boost/function_types/function_type.hpp>
#include <boost/function_types/parameter_types.hpp>
#include <boost/function_types/function_arity.hpp>
#include <boost/typeof/std/utility.hpp>
#include <iostream>
struct bar {
int foo(int, char) { return 0; }
};
int main() {
typedef BOOST_TYPEOF(&bar::foo)
foo_type;
int arity = boost::function_types::function_arity<foo_type>::value;
typedef boost::mpl::at_c<boost::function_types::parameter_types<foo_type>,1>::type
arg1;
typedef boost::mpl::at_c<boost::function_types::parameter_types<foo_type>,2>::type
arg2;
std::cout << typeid(foo_type).name() << std::endl;
std::cout << arity << std::endl;
std::cout << typeid(arg1).name() << ",";
std::cout << typeid(arg2).name() << std::endl;
return 0;
}
This can be done with newer boost lib(callable traits, bonus: it works with lambdas also).
I have also added the another printout with a human readable output, although not sure if the question demands it.
#include <boost/mp11.hpp>
#include <boost/callable_traits.hpp>
#include <iostream>
#include <type_traits>
#include <boost/type_index.hpp>
using namespace std;
using namespace boost::mp11;
using namespace boost::typeindex;
namespace ct = boost::callable_traits;
struct bar {
int foo(int, char) { return 0; }
};
int main() {
using Fn = decltype(&bar::foo);
cout << typeid(Fn).name() << endl;
cout << tuple_size<ct::args_t<Fn>>::value << endl; // includes implicit this
cout << typeid(mp_at_c<ct::args_t<Fn>,0>).name() << ",";
cout << typeid(mp_at_c<ct::args_t<Fn>,1>).name() << endl;
cout << "Human readable" << endl;
cout << type_id<Fn>().pretty_name() << endl;
cout << tuple_size<ct::args_t<Fn>>::value << endl; // includes implicit this
cout << type_id<mp_at_c<ct::args_t<Fn>,0>>().pretty_name() << ",";
cout << type_id<mp_at_c<ct::args_t<Fn>,1>>().pretty_name() << endl;
return 0;
}
gcc output:
M3barFiicE
3
3bar,i
Human readable
int (bar::*)(int, char)
3
bar,int
精彩评论