Article 27: Considerations _ uuidof and UUID on the keyword in different compilers compatibility issues more terms please go to the original Article Source: http://blog.csdn.net/liuchang5
You may still remember the "Do not discard the security mechanism provided by the compiler for us" mentioned in clause 11. We use UUID, _ uuidof, and other keywords because we advocate more secure code. It facilitates development and makes the development program more secure in terms of type.
But you may consider porting issues. We don't expect com to run on non-Windows platforms, but it doesn't mean that C ++ can only compile on the VC compiler. If there is no VC, can the smart pointer that uses the _ uuidof and UUID keywords continue to be used?
_ Com_ptr_t provides us with a compromise. We can only decide whether to use the uuidof keyword in his definition:
// Do not use the _ uuidof keyword _ com_smartptr_typedef (icalculator, iid_icalculator); // use the uuidof keyword _ partition (icalculator, _ uuidof (icalculaor ));
Ccomptr is not that polite. He directly uses the _ uuidof keyword during code implementation. This makes it a lot of trouble to use such smart pointers in non-VC compilers.
Let me introduce a technique that allows you to use the keyword _ uuidof in almost all c ++ compilers. The condition is that your c ++ compiler should support the special features of the template [11] [12 ].
First, we design a function that can convert the guid in the form of "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" to the guid type. Of course, we should also consider adding braces at both ends of the guid string. The following function can easily complete this point.
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; }
Let's write a trait class and a special version for this trait class. However, we put this special version into a macro. Let users define the special trait class through macros.
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; \ } \ }
Then a _ uuidof macro can be defined. It is used to simulate the function of the _ uuidof macro in the VC compiler. It will actually call the trait class after specialization:
#define __uuidof(Class) _UuidTraits<Class>::Guid()
Finally, we define a macro to bind the guid to the interface. In the future, we can bind the guid and class with this macro.
#define DEFINE_CLSID(Class,guid) \ class Class; \ _DEFINE_UUID(Class,guid) #define DEFINE_IID(Interface,iid) \ struct Interface; \ _DEFINE_UUID(Interface,iid)
OK ~, Everything is done. Let's test it a bit.
DEFINE_IID(Interface,"{B372C9F6-1959-4650-960D-73F20CD479BB}") DEFINE_IID(Class,"{B372C9F6-1959-4650-960D-73F20CD479AA}") void test() { CLSID clsid=__uuidof(Class); IID iid=__uuidof(Interface); ... }
Using the above techniques, we can easily create the cross-compiler _ uuidof keyword. The intelligent pointer code can be reused, And the type becomes more secure.
Hmm ~ It seems that ccomptr's designers are not sages. This kind of technology that makes the interface hard to be misused is not initially introduced into this smart pointer. However, with the widespread use of smart pointers, misoperation has also attracted the attention of smart pointer designers. ATL also takes remedial measures to solve this problem.
We should always be vigilant and keep in mind this clause "interfaces should be easy to use and not misuse ".