Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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() << ",";
    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.

like image 969
Jive Dadson Avatar asked Jan 29 '10 20:01

Jive Dadson


3 Answers

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;
}
like image 127
Kornel Kisielewicz Avatar answered Sep 19 '22 11:09

Kornel Kisielewicz


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;
}
like image 43
Jive Dadson Avatar answered Sep 18 '22 11:09

Jive Dadson


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

like image 33
NoSenseEtAl Avatar answered Sep 20 '22 11:09

NoSenseEtAl