Prefer Strong Type-checking of C++ Integral Types
idtypes.idl is used to provide static type checking for all types, including intrinsic types such as int, float, short, double. This is basically a type-safe typedef. Let’s say you're using a LONG to represent a user ID. Ordinarily, you'd just use the LONG data type in all your APIs. This isn't type safe because someone can pass in any LONG value -- and not necessary a user ID. To create a new type for user ID, add to this your IDL:
DECLARE_ID( LONG, USERID_LONG )
Now use USERID_LONG as your type in IDL or C/C++. It's just as efficient as using a LONG but the compiler will complain unless the client passes in a USERID_LONG.
This page is an example of Catching defects with Patterns.
#pragma once
//------------------------------------------------------------------------------
// Used for providing static type checking for all types, including intrinsics
//------------------------------------------------------------------------------
// Used for providing static type checking for all types, including intrinsics
// Summary
// Say you're using a LONG to represent a user ID. Ordinarly, you'd just use
// LONG data type in all your APIs. This isn't type safe because someone
// can pass in *any* LONG value -- and not necessary a user ID.
// To create a new type for user ID, add to this your IDL:
// DECLARE_ID( LONG, USER_ID_TYPE )
// Now use USER_ID_TYPE as your type. It's just as efficient as using LONG
// but the compiler will complain unless the client passes in a USER_ID_TYPE
// instance.
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Turn off extern "C"
//------------------------------------------------------------------------------
cpp_quote(" #ifdef __cplusplus ")
cpp_quote(" } ")
cpp_quote(" #endif ")
//------------------------------------------------------------------------------
// Declare the T_DECLARE_ID template.
// Using this template, you can create an alias for simple types, such as SHORT
// LONG, etc.
// The following example creates a data type called DISPLAY_ID which can
// be used with
// typedef T_DECLARE_ID< SHORT > DISPLAY_ID;
//------------------------------------------------------------------------------
cpp_quote(" #ifdef __cplusplus ")
cpp_quote(" template<class T> ")
cpp_quote(" class T_DECLARE_ID ")
cpp_quote(" { ")
cpp_quote(" T value; ")
cpp_quote(" ")
cpp_quote(" public: ")
cpp_quote(" ")
cpp_quote(" T_DECLARE_ID() ")
cpp_quote(" : value( T() ) ")
cpp_quote(" { ")
cpp_quote(" } ")
cpp_quote(" ")
cpp_quote(" explicit T_DECLARE_ID( const T& value ) ")
cpp_quote(" : value( value ) ")
cpp_quote(" { ")
cpp_quote(" } ")
cpp_quote(" ")
cpp_quote(" T& Value() ")
cpp_quote(" { ")
cpp_quote(" return value; ")
cpp_quote(" } ")
cpp_quote(" ")
cpp_quote(" }; ")
cpp_quote(" #endif ")
//------------------------------------------------------------------------------
// DECLARE_ID is a macro wrapper for T_DECLARE_ID so that it can be used
// from within an .IDL file.
//------------------------------------------------------------------------------
// The non-C++ version is this (for .tlb)
cpp_quote("#if 0")
#define DECLARE_ID(cpptypeXX,idtypeXX) typedef cpptypeXX idtypeXX;
cpp_quote("#endif // 0")
// The C++ version is this.
cpp_quote(" #define DECLARE_ID(cpptypeXX,idtypeXX) typedef T_DECLARE_ID<cpptypeXX> idtypeXX;")
//------------------------------------------------------------------------------
// Turn extern "C" back on.
//------------------------------------------------------------------------------
cpp_quote(" #ifdef __cplusplus ")
cpp_quote(" extern \"C\"{ ")
cpp_quote(" #endif ")