Posted on 2008-07-05 20:54 
cexer 阅读(1783) 
评论(0)  编辑 收藏 引用  所属分类: 
utility 
			
			
		 
		转自 CSDN 许式伟的专栏
  这个技巧不是针对VC++ 6.0缺陷的,而是针对VC++扩展语法的。这个技巧的来由,是为了某些希望有一天有可能要脱离Visual C++环境进行开发的人员。为了脱离VC++,你需要谨慎使用它的所有扩展语法。例如本文讨论的__uuidof。我们先来看看一个例子:
    class __declspec(uuid("B372C9F6-1959-4650-960D-73F20CD479BA")) Class;   
    struct __declspec(uuid("B372C9F6-1959-4650-960D-73F20CD479BB")) Interface;   
        
    void test()   
    {   
        CLSID clsid=__uuidof(Class);   
        IID iid=__uuidof(Interface);   
        ...   
    }
 
  这比起你以前定义uuid的方法简单多了吧?可惜,这样好用的东西,它只在VC++中提供。不过没有关系,我们这里介绍一个技巧,可以让你在几乎所有C++编译器中都可以这样方便的使用__uuidof。这里没有说是所有,是因为我们使用了模板特化技术,可能存在一些比较“古老”的 C++编译器,不支持该特性。
  也许你已经迫不及待了。好,让我们来看看:
    #include <string>   
    #include <cassert>   
        
    inline STDMETHODIMP_(GUID) GUIDFromString(LPOLESTR lpsz)   
    {   
       HRESULT hr;   
       GUID guid;   
       if (lpsz[0]=='{')   
       {  
            hr=CLSIDFromString(lpsz,&guid);  
        }  
        else  
        {  
            std::basic_string<OLECHAR> strGuid;  
            strGuid.append(1,'{');  
            strGuid.append(lpsz);  
            strGuid.append(1,'}');  
            hr = CLSIDFromString((LPOLESTR)strGuid.c_str(),&guid);  
        }  
        assert(hr==S_OK);  
        return guid;  
    }  
       
    template <class Class>  
    struct _UuidTraits {  
    };  
       
    #define _DEFINE_UUID(Class,uuid)                                    \  
        template <>                                                     \  
    struct _UuidTraits<Class>{                                          \  
        static const GUID& Guid(){                                      \  
        static GUID guid=GUIDFromString(L## uuid);                      \  
        return guid;                                                    \  
    }                                                                   \  
    }  
       
    #define __uuidof(Class)   _UuidTraits<Class>::Guid()  
       
    #define DEFINE_CLSID(Class,guid)                                    \  
    class Class;                                                        \  
        _DEFINE_UUID(Class,guid)  
       
    #define DEFINE_IID(Interface,iid)                                   \  
    struct Interface;                                                   \  
        _DEFINE_UUID(Interface,iid)
 
  这样一来,就已经模拟出一个__uuidof关键字。我们可以很方便进行uuid的定义。举例如下:
    void test()   
    {   
        CLSID clsid=__uuidof(Class);   
        IID iid=__uuidof(Interface);   
        ...   
    }  
 
  在VC++中,为了与其他编译器以相同的方式来进行uuid的定义,我们不直接使用__declspec(uuid),而是也定义DEFINE_CLSID, DEFINE_IID宏:
    #define DEFINE_CLSID(Class,clsid)           \   
        class __declspec(uuid(clsid)) Class   
        
    #define DEFINE_IID(Interface,iid)           \   
        struct __declspec(uuid(iid)) Interface
 
  这样一来,我们已经在所有包含VC++在内的支持模板特化技术的编译器中,提供了__uuidof关键字。通过它可以进一步简化你在C++语言中实现COM组件的代价。
  附注:关于本文使用的C++模板的特化技术,详细请参阅C++文法方面的书籍,例如《C++ Primer》。其实这个技巧在C++标准库——STL中有一个专门的名字:traits(萃取),你可以在很多介绍STL的书籍中见到相关的介绍。
  转注:因为自己以后写的文章需要用到类似的技巧,因此先搬过来放这。