Click here to Skip to main content
15,891,184 members
Articles / Programming Languages / C++

Type-safe Callbacks in C++

Rate me:
Please Sign up or sign in to vote.
4.71/5 (47 votes)
13 Feb 2008CPOL8 min read 203.6K   4.9K   130  
Demonstrates how to use type-safe callbacks in C++
// preprocessor.h

// This file is an extract from some files (like ct_if.hpp) of the huge Boost library (35 Megabyte)
// modified, shortened and compacted to one file by ElmueSoft (www.elmue.de.vu  or  kickme.to/elmue)



// -------------------------------------------------------------------
// Boost.Function library

// Copyright (C) 2001-2003 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.

// For more information, see http://www.boost.org
// -------------------------------------------------------------------


#if !defined(PREPROCESSOR_H)
#define PREPROCESSOR_H


// turn off MS Visual Studio warning: "Identifier was truncated to '255' characters in the debug information"
#pragma warning( disable : 4786 )


// Note:
// Older versions of compilers do not support partial template specialization
// In this case a workaround is necessary

#if   _MSC_VER == 1200 // Visual Studio 6.0
  #define PARTIAL_TEMPLATE_SPECIALIZATION_AVAILABLE   0

#elif _MSC_VER == 1300 // Visual Studio 7.0 (.NET)
  #define PARTIAL_TEMPLATE_SPECIALIZATION_AVAILABLE   0

#elif _MSC_VER == 1310 // Visual Studio 7.1 (.NET 2003)
  #define PARTIAL_TEMPLATE_SPECIALIZATION_AVAILABLE   1

#else // Unknown Compiler (please set the value manually to 0 or 1)
  #error Unknown compiler : insert 0 or 1 in the next line and comment out this line !
  #define PARTIAL_TEMPLATE_SPECIALIZATION_AVAILABLE   ?
#endif


// *********** <PREPROCESSOR MACROS> ***************


// UNUSABLE is used as a dummy replacement for functions returning void
// Needed for compilers not supporting partial template specialization
// (like MS Visual Studio 6)

#define UNUSABLE \
cPreProcessor::unusable*


// IS_VOID returns true if class T == void, otherwise false

#define IS_VOID(T) \
cPreProcessor::is_void<T>::value


// IS_USABLE returns 0 if class T == cPreProcessor::unusable*, otherwise 1

#define IS_USABLE(T) \
cPreProcessor::is_usable<T>::value


// CLASS_SWITCH returns class A if condition == true, class B if condition == false

#define CLASS_SWITCH(condition, A, B) \
cPreProcessor::select_switch<condition, A, B>::value



// *********** <PREPROCESSOR SWITCHES> ***************

struct cPreProcessor
{
    // ################  unusable  #################

    struct unusable
    {
        // empty structure
    };

    // ################  is_void  #################

    template <typename T>
    struct is_void
    { enum { value = false }; };

    // Specialization of is_void for T == void
    template <>
    struct is_void<void>
    { enum { value = true }; };

    // ################  is_usable  #################

    template <typename T>
    struct is_usable
    { enum { value = 1 }; };

    // Specialization of is_usable for T == unusable*
    template <>
    struct is_usable<unusable*>
    { enum { value = 0 }; };

    // ################  select_switch  #################

#if PARTIAL_TEMPLATE_SPECIALIZATION_AVAILABLE

    // for newer compilers (e.g. Visual Studio 7.1 = Visual Studio .NET 2003)

    template<int condition, class A, class B>
    // partial specialization for condition == illegal value
    struct select_switch
    {
        typedef typename UNUSABLE value;
    };

    // partial specialization for condition == true
    template<class A, class B>
    struct select_switch<true, A, B>
    {
        typedef typename A value;
    };

    // partial specialization for condition == false
    template<class A, class B>
    struct select_switch<false, A, B>
    {
        typedef typename B value;
    };

#else //  !PARTIAL_TEMPLATE_SPECIALIZATION_AVAILABLE

    // for older compilers: (e.g. Visual Studio 6.0 and 7.0)
    // the following has to be that awkward because lots of old compilers
    // do not support partial template specialization

    struct switch_true
    {
        template<class A, class B>
        struct class_switch
        { typedef  A  ret_class; };
    };

    struct switch_false
    {
        template<class A, class B>
        struct class_switch
        { typedef  B  ret_class; };
    };

    template<int condition>
    struct condition_switch
    { typedef  switch_true  selector; };

    // Specialization of condition_switch for condition == false
    template <>
    struct condition_switch<false>
    { typedef  switch_false  selector; };


    template<int condition, class A, class B>
    struct select_switch
    {
        typedef  condition_switch<condition>::selector    Selector;
        typedef  Selector::class_switch<A, B>::ret_class  value;
    };

#endif // PARTIAL_TEMPLATE_SPECIALIZATION_AVAILABLE

};

#endif // PREPROCESSOR_H

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) ElmüSoft
Chile Chile
Software Engineer since 40 years.

Comments and Discussions