19.8.7 IID_traits
现在,与接口强制的实现有关的就只剩下一件事情,即接口强制是如何来确定接口标识符的。很简单,我们使用经典的技术[Lipp1998]来将类型与值关联到一起,即traits技术。IDD_traits是一个接口标识符traits类,其定义如下:
- template <class I>
- struct IID_traits
- {
- public:
- static REFIID iid();
- };
善意的忠告:在那些支持微软__uuidof()扩展的编译器上,我走了捷径,(对于一般情况)我将iid()方法定义成这样:- template <class I>
- inline /* static */ REFIID IID_traits<I>::iid()
- {
- return __uuidof(I);
- }
对于那些不支持__uuidof()扩展的编译器而言,IID_traits并不提供任何缺省定义,你必须自行(为Interface和Interface*)定义自己的特化。COMSTL_IID_TRAITS_DEFINE()宏就是为此而准备的,因此,所有目前存在的标准接口都在comstl_interface_traits_std.h头文件当中特化过了,在这类编译器上面,该头文件是自动被包含进来的:- #ifdef __IClassFactory_FWD_DEFINED__
- COMSTL_IID_TRAITS_DEFINE(IClassFactory)
- #endif /* __IClassFactory_FWD_DEFINED__ */
如果用户的编译器不支持__uuidof(),他们就必须以类似的方式来为他们自己的接口定义特化版本的IID_traits。这并不是理想的方式,但毕竟也不算麻烦,此外这种做法还相当安全:由于IID_traits并不提供一个缺省情况下的实现,所以任何错误都不能逃过编译器这一关。
从理想主义的角度来看,对于不得不违背关于回避专有扩展的原则,人们会感到恼火,但这里实用主义占了上风(而且我估计大部分时候都是如此)。只要不至于过分依赖这些专有扩展,我想我们还是愿意使用它们的。毕竟我们的目标是写出最高质量的软件而不是最"纯粹"的软件!