获得全局函数和成员函数指针的部分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 *
首先,我们不可能用类模板来提取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 *
相关文章推荐
- C++ MFC 其他函数获得主对话框指针并使用成员的方法
- C++ MFC 其他函数获得主对话框指针并使用成员的方法
- C++成员函数指针的另类调用方法
- c++ 全局函数指针和类成员函数指针
- C++ string 类 部分成员函数实现(实现COW copy-on-write+实现智能指针(有极大bug版本))
- 类的成员函数指针的使用方法
- 非static成员函数通过类名::来调用,空指针调用成员方法不出错!
- php部分(查看文件、建立站点、语法变量、变量的几个方法、“全局局部变量的调用”、static、函数参数的作用域);
- 全局函数访问类成员方法
- 为什么通过空指针(NULL)能够正确调用类的部分成员函数
- 为什么通过空指针(NULL)可以正确调用类的部分成员函数
- 类成员函数返回(成员)函数指针,包装类调用外部类的成员方法
- c++ 如何把this指针传入成员函数 像全局函数一样调用成员函数
- 【转】C++编程中用指针直接调用类成员函数问题及其解决方法
- 把全局函数指针指向类的成员函数
- this指针指向当前调用对象,只是用于类的非静态成员函数。静态函数和全局函数 无当前对象,无this指针。
- 谈函数指针(全局/类成员函数)和函数对象
- 类的成员函数指针的使用方法
- 获得全局视图指针的方法
- C++的 成员函数指针, 静态函数指针,全局函数指针 区别