您的位置:首页 > 大数据 > 人工智能

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

2006-09-09 11:28 471 查看
全局函数和成员函数指针不是类型,而是一种变量,虽然它们在本质上有很多区别,但是从模板的角度来说,却是非常类似的。那么如何尽可能的获取它们的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_func1、test_func2和test_func3声明如下:
int test_func1(void *);
int test_func2(char, int []);
void test_func3(char, int [], float*******);

运行结果会是:
2
3
4

如果要解析成员函数,只需要在函数模板中增加一个模板参数即可。不过此时就不能用boost的function_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 *
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: