kasajian
5/20/2014 - 3:19 AM

Prefer Strong Type-checking of C++ Integral Types

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                                           ")