type_traits里面有着很多的文件,很难一一阅读完,这里说明is_function这个metafunction和他们所涉及到的一些其他的源文件,愿能起到抛砖引玉的作用吧。
首先来说的就是is_function,我们首先查阅到 boost/type_traits/is_funcion.hpp line 64 struct is_function_impl 就是is_function的实现(boost源代码里面有许多这样的东西)
其中boost/type_traits/is_funcion.hpp line 64 - 77是主要部分 注意我们常见的int (*)(int,int)是函数的指针,而int (int,int)才是函数而is_function的只是对后者才返回1
boost/type_traits/is_funcion.hpp line 71 中is_function_ptr_tester在 boost/type_traits/detail/is_function_ptr_tester.hpp 中定义,可以判断是否是函数指针,我们打开 boost/type_traits/detail/is_function_ptr_tester.hpp 后发现了一大堆乱其八糟的模板函数,注意只有声明没有定义,这些函数之间的关系是重载的关系,由编译器决定哪个函数被使用,其中 boost/type_traits/detail/is_function_ptr_tester.hpp line 29
// Note it is acceptible to use ellipsis here, since the argument will
// always be a pointer type of some sort (JM 2005/06/04):
no_type BOOST_TT_DECL is_function_ptr_tester(...);
定义了一个默认为非函数指针的函数版本,而其后定了了是函数指针的版本
我们阅读is_function_ptr_tester.hpp的时候要注意以下两点
1.所谓判断是否是函数,是通过大量的丑陋的重复的代码判断的(is_function_ptr_tester.hpp line 37开始)。而这些丑陋的代码也仅仅支持到函数参数个数最多为25的函数,也就是说
boost::is_function<int (int,int,int,int,int,int,int,int,int,int,
int,int,int,int,int,int,int,int,int,int,
int,int,int,int,int,int)>::value //26个参数,value值为0
boost::is_function<int (int,int,int,int,int,int,int,int,int,int,
int,int,int,int,int,int,int,int,int,int,
int,int,int,int,int)>::value //25个参数,value值为0
2.为什么is_function_ptr_tester.hpp中对这些函数之进行了声明? 我们可以从 boost/type_traits/is_funcion.hpp line 71看到
value = sizeof(::boost::type_traits::is_function_ptr_tester(t))
== sizeof(::boost::type_traits::yes_type)
上述代码是仅在编译时判断,是通过判断返回值类型的大小来确定
boost/type_traits/detail/yes_no_type.hpp中定义了 type_traits::yes_type和type_traits::no_type boost/type_traits/detail/yes_no_type.hpp line 17
typedef char yes_type;
struct no_type
{
char padding[8];
};
我们可以知道yes_type的size是1,而no_type的size是8通过判断可以知道是否范围值为yes_type,从而可以判断该指针是否是函数指针 因为不涉及到运行时,因此仅仅需要声明而不需要定义
boost/type_traits/is_funcion.hpp line 63中
struct is_function_impl
{
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
#pragma warning(push)
#pragma warning(disable:6334)
#endif
static T* t;
BOOST_STATIC_CONSTANT(
bool, value = sizeof(::boost::type_traits::is_function_ptr_tester(t))
== sizeof(::boost::type_traits::yes_type)
);
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
#pragma warning(pop)
#endif
};
那几个#pragam warning只是关闭了warning选项的,不用理他们
其中BOOST_STATIC_CONSTANT的定义在boost/config/suffix.hpp line 350
# define BOOST_STATIC_CONSTANT(type, assignment) static const type assignment
也就是说上述代码展开后是
template <type T>
struct is_function_impl
{
static T* t;
static const bool value = (sizeof(::boost::type_traits::is_function_ptr_tester(t)) == sizeof(::boost::type_traits::yes_type)
}
而boost/type_traits/is_funcion.hpp line 80
template <typename T>
struct is_function_impl<T&> : public false_type
{};
则将全部的引用类型定义为false,其中false_type在boost/type_traits/integral_constant.hpp line:48中定义了。
现在我们知道了is_function的实现细节,只用把它包装起来就可以了 boost/type_traits/is_funcion.hpp line 89
boost/type_traits/detail/bool_trait_def.hpp line 67
#define BOOST_TT_AUX_BOOL_TRAIT_DEF1(trait,T,C) /
template< typename T > struct trait /
BOOST_TT_AUX_BOOL_C_BASE(C) /
{ /
BOOST_TT_AUX_BOOL_TRAIT_VALUE_DECL(C) /
BOOST_MPL_AUX_LAMBDA_SUPPORT(1,trait,(T)) /
}; /
/
BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(1,trait) /
其中BOOST_MPL_AUX_LAMBDA_SUPPORT因为使用的是vc8定义为空 BOOST_TT_AUX_TEMPLATE_ARITY_SPEC也因为使用vc8定义为空 而BOOST_TT_AUX_BOOL_C_BASE在bool_trait_def.hpp line 62定义
#ifndef BOOST_TT_AUX_BOOL_C_BASE
# define BOOST_TT_AUX_BOOL_C_BASE(C) : ::boost::integral_constant<bool,C>
#endif
BOOST_TT_AUX_BOOL_TRAIT_VALUE_DECL在bool_trait_def.hpp line 59中定义,伟大的vc8中定义还是为空所以,宏展开为
template< typename T > is_function
: ::boost::integral_const<bool,::boost::detail::is_function_impl<T>::value>
{
}
而boost::integral_const的定义在boost/type_traits/integral_constant.hpp很简单,其中mpl::true_在 boost/mpl/bool.hpp boost/mpl/bool_fwd.hpp 中定义 应该很容易看懂,就不罗嗦了