获得全局函数和成员函数指针的部分traits的方法

来源:互联网 发布:无线网络流量测试软件 编辑:程序博客网 时间:2024/06/07 07:05

全局函数和成员函数指针不是类型,而是一种变量,虽然它们在本质上有很多区别,但是从模板的角度来说,却是非常类似的。那么如何尽可能的获取它们的traits呢?就这个问题,我做了一些简单的研究,所有的编译结果基于VS.net 2005

 

首先,我们不可能用类模板来提取traits信息,也就是说,这种traits手法和一般的type_traits不一样,也弱很多。这个的原因是,类模板如果要接受数值,那么就一定要指定类型,而指针类型正是我们要提取的信息,当然这就陷入了一种循环依赖之中。

 

那么,我将目光转向使用函数模板,事实上,函数模板本身就是用来提取变量信息,所以用这个就再恰当不过了。由于函数模板必须调用函数才能够特化,而函数中除了返回值的sizeof信息以外,其他的都是动态获得的,所以我们能在静态挖掘的信息恐怕只有经过巧妙构造的sizeof信息了。最容易想到的是,用sizeof信息获得参数的个数或者获得成员函数所在类的大小。

例如,我想提取全局函数的参数个数,我可以这样实现这个function_arg_count函数:

#include <boost/type_traits.hpp>

 

/**

  Contain size information.

 */

template <int N>

struct size_of_type

{

    char element_[N + 1];

};

 

/** Global function with no arguments. */

template <typename R>

size_of_type<boost::function_traits<R ()>::arity>

function_arg_count(R (*)());

 

/** Global function with 1 arguments. */

template <typename R, typename T1>

size_of_type<boost::function_traits<R (T1)>::arity>

function_arg_count(R (*)(T1));

 

// ...

/** Global function with 10 arguments. */

template <typename R, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10>

size_of_type<boost::function_traits<R (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)>::arity>

function_arg_count(R (*)(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10));

 

然后,使用方法是:

int main()

{

    std::cout << sizeof(function_arg_count(test_func1)) << std::endl;

    std::cout << sizeof(function_arg_count(test_func2)) << std::endl;

    std::cout << sizeof(function_arg_count(test_func3)) << std::endl;

 

    return 0;

}

 

其中,test_func1test_func2test_func3声明如下:

int test_func1(void *);

int test_func2(char, int []);

void test_func3(char, int [], float*******);

 

运行结果会是:

2

3

4

 

如果要解析成员函数,只需要在函数模板中增加一个模板参数即可。不过此时就不能用boostfunction_traits了,因为这个function_traits不支持成员函数的traits,我必须自己写一个traits类来实现这个功能。

以获取0个参数的函数为例:

/**

  Member function traits helper.

 */

template <typename Function>

struct member_function_traits_helper;

 

template <typename R, typename Parent>

struct member_function_traits_helper<R (Parent::*)()>

{

    BOOST_STATIC_CONSTANT(int, arity = 0);

    typedef R result_type;

    typedef Parent parent_type;

};

 

/**

  Member function traits.

 */

template <typename Function>

struct member_function_traits :

    public member_function_traits_helper<Function>

{

};

 

/** Member function with no arguments. */

template <typename R, typename Parent>

size_of_type<member_function_traits<R (Parent::*)()>::arity>

function_arg_count(R (Parent::*)());

 

这样就OK了,其他的类似,包括需要自己扩展这个member_function_traits

使用方法是:

int main()

{

    std::cout << sizeof(function_arg_count(&test_class::func0)) << std::endl;

    std::cout << sizeof(function_arg_count(&test_class::func1)) << std::endl;

    std::cout << sizeof(function_arg_count(&test_class::func2)) << std::endl;

 

    return 0;

}

 

其中,test_class的声明是:

class test_class

{

public: // Note: You can only get traits of public function.

    void func0();

    int func1(char);

    std::string& func2(int, double&);

};

 

运行结果是:

1

2

3

 

至于如何获得成员函数所在的类的大小,相信已经是非常自然而然,就不再敷述。

 

值得注意的是,除了这些编译期间的traits,我还可以使用typeid获得运行时的特征,这样也可以解决某些traits的需求。现在只举一个例子:

template <int N>

struct arg_index

{

};

 

template <typename R,

typename T1,

typename T2,

typename argN,

typename Ret>

Ret function_arg_typename(R (T1, T2), argN);

 

template <typename R,

typename T1,

typename T2>

T1 function_arg_typename<>(R (T1, T2), arg_index<0>);

 

template <typename R,

typename T1,

typename T2>

T2 function_arg_typename<>(R (T1, T2), arg_index<1>);

 

使用方法如下:

int main()

{

    std::cout << typeid(function_arg_typename(test_func2, arg_index<0>())).name() << std::endl;

    std::cout << typeid(function_arg_typename(test_func2, arg_index<1>())).name() << std::endl;

}

 

其中,test_func2声明如下:

int test_func2(int , char *);

 

运行结果是:

int

char *

 <iframe frameborder="0" id="gn_notemagic" style="position: absolute; display: block; opacity: 0.7; z-index: 500; width: 16px; height: 20px; top: 54px; right: 396px;" src="http://www.google.com/gn/static_files/blank.html"></iframe>
原创粉丝点击