这个技巧不是针对VC++缺陷的,而是针对VC++扩展语法的。这个技巧的来由,是为了某些希望有一天有可能要脱离Visual C++环境进行开发的人员。为了脱离VC++,你需要谨慎使用它的所有扩展语法。例如本文讨论的__uuidof。我们先来看看一个例子:
这 比起你以前定义uuid的方法简单多了吧?可惜,这样好用的东西,它只在VC++中提供。不过没有关系,我们这里介绍一个技巧,可以让你在几乎所有C++ 编译器中都可以这样方便的使用__uuidof。这里没有说是所有,是因为我们使用了模板特化技术,可能存在一些比较“古老”的C++编译器,不支持该特 性。
也许你已经迫不及待了。好,让我们来看看:
这样一来,就已经模拟出一个__uuidof关键字。我们可以很方便进行uuid的定义。举例如下:
在VC++中,为了与其他编译器以相同的方式来进行uuid的定义,我们不直接使用__declspec(uuid),而是也定义DEFINE_CLSID, DEFINE_IID宏:
这样一来,我们已经在所有包含VC++在内的支持模板特化技术的编译器中,提供了__uuidof关键字。通过它可以进一步简化你在C++语言中实现COM组件的代价。
- 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的定义。举例如下:
- DEFINE_CLSID(Class, "{B372C9F6-1959-4650-960D-73F20CD479BA}");
- DEFINE_IID(Interface, "{B372C9F6-1959-4650-960D-73F20CD479BB}");
- 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组件的代价。