STL揭秘之编译期纯虚类判断__is_abstract_imp

首先列上代码:

__is_abstract_imp命名空间里声明了两个重载的模板函数,返回值分别为char和__two。声明这两个函数的意义在于,我们可以通过编译期重载函数的匹配来判断传入的模板参数是否符合我们的要求,判断的方式也很简单,只要使用sizeof操作符就行了:

上行代码的含义也很简单明了,即匹配第一个重载函数时,sizeof的结果为1,匹配第二个重载函数时sizeof的结果为2,所以我们就实现了编译期的类型判断。

那么,我们就需要进一步理解为啥通过这两重载函数可以判断出一个类类型是否为纯虚类,即何时_Tp (*)[1]会匹配成功。

_Tp (*)[1]这写法乍一看会让人感到莫名其妙,也很容易让人联想到是否跟类的虚函数表有关(我就在这卡了很久),实际上并没有那么复杂,我们只要将它换种写法一切就豁然开朗了:

参数p不就是一个指向_TP类型的数组的指针(即数组指针)吗,前面的写法只是省去了参数名而已。。。。理解起来就是下面这样:

后面的[1]代表的是指向一个只拥有一个元素的数组的指针(所以如果你将其改成0,会造成编辑器的警告,因为定义了一个指向0个元素的数组的指针)。

那么接下来就很好理解了,因为纯虚类无法实例化,所以我们无法定义一个纯虚类对象的数组(注意不是纯虚类对象指针的数组,即是TP  a[1],不是TP* a[1]),所以在遇到纯虚类时第一个重载函数匹配会失败,而遇到非纯虚类第一个重载函数却能匹配成功,所以我们现在就能够通过这个模板来判断传入模板参数的类型是否为纯虚类类型了。

到这里,有的人可能还会有疑问,为什么我们需要这样写呢,写成下面这样不行么,不是一样也能判断模板的参数类型么,而且还更好理解:

实际上这并不是stl在故意炫技,我们需要注意的是sizeof的写法:

即sizeof在计算函数返回值大小的时候必须给函数传入一个参数,并且我们需要让sizeof的计算发生在编译期而非运行期,我们是不可能创建一个_TP对象传进去的,也就是说这里__test最理想的参数就是指针了,我们只需要传入0作为参数就可以了,所以这里最好的参数选择就是指针数组了。

最后,感谢同事给的思路启发,摸摸哒:)

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

  1. Pingback: STL揭秘之外覆器integral_constant – 小溪开大船