这次要说的是has_xxx.hpp, 这一段小小的代码虽然很简短,但是写得很精彩,不容错过,请大家留意了。
首先我们来谈谈has_xxx.hpp的作用, has_xxx就是用来判断某一个类中是否有xxx这个inner class,我们用has_type为例子说明问题(boost/mpl/aux_/has_type.hpp)
struct A
{
typedef int type
};
struct B
{
};
/*
....
*/
boost::mpl::aux::has_type<A>::value; // 1
boost::mpl::aux::has_type<B>::value; // 0
大家在脑子里好好想想,这样神奇的功能是怎么样创造出来的呢.??反正我是想不出,呵呵,那就来看代码 boost/mpl/has_xxx.hpp就是一个范本,其中定义了宏
BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait,name,default)
如果你的编译器和本人一样,上述的宏定义在 boost/mpl/has_xxx.hpp line: 164 在本人的编译器的版本中,最后一个参数,本人认为毫无作用,而如上文所说的has_type用到的就是这个宏来定义自身的功能
boost/mpl/aux_/has_type.hpp line:20
BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_type, type, true)
现在一切的谜团都在BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF部分,就让我们来看看其中的神奇
boost/mpl/has_xxx.hpp line: 160
namespace boost { namespace mpl { namespace aux {
template< typename T > struct msvc71_sfinae_helper { typedef void type; }; // 1
}}}
# define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, default_) /
template< typename T, typename U = void > / // 2
struct BOOST_PP_CAT(trait,_impl_) / // 3
{ /
BOOST_STATIC_CONSTANT(bool, value = false); /
typedef boost::mpl::bool_<value> type; /
}; /
/
template< typename T > /
struct BOOST_PP_CAT(trait,_impl_)< / // 4
T /
, typename boost::mpl::aux::msvc71_sfinae_helper< typename T::name >::type / // 5
> /
{ /
BOOST_STATIC_CONSTANT(bool, value = true); /
typedef boost::mpl::bool_<value> type; /
}; /
/
template< typename T, typename fallback_ = boost::mpl::bool_<default_> > /
struct trait / // 6
: BOOST_PP_CAT(trait,_impl_)<T> /
{ /
}; /
现在本人就对上述代码进行说明,我们参考对has_type的定义展开宏
BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_type,type,default)
首先在注释1处,定义了一个辅助类,这个类的作用是用来判断是否存在内嵌的类注释2处是对其中的impl_的类的定义,注意默认的typename U为void,而且事实上U并不被使用注释3处,BOOST_PP_CAT宏的作用是连接两个字符串,展开后就是 struct has_type_impl_{ 我们可以看到默认下传回的value是错误的,也即没有定义type 注释4,5处是一个特化,也就是通过注释1的辅助类判断是否有一个名为type的inner class,如果有选择4的定义,如果没有选择3 中的定义注释6中展开后为struct has_type,我们从这里可以看到两点
1. fallback_参数没有使用到。
2.has_type_impl_中第二个参数永远为void 我们可以看到,当6中的参数T带有T::type的时候,注释4处的定义更加符合,所以模板将根据注释4处的定义构造,value也就是1.反之将根据注释3处的定义构造,value为0 这样我们就可以在编译期判断某个类是否拥有某个名称的inner class了