std::regx

2017. 8. 25. 09:09 from 셈말짓기/C and C++

#include "stdafx.h"

 

#include <regex>

#include <sstream>

#include <vector>

#include <iostream>

#include <vector>

 

void t4()

{

         //-----------------------------------------------------------------------

         std::string expression;

 

 

         //  ECMAScript : Special Keyword ^ $ \ . * + ? ( ) [ ] { } |

         expression = "\\\"([^\\\"]*)\\\"=([NR])";

         //       expression = R"STRING_LITERAL_DELIMITER(\"([^\"]*)\"=([NR]))STRING_LITERAL_DELIMITER";

         expression = R"d(\"([^\"]*)\"=([NR]))d";

         //       expression = R"d(\"([^\"]*)\")d";

 

 

         //-----------------------------------------------------------------------

         std::string text;

         std::string element;

 

         text = "  \"1A(:B/C)\":N, \"2AB,C\":R\"3A(:B/C)\":R, \"aa\"  ";

         text = "  \"21\"=N, \"22\"=R, \"23\"=R, \"24\"=x";

 

 

 

         //-----------------------------------------------------------------------

         std::vector<int> ei; // element index

 

 

         ei.push_back(1);

         ei.push_back(2);

         ei.push_back(3);

 

 

         //-----------------------------------------------------------------------

         std::regex                       r(expression);

         const std::sregex_token_iterator end;

         std::sregex_token_iterator       i(text.begin(), text.end(), r, ei);

 

 

         std::cout << expression << std::endl;

         std::cout << text << std::endl;

         while (i != end)

         {

                  element = *i++;

 

                  std::cout << element << std::endl;

         }

}

 

void t5()

{

         //-----------------------------------------------------------------------

         std::string expression;

 

 

         expression = R"d(\"([^\"]*)\"=([NR]))d";

 

 

         //-----------------------------------------------------------------------

         std::string text;

         std::string element;

 

 

         text = "  \"21\"=N, \"22\"=R, \"23\"=R, \"24\"=x";

 

 

         //-----------------------------------------------------------------------

         std::regex      r(expression);

         std::smatch     m;

         std::ssub_match sm;

 

         std::string value;

 

         std::size_t i;

         std::size_t count;

 

 

         value = text;

 

         while (std::regex_search(value, m, r))

         {

                  count = m.size();

 

                  for (i = 0u; i < count; i++)

                  {

                           sm = m[i];

 

                           if (sm.matched)

                           {

                                   element = sm.str();

 

                                   std::cout << i << " = " << element << std::endl;

                           }

                  }

 

                  value = m.suffix();

         }

}

 

int _tmain(int argc, _TCHAR* argv[])

{

         t5();

 

 

         return 0;

}

 

Posted by 셈말짓기 :


/////////////////////////////////////////////////////////////////////////////

//

// File: FSMSample.cpp

//

// Created by MOON, Eui-kwon.

// Created on Aug-10th, 2011.

//

// 교육용으로작성한FSM Sample.

// 예전에FSM 공부할때cdplayer라는샘플코드를본것같은데코드는없고

// 웹에상태천이표만있어서그기준으로코드를작성함.

//

// machine, state, event 각각의인터페이스는비지터패턴형식으로구성함.

//

/////////////////////////////////////////////////////////////////////////////

//===========================================================================

 

 

 

#include "stdafx.h"

#include <assert.h>

 

/////////////////////////////////////////////////////////////////////////////

//

// Finite state machine

//

/////////////////////////////////////////////////////////////////////////////

//===========================================================================

namespace fsm

{

 

 

 

/////////////////////////////////////////////////////////////////////////////

//===========================================================================

class event;

class state;

class machine;

 

 

 

/////////////////////////////////////////////////////////////////////////////

//

// Interface

//

/////////////////////////////////////////////////////////////////////////////

//===========================================================================

class machine

{

private:

        state* _state;

       

public:

        machine();

        virtual ~machine();

 

public:

        virtual void   transition (state*);

        virtual void   notify     (event*);

        virtual state* get_state  (void  ) const;

};

 

/////////////////////////////////////////////////////////////////////////////

//===========================================================================

class event

{

public:

        event();

        virtual ~event();

 

public:

        virtual void notify (machine*, state*);

};

 

/////////////////////////////////////////////////////////////////////////////

//===========================================================================

class state

{

public:

        state();

        virtual ~state();

       

public:

        virtual void on_entry   (machine*, state*);

        virtual void on_exit    (machine*, state*);

        virtual void on_event   (machine*, event*);

 

public:

        virtual void transition (machine*, state*);

};

 

 

 

 

/////////////////////////////////////////////////////////////////////////////

//

// Implementation

//

/////////////////////////////////////////////////////////////////////////////

//===========================================================================

event:: event(){}

event::~event(){}

 

void event::notify (machine* m, state*s)

{

        if (s)

        {

               s->on_event (m, this);

        }

}

 

//===========================================================================

state:: state(){}

state::~state(){}

 

void state::on_entry (machine*, state*) {}

void state::on_exit  (machine*, state*) {}

void state::on_event (machine*, event*) {}

 

void state::transition (machine* m, state* s)

{

        if (m)

        {

               m->transition (s);

        }

}

 

//===========================================================================

machine::machine():

        _state (0)

{

}

 

machine::~machine()

{

}

 

state* machine::get_state (void) const

{

        return _state;

}

 

void machine::transition (state* current)

{      

        state* previous;

 

        previous = _state;

        if (previous)

        {

               previous->on_exit (this, current );

        }

 

        _state = current;

        if (current)

        {

               current ->on_entry (this, previous);

        }

}

 

void machine::notify (event* e)

{

        if (e)

        {

               e->notify (this, _state);

        }

}

 

}; // end of "namespace fsm"

 

 

 

/////////////////////////////////////////////////////////////////////////////

//

// Sample

//

/////////////////////////////////////////////////////////////////////////////

//===========================================================================

#define fsm_trace  printf

#define fsm_assert assert

 

//===========================================================================

enum cdplayer_event_code_t

{

        ec_play        = 0,

        ec_open_close  = 1,

        ec_cd_detected = 2,

        ec_stop        = 3,

        ec_pause       = 4

};

 

//===========================================================================

class cdplayer_event : public fsm::event

{

public:

        const cdplayer_event_code_t _code;

 

        explicit cdplayer_event (cdplayer_event_code_t code) : _code(code)

        {

        }

 

        void notify (fsm::machine* m, fsm::state*s)

        {

               switch (_code)

               {

               case ec_play       : fsm_trace("\t\tnotify: play        \r\n"); break;

               case ec_open_close : fsm_trace("\t\tnotify: open_close  \r\n"); break;

               case ec_cd_detected: fsm_trace("\t\tnotify: cd_detected \r\n"); break;

               case ec_stop       : fsm_trace("\t\tnotify: stop        \r\n"); break;

               case ec_pause      : fsm_trace("\t\tnotify: pause       \r\n"); break;

               }

 

               fsm::event::notify (m, s);

        }

};

 

//===========================================================================

class cdplayer_state : public fsm::state

{

public:

        virtual const char* get_name (void) = 0;

 

        virtual void on_event (fsm::machine* m, fsm::event* e)

        {

               /*

               cdplayer*       cm = static_cast<cdplayer*      > ( m );

               cdplayer_event* ce = static_cast<cdplayer_event*> ( e );

 

               switch (ce->_code)

               {

               case ec_play       : break;

               case ec_open_close : break;

               case ec_cd_detected: break;

               case ec_stop       : break;

               case ec_pause      : break;

               }

               */

        }

 

        virtual void on_entry (fsm::machine*, fsm::state*)

        {

               fsm_trace("\ton_entry: %s \r\n", get_name());

        }

 

        virtual void on_exit (fsm::machine*, fsm::state*)

        {

               fsm_trace("\ton_exit : %s \r\n", get_name());

        }

};

#define DECLARE_NAME(n) virtual const char* get_name (void) { return (n); }

 

//===========================================================================

class stopped: public cdplayer_state

{

public:

        DECLARE_NAME ("stopped" )

        virtual void on_event (fsm::machine* m, fsm::event* e);

};

 

//===========================================================================

class open: public cdplayer_state

{

public:

        DECLARE_NAME ("open" )

        virtual void on_event (fsm::machine* m, fsm::event* e);

};

 

//===========================================================================

class empty: public cdplayer_state

{

public:

        DECLARE_NAME ("empty" )

        virtual void on_event (fsm::machine* m, fsm::event* e);

};

 

//===========================================================================

class playing: public cdplayer_state

{

public:

        DECLARE_NAME ("playing" )

        virtual void on_event (fsm::machine* m, fsm::event* e);

};

 

//===========================================================================

class paused: public cdplayer_state

{

public:

        DECLARE_NAME ("paused" )

        virtual void on_event (fsm::machine* m, fsm::event* e);

};

 

//===========================================================================

class cdplayer: public fsm::machine

{

private:

        stopped _stopped;

        open    _open   ;

        empty   _empty  ;

        playing _playing;

        paused  _paused ;

 

public:

        enum state_id_t

        {

               sid_stopped,

               sid_open   ,

               sid_empty  ,

               sid_playing,

               sid_paused ,

        };

 

public:

        virtual void transition (fsm::state* n)

        {

               cdplayer_state* previous = static_cast<cdplayer_state*> ( get_state() );

               cdplayer_state* current  = static_cast<cdplayer_state*> ( n );

 

               fsm_trace ("transition:");

               if (previous) fsm_trace (" %s -> ", previous->get_name());

               if (current ) fsm_trace (" %s ", current ->get_name());

               fsm_trace ("\r\n");

 

               fsm::machine::transition(n);

        }

 

        cdplayer_state* get_state_instance (state_id_t id)

        {

               switch (id)

               {

               case sid_stopped : return &_stopped ;

               case sid_open    : return &_open    ;

               case sid_empty   : return &_empty   ;

               case sid_playing : return &_playing ;

               case sid_paused  : return &_paused  ;

               }

 

               fsm_assert (0);

 

               return 0;

        }

 

public:

        void start_playback         (void){ printf("\t\t\taction: start_playback         \r\n"); }

        void open_drawer            (void){ printf("\t\t\taction: open_drawer            \r\n"); }

        void close_drawer           (void){ printf("\t\t\taction: close_drawer           \r\n"); }

        void collect_cd_information (void){ printf("\t\t\taction: collect_cd_information \r\n"); }

        void store_cd_information   (void){ printf("\t\t\taction: store_cd_information   \r\n"); }

        void stop_playback          (void){ printf("\t\t\taction: stop_playback          \r\n"); }

        void pause_playback         (void){ printf("\t\t\taction: pause_playback         \r\n"); }

        void resume_playback        (void){ printf("\t\t\taction: resume_playback        \r\n"); }

};

 

/*********************************************************************************

 CD PLAYER STATE TRANSITION TABLE

---------------+-------------+------------+--------------------------------------

 CURRENT STATE | EVENT       | NEXT STATE | TRANSITION ACTION

---------------+-------------+------------+--------------------------------------

 stopped       | play        | playing    | start playback

 stopped       | open/close  | open       | open drawer

 open          | open/close  | empty      | close drawer; collect cd information

 empty         | open/close  | open       | open drawer

 empty         | cd-detected | stopped    | store cd information

 playing       | stop        | stopped    | stop playback

 playing       | pause       | paused     | pause playback

 playing       | open/close  | open       | stop playback; open drawer

 paused        | play        | playing    | resume playback

 paused        | stop        | stopped    | stop playback

 paused        | open/close  | open       | stop playback; open drawer

---------------+-------------+------------+--------------------------------------

*********************************************************************************/

 

//===========================================================================

void stopped::on_event (fsm::machine* m, fsm::event* e)

{

        cdplayer*       cm = static_cast<cdplayer*      > ( m );

        cdplayer_event* ce = static_cast<cdplayer_event*> ( e );

 

        switch (ce->_code)

        {

        case ec_play :

               cm->start_playback();

               transition(cm, cm->get_state_instance (cdplayer::sid_playing));

               break;

 

        case ec_open_close :

               cm->open_drawer ();

               transition(cm, cm->get_state_instance (cdplayer::sid_open));

               break;

        }

}

 

//===========================================================================

void open::on_event (fsm::machine* m, fsm::event* e)

{

        cdplayer*       cm = static_cast<cdplayer*      > ( m );

        cdplayer_event* ce = static_cast<cdplayer_event*> ( e );

 

        switch (ce->_code)

        {

        case ec_open_close :

               cm->close_drawer();

               cm->collect_cd_information();

               transition(cm, cm->get_state_instance (cdplayer::sid_empty));

               break;

        }

}

 

//===========================================================================

void empty::on_event (fsm::machine* m, fsm::event* e)

{

        cdplayer*       cm = static_cast<cdplayer*      > ( m );

        cdplayer_event* ce = static_cast<cdplayer_event*> ( e );

 

        switch (ce->_code)

        {

        case ec_open_close :

               cm->open_drawer();

               transition(cm, cm->get_state_instance (cdplayer::sid_open));

               break;

 

        case ec_cd_detected:

               cm->store_cd_information();

               transition(cm, cm->get_state_instance (cdplayer::sid_stopped));

               break;

        }

}

 

//===========================================================================

void playing::on_event (fsm::machine* m, fsm::event* e)

{

        cdplayer*       cm = static_cast<cdplayer*      > ( m );

        cdplayer_event* ce = static_cast<cdplayer_event*> ( e );

 

        switch (ce->_code)

        {

        case ec_stop :

               cm->stop_playback();

               transition(cm, cm->get_state_instance (cdplayer::sid_stopped));

               break;

 

        case ec_pause :

               cm->pause_playback();

               transition(cm, cm->get_state_instance (cdplayer::sid_paused));

               break;

 

        case ec_open_close :

               cm->stop_playback();

               cm->open_drawer();

               transition(cm, cm->get_state_instance (cdplayer::sid_open));

               break;

        }

}

//===========================================================================

void paused::on_event (fsm::machine* m, fsm::event* e)

{

        cdplayer*       cm = static_cast<cdplayer*      > ( m );

        cdplayer_event* ce = static_cast<cdplayer_event*> ( e );

 

        switch (ce->_code)

        {

        case ec_play :

               cm->resume_playback();

               transition(cm, cm->get_state_instance (cdplayer::sid_playing));

               break;

 

        case ec_stop :

               cm->stop_playback();

               transition(cm, cm->get_state_instance (cdplayer::sid_stopped));

               break;

 

        case ec_open_close :

               cm->stop_playback();

               cm->open_drawer();

               transition(cm, cm->get_state_instance (cdplayer::sid_open));

               break;

        }

}

//===========================================================================

int _tmain(int argc, _TCHAR* argv[])

{

        cdplayer       player;

        cdplayer_event play        (ec_play       );

        cdplayer_event open_close  (ec_open_close );

        cdplayer_event cd_detected (ec_cd_detected);

        cdplayer_event stop        (ec_stop       );

        cdplayer_event pause       (ec_pause      );

 

        player.transition ( player.get_state_instance(cdplayer::sid_empty) );

 

        player.notify ( &cd_detected );

        player.notify ( &play        );

        player.notify ( &pause       );

        player.notify ( &stop        );

        player.notify ( &open_close  );

        player.notify ( &stop        );

        player.notify ( &play        );

        player.notify ( &open_close  );

 

        player.notify ( &open_close  );

        player.notify ( &cd_detected );

        player.notify ( &play        );

 

        return 0;

}

 

/////////////////////////////////////////////////////////////////////////////

//

// result

//

/////////////////////////////////////////////////////////////////////////////

//===========================================================================

/*

transition: empty

        on_entry: empty

                notify: cd_detected

                        action: store_cd_information

transition: empty ->  stopped

        on_exit : empty

        on_entry: stopped

                notify: play

                        action: start_playback

transition: stopped ->  playing

        on_exit : stopped

        on_entry: playing

                notify: pause

                        action: pause_playback

transition: playing ->  paused

        on_exit : playing

        on_entry: paused

                notify: stop

                        action: stop_playback

transition: paused ->  stopped

        on_exit : paused

        on_entry: stopped

                notify: open_close

                        action: open_drawer

transition: stopped ->  open

        on_exit : stopped

        on_entry: open

                notify: stop

                notify: play

                notify: open_close

                        action: close_drawer

                        action: collect_cd_information

transition: open ->  empty

        on_exit : open

        on_entry: empty

                notify: open_close

                        action: open_drawer

transition: empty ->  open

        on_exit : empty

        on_entry: open

                notify: cd_detected

                notify: play

계속하려면아무키나누르십시오. . .

*/

 

 

Posted by 셈말짓기 :

static_cast
It is able to do the reverse of what an implicit conversion can do. Meaning: narrow (long -> int), widen (int -> long), base-to-derived, void*-to-T* for example. You can't use it for the stuff that an reversed implicit conversion cannot do. (I.e you cannot cast an int* into int).


dynamic_cast
It is used to cast a base pointer into a derived pointer. If the base pointer doesn't point to an object of the type of the derived, it returns 0.
It is used to cast a base reference into a derived reference. If the reference isn't pointing to an object of the derived, it throws std::bad_cast.
It can be considered the checked cast equivalent to static_cast, in that it checks whether the object pointed to really is of the derived type.


reinterpret_cast

It is used to cast a pointer type to a wide enough integral type and back to the original pointer type.
It is used to cast between pointer types of incompatible types (int* to double* for example). The result of that mapping is unspecified, but it's possible to do so.


const_cast

It is used to cast away const or volatile. It is used in the rare cases when you have a originally non-const object, which is pointed to by a pointer-to-const or referenced to by a reference-to-const. Casting away constness is considered evil and should not be done if it can be avoided.

Posted by 셈말짓기 :
코드프로젝트에 있는 코드 고쳐서 좀 만들어 봤습니다.
전 임베디드를 해서 해당 타겟이 int64를 지원안해서 고쳐보았습니다.
원본 소스는 http://www.codeproject.com/KB/IP/csntp.aspx 이지만 모양새는 많이 다릅니다. -_-;


// sntp.cpp : 콘솔응용프로그램에대한진입점을정의합니다.

//

 

#include "stdafx.h"

 

#include <time.h>

 

 

#include <winsock2.h>

#pragma comment(lib, "ws2_32.lib")

 

namespace sntp

{

 

/////////////////////////////////////////////////////////////////////////////

//===========================================================================

#if defined ( WIN32 )

#        define __little_endian__ 1

#endif

#if defined ( VXWORKS )

#        define __big_endian__    1

#endif

 

#define __sntp_debug_print__ 1

 

//===========================================================================

typedef unsigned int       uint32_t;

typedef unsigned short int uint16_t;

typedef unsigned char      uint8_t;

 

typedef signed int         int32_t;

typedef signed short int   int16_t;

typedef signed char        int8_t;

 

//===========================================================================

typedef struct _system_time_t

{

    uint16_t year         ;

    uint16_t month        ;

    uint16_t day_of_week  ;

    uint16_t day          ;

    uint16_t hour         ;

    uint16_t minute       ;

    uint16_t second       ;

    uint16_t milliseconds ;

} system_time_t;

 

typedef struct _timestamp_t

{

    uint32_t seconds          ;

    uint32_t seconds_fraction ;

} timestamp_t;

 

typedef struct _ntp_server_response_t

{

         int leap_indicator;

         // 0: no warning

         // 1: last minute in day has 61 seconds

         // 2: last minute has 59 seconds

         // 3: clock not synchronized

 

         int stratum;

         //      0: unspecified or unavailable

         //      1: primary reference (e.g., radio clock)

         //   2-15: secondary reference (via NTP or SNTP)

         // 16-255: reserved

 

         timestamp_t originate_timestamp  ; // T1: Time when the request was sent from the client to the SNTP server

         timestamp_t receive_timestamp    ; // T2: Time when the request was received by the server

         timestamp_t transmit_timestamp   ; // T3: Time when the server sent the request back to the client

         timestamp_t destination_timestamp; // T4: Time when the reply was received by the client

         double      round_trip_delay     ; // Round trip time in seconds

         double      local_clock_offset   ; // Local clock offset relative to the server

} ntp_server_response_t;

 

// Ref. RFC 2030 - Simple Network Time Protocol (SNTP) Version 4 for IPv

// http://www.faqs.org/rfcs/rfc2030.html

typedef struct _ntp_packet_t

{

#if defined ( __little_endian__ )

    uint8_t     mode                : 3 ;

    uint8_t     vn                  : 3 ;

    uint8_t     li                  : 2 ;

#else                                                                    

    uint8_t     li                  : 2 ;

    uint8_t     vn                  : 3 ;

    uint8_t     mode                : 3 ;

#endif                                                                   

    uint8_t     stratum                 ;

    uint8_t     poll                    ;

    uint8_t     precision               ;

    uint32_t    root_delay              ;

    uint32_t    root_dispersion         ;

    uint32_t    reference_identifier    ;

    timestamp_t reference_timestamp     ;

    timestamp_t originate_timestamp     ;

    timestamp_t receive_timestamp       ;

    timestamp_t transmit_timestamp      ;

} ntp_packet_t;

 

typedef unsigned int socket_handle_t;

 

 

 

/////////////////////////////////////////////////////////////////////////////

//===========================================================================

#include "sntp.inl"

static const uint16_t _socket_timeout      =    1000;

static const uint16_t _socket_default_port =     123;

static const int32_t  _julian_1900_01_01   = 2415021;

 

 

 

/////////////////////////////////////////////////////////////////////////////

//===========================================================================

inline socket_handle_t socket_create (int af, int type, int protocol)

{

         return (socket_handle_t)socket (af, type, protocol);

}

 

inline int socket_close (socket_handle_t s)

{

         return closesocket (s);

}

 

inline int socket_connect (socket_handle_t s, const struct sockaddr* name, int namelen)

{

         return connect (s, name, namelen);

}

 

inline int socket_recv (socket_handle_t s, char* buf, int len, int flags)

{

         return recv (s, buf, len, flags);

}

 

inline int socket_send (socket_handle_t s, const char* buf, int len, int flags)

{

         return send (s, buf, len, flags);

}

 

bool socket_make_address (

         struct sockaddr_in* sa,

         const char*         address,

         uint16_t            port   ,

         uint16_t            family = AF_INET)

{

         memset (sa, 0, sizeof(struct sockaddr_in));

 

         sa->sin_family      = family;

         sa->sin_addr.s_addr = inet_addr(address);

 

         if (sa->sin_addr.s_addr==INADDR_NONE)

         {

                  struct hostent* host;

 

                  host = gethostbyname(address);

                  if (host != 0)

                  {

                           sa->sin_addr.s_addr = ((struct in_addr*)host->h_addr)->s_addr;

                  }

                  else

                  {

                           return false;

                  }

         }

 

         sa->sin_port = htons((uint16_t)port);

 

         return true;

}

 

//===========================================================================

void convert_gregorian_to_julian (uint16_t year, uint16_t month, uint16_t day, int32_t& julian)

{

         int32_t y ;

         int32_t m ;

         int32_t d ;

         int32_t c ;

         int32_t ya;

        

         y = (int32_t) year ;

         m = (int32_t) month;

         d = (int32_t) day  ;

        

         if (m > 2)

         {

                  m = m - 3;

         }

         else

         {

                  m = m + 9;

                  y = y - 1;

         }

        

         c  = y / 100;

         ya = y - 100 * c;

        

         julian = (146097L * c) / 4 + (1461L * ya) / 4 + (153L * m + 2) / 5 + d + 1721119L;

}

 

void convert_julian_to_gregorian (int32_t julian, uint16_t& year, uint16_t& month, uint16_t& day)

{

         int32_t j;

         int32_t y;

         int32_t d;

         int32_t m;

        

         j = julian - 1721119;

         y = (4 * j - 1) / 146097;

         j = 4 * j - 1 - 146097 * y;

         d = j / 4;

         j = (4 * d + 3) / 1461;

         d = 4 * d + 3 - 1461 * j;

         d = (d + 4) / 4;

         m = (5 * d - 3) / 153;

         d = 5 * d - 3 - 153 * m;

         d = (d + 5) / 5;

         y = 100 * y + j;

 

         if (m < 10)

         {

                  m = m + 3;

         }

         else

         {

                  m = m - 9;

                  y = y + 1;

         }

 

         year  = (uint16_t) y;

         month = (uint16_t) m;

         day   = (uint16_t) d;

}

 

uint32_t convert_milliseconds_to_seconds_fraction (uint16_t milliseconds)

{

#if 1

         // 4294967296 == 0x1 0000 0000 (2^32)

         return (uint32_t) (4294967296.0 * milliseconds / 1000);

#else   

         return ( milliseconds<1000 )? _seconds_fraction_table[milliseconds] : _seconds_fraction_table[999];

#endif  

}

 

uint16_t convert_seconds_fraction_to_milliseconds (uint32_t seconds_fraction)

{

#if 1

         static const double ratio        = (((double)1000.0)/4294967296.0);

         double              milliseconds = ((double)seconds_fraction) * ratio;

#else

         static const double ratio        = (((double)1000.0)/0xFFFFFFFF);

         double              milliseconds = ((double)seconds_fraction) * ratio + 0.5;

#endif  

         return (uint16_t)(milliseconds);

}

 

void make_timestamp (

         timestamp_t& timestamp        ,

         uint16_t     year             ,

         uint16_t     month        = 1 ,

         uint16_t     day          = 1 ,

         uint16_t     hour         = 0 ,

         uint16_t     minute       = 0 ,

         uint16_t     second       = 0 ,

         uint16_t     milliseconds = 0 )

{

         int32_t julian;

        

         convert_gregorian_to_julian (year,month,day, julian);

         julian = julian - _julian_1900_01_01;

        

         timestamp.seconds          = (julian*24*60*60) + (hour*60*60) + (minute*60) + second;

         timestamp.seconds_fraction = convert_milliseconds_to_seconds_fraction (milliseconds);

}

 

//===========================================================================

void get_current_timestamp (timestamp_t& timestamp)

{

#if 0

         static const uint32_t from_1900_to_1970 = 86400U * (365U*70U + 17U);

        

         uint32_t t;

        

         t = (uint32_t)time (0); // time(): 1970-01-01 based

         t+= from_1900_to_1970;

        

         timestamp.seconds          = t;

         timestamp.seconds_fraction = 0;

#else

         SYSTEMTIME st;

        

         GetSystemTime (&st);

         make_timestamp (timestamp,

                  st.wYear        ,

                  st.wMonth       ,

                  //st.wDayOfWeek   ,

                  st.wDay         ,

                  st.wHour        ,

                  st.wMinute      ,

                  st.wSecond      ,

                  st.wMilliseconds);

#endif           

}

 

//===========================================================================

void convert_timestamp_to_system_time (const timestamp_t& timestamp, system_time_t& system_time)

{

         uint32_t julian;

        

         system_time.hour         = (timestamp.seconds/3600)%24;

         system_time.minute       = (timestamp.seconds/60  )%60;

         system_time.second       = (timestamp.seconds     )%60;

        

         system_time.milliseconds = convert_seconds_fraction_to_milliseconds (timestamp.seconds_fraction);

 

         julian = timestamp.seconds/86400 + _julian_1900_01_01;

        

         convert_julian_to_gregorian (julian, system_time.year, system_time.month, system_time.day);

         system_time.day_of_week = ((julian+1) % 7);

}

 

void print_timestamp (const timestamp_t& timestamp)

{

         system_time_t system_time;

         const char*   day_of_week_string[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };

        

         convert_timestamp_to_system_time (timestamp, system_time);

        

         printf ("%4d-%02d-%02d(%s) %02d:%02d:%02d.%03d \r\n",

                  system_time.year        ,

                  system_time.month       ,

                  system_time.day         ,

                  day_of_week_string[system_time.day_of_week],

                 

                  system_time.hour        ,

                  system_time.minute      ,

                  system_time.second      ,

                  system_time.milliseconds);

}

 

//===========================================================================

bool client_request (

         ntp_server_response_t& response        ,

         struct sockaddr_in*    server_address  ,

         uint32_t               milisec_timeout = _socket_timeout)

{

    socket_handle_t socket_handle;

    struct timeval  timeout;

    fd_set          fds;

    int             result;

   

    socket_handle = socket_create (AF_INET, SOCK_DGRAM, 0);

    if (socket_handle < 0)

    {

        return false;

    }

   

    result = socket_connect (socket_handle, (struct sockaddr*) server_address, sizeof(struct sockaddr_in));

    if (result < 0)

    {

        socket_close(socket_handle);

        return false;

    }

   

 

         // ntp packet

    ntp_packet_t ntp_packet;

    timestamp_t  timestamp ;

 

    memset(&ntp_packet, 0, sizeof(ntp_packet));

    ntp_packet.vn   = 4;

    ntp_packet.mode = 3;

    ntp_packet.li   = 0;

   

    get_current_timestamp (timestamp);

    ntp_packet.transmit_timestamp.seconds           = htonl(timestamp.seconds         );

    ntp_packet.transmit_timestamp.seconds_fraction  = htonl(timestamp.seconds_fraction);

 

         // T1

    response.originate_timestamp.seconds          = timestamp.seconds         ;

    response.originate_timestamp.seconds_fraction = timestamp.seconds_fraction;

 

        

    result = socket_send (socket_handle, (char*)&ntp_packet, sizeof(ntp_packet), 0);

    if ( result != sizeof(ntp_packet) )

    {

        socket_close (socket_handle);

        return false;

    }

        

    FD_ZERO (&fds);

    FD_SET  (socket_handle, &fds);

    timeout.tv_sec  =  milisec_timeout / 1000;

    timeout.tv_usec = (milisec_timeout % 1000) * 1000;

    result = select (socket_handle+1, &fds, NULL, NULL, &timeout);

   

    if ( result == 0 || result == -1 )

    {

        socket_close(socket_handle);

        return false;

    }

   

 

         // T4

         get_current_timestamp (timestamp);

    response.destination_timestamp.seconds          = timestamp.seconds         ;

    response.destination_timestamp.seconds_fraction = timestamp.seconds_fraction;

 

   

    result = socket_recv (socket_handle, (char*)&ntp_packet, sizeof(ntp_packet), 0);

    if ( result != sizeof(ntp_packet) )

    {

        socket_close(socket_handle);

        return false;

    }

 

    socket_close (socket_handle);

 

   

         // T2/3

    response.receive_timestamp.seconds           = ntohl(ntp_packet.receive_timestamp.seconds          );

    response.receive_timestamp.seconds_fraction  = ntohl(ntp_packet.receive_timestamp.seconds_fraction );

    response.transmit_timestamp.seconds          = ntohl(ntp_packet.transmit_timestamp.seconds         );

    response.transmit_timestamp.seconds_fraction = ntohl(ntp_packet.transmit_timestamp.seconds_fraction);

        

         //-----------------------------------------------------------------------

         // Timestamp Name          ID   When Generated

         //-----------------------------------------------------------------------

         // Originate Timestamp     T1   time request sent by client

         // Receive Timestamp       T2   time request received by server

         // Transmit Timestamp      T3   time reply sent by server

         // Destination Timestamp   T4   time reply received by client

        

         /*

         The roundtrip delay(d)

    d = (T4 - T1) - (T2 - T3)    

        

         local clock offset t are defined as

         t = ((T2 - T1) + (T3 - T4)) / 2.

         */     

 

         static const uint32_t NTP_DIFF  = 2208988800U;      // 1970-01-01

         static const double   NTP_SCALE = 2.3283064365e-10; // 2^-32

 

         double t1,t2,t3,t4;

 

         t1=response.originate_timestamp  .seconds-NTP_DIFF + response.originate_timestamp  .seconds_fraction * NTP_SCALE;

         t2=response.receive_timestamp    .seconds-NTP_DIFF + response.receive_timestamp    .seconds_fraction * NTP_SCALE;

         t3=response.transmit_timestamp   .seconds-NTP_DIFF + response.transmit_timestamp   .seconds_fraction * NTP_SCALE;

         t4=response.destination_timestamp.seconds-NTP_DIFF + response.destination_timestamp.seconds_fraction * NTP_SCALE;

        

         response.round_trip_delay   =  (t4 - t1) - (t2 - t3);

         response.local_clock_offset = ((t2 - t1) + (t3 - t4)) * 0.5;

 

         //-----------------------------------------------------------------------

 

         response.stratum        = ntp_packet.stratum;

         response.leap_indicator = ntp_packet.li;

 

#if __sntp_debug_print__

         printf ("# sntp_debug \r\n");

    printf ("  li                  = %d     \r\n", ntp_packet.li                   );

    printf ("  vn                  = %d     \r\n", ntp_packet.vn                   );

    printf ("  mode                = %d     \r\n", ntp_packet.mode                 );

    printf ("  stratum             = 0x%02x \r\n", ntp_packet.stratum              );

    printf ("  poll                = 0x%02x \r\n", ntp_packet.poll                 );

    printf ("  precision           = 0x%02x \r\n", ntp_packet.precision            );

    printf ("  root_delay          = 0x%08x \r\n", ntp_packet.root_delay           );

    printf ("  root_dispersion     = 0x%08x \r\n", ntp_packet.root_dispersion      );

    printf ("  reference_identifier= 0x%08x \r\n", ntp_packet.reference_identifier );

 

         printf ("  reference_timestamp = ");

    timestamp.seconds         =ntohl(ntp_packet.reference_timestamp.seconds         );

    timestamp.seconds_fraction=ntohl(ntp_packet.reference_timestamp.seconds_fraction);

    print_timestamp (timestamp);

 

         printf ("  originate_timestamp = ");

    timestamp.seconds         =ntohl(ntp_packet.originate_timestamp.seconds         );

    timestamp.seconds_fraction=ntohl(ntp_packet.originate_timestamp.seconds_fraction);

    print_timestamp (timestamp);

 

         printf ("  receive_timestamp   = ");

    timestamp.seconds         =ntohl(ntp_packet.receive_timestamp  .seconds         );

    timestamp.seconds_fraction=ntohl(ntp_packet.receive_timestamp  .seconds_fraction);

    print_timestamp (timestamp);

 

         printf ("  transmit_timestamp  = ");

         timestamp.seconds         =ntohl(ntp_packet.transmit_timestamp .seconds         );

    timestamp.seconds_fraction=ntohl(ntp_packet.transmit_timestamp .seconds_fraction);

    print_timestamp (timestamp);

 

         printf ("\r\n");

        

         printf ("  round_trip_delay    = %f \r\n", response.round_trip_delay  );

         printf ("  local_clock_offset  = %f \r\n", response.local_clock_offset);

#endif

 

    return true;

}

 

bool get_time (timestamp_t& adjusted_time, const char* address, uint16_t port = _socket_default_port)

{

         ntp_server_response_t response;

         struct sockaddr_in    sa;

        

         if (false==socket_make_address (&sa, address, port))

                  return false;

 

         if (false==client_request(response, &sa))

                  return false;

                 

         uint32_t    offset_second       ;

         uint32_t    offset_milliseconds ;

        

         uint32_t    current_milliseconds;

         uint32_t    current_second      ;

        

         timestamp_t current_timestamp   ;

        

         double      offset;

         bool        offset_negative;

                 

        

         offset          = (0>response.local_clock_offset)? -1.0*response.local_clock_offset : response.local_clock_offset;

         offset_negative = (0>response.local_clock_offset)? true : false;

        

         offset_second       = (uint32_t)( offset                    );

         offset_milliseconds = (uint32_t)((offset-offset_second)*1000);

        

        

         get_current_timestamp (current_timestamp);

        

         current_second       = current_timestamp.seconds;

         current_milliseconds = convert_seconds_fraction_to_milliseconds (current_timestamp.seconds_fraction);

        

         if (offset_negative)

         {

                  if (current_milliseconds<offset_milliseconds)

                  {

                           current_milliseconds = 1000+current_milliseconds-offset_milliseconds;

                           current_second       = current_second-offset_second - 1;

                  }

                  else

                  {

                           current_milliseconds = current_milliseconds-offset_milliseconds;

                           current_second       = current_second-offset_second;

                  }

         }

         else

         {

                  current_milliseconds+=offset_milliseconds;

 

                  current_second       = current_second+offset_second + (current_milliseconds/1000);

                  current_milliseconds = current_milliseconds%1000;

         }

        

         current_timestamp.seconds          = current_second;

         current_timestamp.seconds_fraction = convert_milliseconds_to_seconds_fraction (current_milliseconds);

        

         memcpy (&adjusted_time, &current_timestamp, sizeof(adjusted_time));

        

         return true;

}

 

//===========================================================================

} // end of "namespace sntp { "

 

 

 

/////////////////////////////////////////////////////////////////////////////

//===========================================================================

 

void TRACE (const TCHAR* lpFormatStr, ...)

{

         TCHAR   szBuffer[256];

         va_list args;

 

         va_start  (args, lpFormatStr);

#pragma warning( push )

#pragma warning( disable : 4996 )

         _vsntprintf (szBuffer, 256, lpFormatStr, args);

#pragma warning( pop )

         va_end    (args);     

 

         OutputDebugStringA (szBuffer);

         printf (szBuffer);

}

 

class adjust_settime_priviledge

{

public:

         HANDLE           _token_handle    ;

         TOKEN_PRIVILEGES _token_privileges;

         BOOL             _taken_priviledge;

 

public:

         adjust_settime_priviledge ():

                  _token_handle    (0),

                  _taken_priviledge(FALSE)

         {

                  ZeroMemory(&_token_privileges, sizeof(TOKEN_PRIVILEGES));

         }

        

         ~adjust_settime_priviledge ()

         {

                  revert_settime_priviledge ();

         }

        

public:

         BOOL enable_settime_priviledge (void)

         {

                  BOOL opentoken;

                  BOOL success  ;

 

 

                  _taken_priviledge = FALSE;

 

                  opentoken = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &_token_handle);

                  if (!opentoken)

                  {

                           if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)

                           {

                                   //Must be running on 95 or 98 not NT. In that case just ignore the error

                                   SetLastError(ERROR_SUCCESS);

                                   return TRUE;

                           }

                           TRACE(_T("Failed to get Adjust priviledge token\n"));

                           return FALSE;

                  }

                 

                  ZeroMemory(&_token_privileges, sizeof(TOKEN_PRIVILEGES));

                  if (!LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &_token_privileges.Privileges[0].Luid))

                  {

                           TRACE(_T("Failed in callup to lookup priviledge\n"));

                           return FALSE;

                  }

                 

                  _token_privileges.PrivilegeCount            = 1;

                  _token_privileges.Privileges[0].Attributes |= SE_PRIVILEGE_ENABLED;

                 

                  _taken_priviledge = TRUE;

 

                  success = AdjustTokenPrivileges(_token_handle, FALSE, &_token_privileges, 0, NULL, 0);

                  if (!success)

                  {

                           TRACE(_T("Failed to adjust SetTime priviledge\n"));

                  }

                 

                  return success;

         }

 

         void revert_settime_priviledge (void)

         {

                  if (_taken_priviledge)

                  {

                           _token_privileges.Privileges[0].Attributes &= (~SE_PRIVILEGE_ENABLED);

                          

                           if (!AdjustTokenPrivileges(_token_handle, FALSE, &_token_privileges, 0, NULL, 0))

                           {

                                   TRACE(_T("Failed to reset SetTime priviledge\n"));

                           }

                  }

         }

};

 

int _tmain(int argc, _TCHAR* argv[])

{

         WSADATA           wsadata;

         sntp::timestamp_t adjusted_time;

        

         WSAStartup(MAKEWORD(2,2), &wsadata);

 

 

//       if (true==sntp::get_time (adjusted_time, "time.windows.com"))

         if (true==sntp::get_time (adjusted_time, "time.nist.gov"))

//       if (true==sntp::get_time (adjusted_time, "time.nuri.net"))

         {

                  adjust_settime_priviledge asp;

                 

                  if (TRUE==asp.enable_settime_priviledge ())

                  {

                           sntp::system_time_t st;

                          

                           convert_timestamp_to_system_time (adjusted_time, st);                          

                           SetSystemTime((SYSTEMTIME*)&st);

                          

                           printf ("\r\n# adjusted_time: ");

                           print_timestamp (adjusted_time);

                  }

         }

        

         WSACleanup();

        

         return 0;

}

 

결과



Posted by 셈말짓기 :


// http://blogs.msdn.com/b/vcblog/archive/2008/08/28/the-mallocator.aspx
template <typename T> class Mallocator;

template <> class Mallocator<void>
{
public:
    typedef void*        pointer;
    typedef const void*  const_pointer;
    // reference to void members are impossible.
    typedef void         value_type;

public:
    template <class U> struct rebind { typedef pool_allocator<U> other; };
};   

template <typename T>
class Mallocator
{
public:
 // The following will be the same for virtually all allocators.
 typedef T*        pointer;
 typedef const T*  const_pointer;
 typedef T&        reference;
 typedef const T&  const_reference;
 typedef T         value_type;
 typedef size_t    size_type;
 typedef ptrdiff_t difference_type;

public:
 // Default constructor, copy constructor, rebinding constructor, and destructor.
 // Empty for stateless allocators.
 Mallocator()
 {
 }

 ~Mallocator()
 {
 }

 Mallocator(const Mallocator&)
 {
 }

public:
 // The following must be the same for all allocators.
 template <typename U> struct rebind { typedef Mallocator<U> other; };
 template <typename U> Mallocator(const Mallocator<U>&) {}

 // Returns true if and only if storage allocated from *this
 // can be deallocated from other, and vice versa.
 // Always returns true for stateless allocators.
 bool operator==(const Mallocator& other) const
 {
  return true;
 }

 bool operator!=(const Mallocator& other) const
 {
  return !(*this == other);
 }

public:
 size_t max_size() const
 {
  // The following has been carefully written to be independent of
  // the definition of size_t and to avoid signed/unsigned warnings.
  return (static_cast<size_t>(0) - static_cast<size_t>(1)) / sizeof(T);
 }

 T* address(T& r) const
 {
  return &r;
 }

 const T* address(const T& s) const
 {
  return &s;
 }

 void construct(T * const p, const T& t) const
 {
  void * const pv = static_cast<void *>(p);
  new (pv) T(t);
 }

 void destroy(T * const p) const // Defined below.
 {
  p->~T();
 }

 // The following will be different for each allocator.
 T * allocate(const size_t n) const
 {
  // Mallocator prints a diagnostic message to demonstrate
  // what it's doing. Real allocators won't do this.
  //std::cout << "Allocating " << n << (n == 1 ? " object" : " objects") << " of size " << sizeof(T) << "." << std::endl;
  printf ("allocate n=%d size=%d \r\n", n, sizeof(T));

  // The return value of allocate(0) is unspecified.
  // Mallocator returns NULL in order to avoid depending
  // on malloc(0)'s implementation-defined behavior
  // (the implementation can define malloc(0) to return NULL,
  // in which case the bad_alloc check below would fire).
  // All allocators can return NULL in this case.
  if (n == 0)
  {
   return NULL;
  }

  // All allocators should contain an integer overflow check.
  // The Standardization Committee recommends that std::length_error
  // be thrown in the case of integer overflow.
  if (n > max_size())
  {
   throw std::length_error("Mallocator<T>::allocate() - Integer overflow.");
  }

  // Mallocator wraps malloc().
  void * const pv = malloc(n * sizeof(T));

  // Allocators should throw std::bad_alloc in the case of memory allocation failure.
  if (pv == NULL)
  {
   throw std::bad_alloc();
  }

  return static_cast<T *>(pv);
 }

 void deallocate(T * const p, const size_t n) const
 {
  // Mallocator prints a diagnostic message to demonstrate
  // what it's doing. Real allocators won't do this.
  std::cout << "Deallocating " << n << (n == 1 ? " object" : "objects") << " of size " << sizeof(T) << "." << std::endl;

  // Mallocator wraps free().
  free(p);
 }

 // The following will be the same for all allocators that ignore hints.
 template <typename U> T * allocate(const size_t n, const U * /* const hint */) const
 {
  return allocate(n);
 }

 // Allocators are not required to be assignable, so
 // all allocators should have a private unimplemented
 // assignment operator. Note that this will trigger the
 // off-by-default (enabled under /Wall) warning C4626
 // "assignment operator could not be generated because a
 // base class assignment operator is inaccessible" within
 // the STL headers, but that warning is useless.
private:
 Mallocator& operator=(const Mallocator&);
};

Posted by 셈말짓기 :

#include  <stdio.h>
#include  <signal.h>
#include  <setjmp.h>

jmp_buf  g_my_jump_buffer;

bool try_signal (int sig)
{
    int result;

    result = setjmp(my_jump_buffer, sig);
    printf ("setjmp(): resutl %d \r\n", result);
    if (sig==result)
        return true;
    return false;
}

void signal_handler (int sig)
{
    printf ("signal_handler(%d) \r\n", sig);
    longjmp (g_my_jump_buffer, sig);
}

int main (void)
{
    unsigned int* p = (unsigned int*)0xffffffff;

    signal (SIGBUS, signal_handler);

    while (1)
    {    
        if (try_signal (SIGBUS)==0)
        {
            printf ("no signal \r\n");
            *p = 0x00000001;
        }
        else
        {
            printf ("signal \r\n");
        }
    }
    return 0;
}

이런식으로 setjmp를 사용하면 프로그램이 망한다.
setjmp시 현재 스택 포인터를 저장하는 역할을 하기 때문에 위에 처럼 setjmp를 랩핑해서 함수를 호출하여 사용하면
1. 위에 main함수에서 try_signal()을 호출하고 
2. signal이 발생되어서 signal_handler()를 거쳐서
3. 다시 setjmp()함수 위치로 복귀하려 했을때 
   이전 try_signal()이 호출 되어서 저장했던 스택포인터는 
   이전 try_singal()가 main()함수로 복귀를 했으므로 저장했던 해당 스택포인터가 유효 하지 않다.
랩핑해서 사용하고 싶을땐 아래와 같이 inline함수로 구현하던가 매크로로 구현해야한다.

#include  <stdio.h>
#include  <signal.h>
#include  <setjmp.h>

jmp_buf  g_my_jump_buffer;

inline bool try_signal (int sig)
{
    int result;

    result = setjmp(my_jump_buffer, sig);
    printf ("setjmp(): resutl %d \r\n", result);
    if (sig==result)
        return true;
    return false;
}

void signal_handler (int sig)
{
    printf ("signal_handler(%d) \r\n", sig);
    longjmp (g_my_jump_buffer, sig);
}

int main (void)
{
    unsigned int* p = (unsigned int*)0xffffffff;

    signal (SIGBUS, signal_handler);

    while (1)
    {    
        if (try_signal (SIGBUS)==0)
        {
            printf ("no signal \r\n");
            *p = 0x00000001;
        }
        else
        {
            printf ("signal \r\n");
        }
    }
    return 0;
}

Posted by 셈말짓기 :

/////////////////////////////////////////////////////////////////////////////
//===========================================================================
template<typename T>
class Singleton : public T
{
protected:
 Singleton();

public:
 static Singleton<T>& Instance(void);
};

//===========================================================================
template<typename T>
Singleton<T>::Singleton ()
{
}

template<typename T>
Singleton<T>& Singleton<T>::Instance(void)
{
 static Singleton<T> single_instance;

 return single_instance;
}

/////////////////////////////////////////////////////////////////////////////
//===========================================================================
class TestTaskData
{
...
};

/////////////////////////////////////////////////////////////////////////////
//===========================================================================
template class Singleton<TestTaskData>;

명시적으로 템플릿 클래스의 오브젝트 코드를 생성하기 위해서는(Explicit template instantiation)
위의 코드를 cpp에 추가 하면 해당 cpp의 오브젝트 파일에 생성된다.

참고사항> 
#  gcc에서 컴파일 옵션 template instantiation 
   -fimplicit-templates : 묵시적 템플릿 인스턴티에이션을 사용 (템플릿 클래스의 인라인화)
   -fno-implicit-templates : 묵시적 템플릿 인스턴티에이션을 사용 안함
   -frepo : rpo 파일을 통해서 템플릿 인스턴스 db를 생성해서 자동으로 처리

여담>
1. STL 쓰면서 -fno-implicit-templates 옵션 사용하면 죽음이다.
2. msvc++ 생각보다 똑똑한 녀석이었다. ~_~;
3. #pragma interface 와 implementation 살펴보자.

Posted by 셈말짓기 :

#include <stdio.h>
#include <tchar.h>

///////////////////////////////////////////////////////////////////////////////
struct Operand1
{
    int GetOp1()
    {
        return 2;
    }

    int GetOp2()
    {
        return 3;
    }
};

struct Operand2
{
    int GetOp1()
    {
        return 3;
    }

    int GetOp2()
    {
        return 4;
    }
};

///////////////////////////////////////////////////////////////////////////////
template<class T> 
struct CalcEngine1
{
    int Calc(void)
    {
        T* pThis= (T*)this;
        return pThis->GetOp1() / pThis->GetOp2();
    }
};

template<class T> 
struct CalcEngine2
{
    double Calc(void)
    {
        T* pThis= (T*)this;
        return pThis->GetOp1() / (double) pThis->GetOp2();
    }
};

///////////////////////////////////////////////////////////////////////////////
template
<
    class                            OperandPolicy,
    template<class CalcEngine> class CalcEnginePolicy
>
class Calculator : 
    public OperandPolicy,
    public CalcEnginePolicy<OperandPolicy>
{
public:
    void Show (void)
    {
        printf ("Show()=%f\r\n", CalcEnginePolicy<OperandPolicy>::Calc() );
    }
};

///////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
    Calculator <Operand1,CalcEngine1> a;
    Calculator <Operand1,CalcEngine2> b;
    Calculator <Operand2,CalcEngine1> c;
    Calculator <Operand2,CalcEngine2> d;

    a.Show();
    b.Show();
    c.Show();
    d.Show();

    return 0;
}

Posted by 셈말짓기 :

// MetaProgramming.cpp : Defines the entry point for the console application.
//

#include <stdio.h>
#include <tchar.h>

template <unsigned long N>
struct binary
{
    static unsigned const value =
        binary<N/10>::value*2 + N%10;
};

template <>
struct binary<0>
{
    static unsigned const value = 0;
};

int _tmain(int argc, _TCHAR* argv[])
{
    unsigned const one   = binary<   1>::value;
    unsigned const two   = binary<  10>::value;
    unsigned const three = binary<  11>::value;
    unsigned const four  = binary< 100>::value;
    unsigned const seven = binary< 111>::value;
    unsigned const nine  = binary<1001>::value;

    printf (" one   =%d\n", one  );
    printf (" two   =%d\n", two  );
    printf (" three =%d\n", three);
    printf (" four  =%d\n", four );
    printf (" seven =%d\n", seven);
    printf (" nine  =%d\n", nine );

    return 0;
}
Posted by 셈말짓기 :

[가수 변환식] (가수 범위= +1.0 > x > -1.0 )

아래 Code에서 xbits는 부호비트를 포함한 값이다.
-----------------------------------------------------------------------------
#include <windows.h>
#include <math.h>
#include <stdio.h>
#include <tchar.h>

DWORD ConvertMantissaToXBits (double value, DWORD xbits=24)
{
 if (xbits>31 || xbits<12)
  return 0;

 static const DWORD MASK[33] =
 {
  /* 00 */ 0x00000000,
  /* 01 */ 0x00000001,/* 02 */ 0x00000003,/* 03 */ 0x00000007,/* 04 */ 0x0000000f,
  /* 05 */ 0x0000001f,/* 06 */ 0x0000003f,/* 07 */ 0x0000007f,/* 08 */ 0x000000ff,
  /* 09 */ 0x000001ff,/* 10 */ 0x000003ff,/* 11 */ 0x000007ff,/* 12 */ 0x00000fff,
  /* 13 */ 0x00001fff,/* 14 */ 0x00003fff,/* 15 */ 0x00007fff,/* 16 */ 0x0000ffff,
  /* 17 */ 0x0001ffff,/* 18 */ 0x0003ffff,/* 19 */ 0x0007ffff,/* 20 */ 0x000fffff,
  /* 21 */ 0x001fffff,/* 22 */ 0x003fffff,/* 23 */ 0x007fffff,/* 24 */ 0x00ffffff,
  /* 25 */ 0x01ffffff,/* 26 */ 0x03ffffff,/* 27 */ 0x07ffffff,/* 28 */ 0x0fffffff,
  /* 29 */ 0x1fffffff,/* 30 */ 0x3fffffff,/* 31 */ 0x7fffffff,/* 32 */ 0xffffffff
 };

 DWORD  result = 0;
 DWORD  h      = 0;
 double m      = 0.0;

 if (value>=1.0 || value<-1.0)
  return MASK[xbits] & (~(1<<(xbits-1)));

 //m = pow (2.0, double(xbits-1)) * value;
 m = (1<<(xbits-1)) * value;
 h = DWORD (m);

 result = h&MASK[xbits];

 return result;
}

double ConvertXBitsToMantissa (DWORD value, DWORD xbits=24)
{
 if (xbits>31 || xbits<12)
  return 0.0;

 double     result  = 0.0;
 signed int n       = 0;

 n = value<<(32-xbits);
 n = n    >>(32-xbits); // no moved signal flag

 //result = n/pow (2.0, double(xbits-1));
 result = double(n)/(1<<(xbits-1));

 return result;
}

int _tmain(int argc, _TCHAR* argv[])
{
 DWORD  bits = 24;
 double v;
 DWORD  h;
 double f;
 int    i;
 double s;

 v = -1;
 s =  0.1;
 for (i=0; i<22; i++)
 {
  h = ConvertMantissaToXBits(v,bits);
  f = ConvertXBitsToMantissa(h,bits);

  printf ("Mant->xBits(%+.3f)= 0x%08x : ",  v, h);
  printf ("xBits->Mant(0x%08x)= %+.3f\r\n", h, f);

  v = v+s;
 }

 return 0;
}
-----------------------------------------------------------------------------
Mant->xBits(-1.000)= 0x00800000 : xBits->Mant(0x00800000)= -1.000
Mant->xBits(-0.900)= 0x008ccccd : xBits->Mant(0x008ccccd)= -0.900
Mant->xBits(-0.800)= 0x0099999a : xBits->Mant(0x0099999a)= -0.800
Mant->xBits(-0.700)= 0x00a66667 : xBits->Mant(0x00a66667)= -0.700
Mant->xBits(-0.600)= 0x00b33334 : xBits->Mant(0x00b33334)= -0.600
Mant->xBits(-0.500)= 0x00c00000 : xBits->Mant(0x00c00000)= -0.500
Mant->xBits(-0.400)= 0x00cccccd : xBits->Mant(0x00cccccd)= -0.400
Mant->xBits(-0.300)= 0x00d9999a : xBits->Mant(0x00d9999a)= -0.300
Mant->xBits(-0.200)= 0x00e66667 : xBits->Mant(0x00e66667)= -0.200
Mant->xBits(-0.100)= 0x00f33334 : xBits->Mant(0x00f33334)= -0.100
Mant->xBits(-0.000)= 0x00000000 : xBits->Mant(0x00000000)= +0.000
Mant->xBits(+0.100)= 0x000ccccc : xBits->Mant(0x000ccccc)= +0.100
Mant->xBits(+0.200)= 0x00199999 : xBits->Mant(0x00199999)= +0.200
Mant->xBits(+0.300)= 0x00266666 : xBits->Mant(0x00266666)= +0.300
Mant->xBits(+0.400)= 0x00333333 : xBits->Mant(0x00333333)= +0.400
Mant->xBits(+0.500)= 0x003fffff : xBits->Mant(0x003fffff)= +0.500
Mant->xBits(+0.600)= 0x004ccccc : xBits->Mant(0x004ccccc)= +0.600
Mant->xBits(+0.700)= 0x00599999 : xBits->Mant(0x00599999)= +0.700
Mant->xBits(+0.800)= 0x00666666 : xBits->Mant(0x00666666)= +0.800
Mant->xBits(+0.900)= 0x00733333 : xBits->Mant(0x00733333)= +0.900
Mant->xBits(+1.000)= 0x007fffff : xBits->Mant(0x007fffff)= +1.000
Mant->xBits(+1.100)= 0x007fffff : xBits->Mant(0x007fffff)= +1.000

Posted by 셈말짓기 :

#include <stdio.h>
#include <tchar.h>
#include <math.h>

#define LENGTH       32
#define SIGN_BIT     31
#define EXPONENT_MSB 30
#define EXPONENT_LSB 23
#define MANTISSA_MSB 22
#define MANTISSA_LSB  0

float hex_to_float (unsigned int value)
{
 int   sign;
 int   exp;
 int   man;
 float result;

 sign = (value & (1 << SIGN_BIT)) != 0;
#pragma warning( push )
#pragma warning( disable : 4307 ) // '-' : integral constant overflow.
 exp  = ((value & ( (2<<EXPONENT_MSB) - (1<<EXPONENT_LSB) )) >> EXPONENT_LSB)
  - (1 << (EXPONENT_MSB - EXPONENT_LSB))
  - (MANTISSA_MSB - MANTISSA_LSB);
#pragma warning( pop )

 man  = ((value & ( (2<<MANTISSA_MSB) - (1<<MANTISSA_LSB) )) >> MANTISSA_LSB)
  + (2 << (MANTISSA_MSB - MANTISSA_LSB));

 result = man * pow((float)2, (float)exp) * (sign ? -1 : 1);

 return result;
}

int _tmain(int argc, _TCHAR* argv[])
{
 union
 {
  unsigned int n;
  float        f;
 } value;

 int   i;
 float f;


 value.f =(float)   0;
 f       =(float)-1.1;

 for (i=0; i<10; i++)
 {
  printf ("%+e=0x%08x:hex_to_float()=%+e \r\n", value.f, value.n, hex_to_float(value.n));
  value.f += f;
 }

 return 0;
}
-----------------------------------------------------------------------------
+0.000000e+000=0x00000000:hex_to_float()=+0.000000e+000
-1.100000e+000=0xbf8ccccd:hex_to_float()=-1.100000e+000
-2.200000e+000=0xc00ccccd:hex_to_float()=-2.200000e+000
-3.300000e+000=0xc0533334:hex_to_float()=-3.300000e+000
-4.400000e+000=0xc08ccccd:hex_to_float()=-4.400000e+000
-5.500000e+000=0xc0b00000:hex_to_float()=-5.500000e+000
-6.600000e+000=0xc0d33333:hex_to_float()=-6.600000e+000
-7.700000e+000=0xc0f66666:hex_to_float()=-7.700000e+000
-8.800000e+000=0xc10ccccd:hex_to_float()=-8.800000e+000
-9.900001e+000=0xc11e6667:hex_to_float()=-9.900001e+000


-----------------------------------------------------------------------------

부동소수점 표현의 국제표준은 IEEE 754입니다.

-----------------------------------------------------------------------------

< float >
C의 float타입은 IEEE 754의 single precision 플로팅포인트를 구현한 것으로,
다음과 같은 포맷을 가집니다.
sign : bit31 (1비트)
exponent : bit30~bit23 (8비트)
mantissa : bit22~bit0 (23비트)

이때, 가수부(만티사)는 정수부분을 1로 정규화한 2진소수표현이며, 지수부(exponent)는
원래 지수에 바이어스 127을 더한 값입니다.
부호비트는 0이면 양수, 1이면 음수입니다.

가수부의 23비트가 100 0000 0000 0000 0000 0000 이라면, 이때 이 부동소수의 가수는
2진소수로 1.1이 되어, 10진법으로는 1 + 1/2 = 1.5가 됩니다.

지수부의 표현이 1000 0000 이라면, 이 값은 바이어스 127, 즉 111 1111이 더해진 수
이므로 실제 지수는 128 - 127 = 1이 됩니다.

따라서, 0 100 0000 100 0000 0000 0000 0000 0000 으로 표현되는 부동소수는
따라서, [0] [100 0000 0] [100 0000 0000 0000 0000 0000] 으로 표현되는 부동소수는
1.5 * 2^1 = 3.0 을 표현하게 됩니다.

single precision의 유효숫자는 가수의 비트길이 (정수부분 포함)24에 의해 결정되며,
2^24 은 약 10^7.2 이므로, 유효숫자는 약 7자리가 됩니다.

-----------------------------------------------------------------------------

< double >
C의 double타입은 IEEE 754의 double precision 플로팅포인트를 구현한 것으로,
다음과 같은 포맷을 가집니다.
sign : bit63 (1비트)
exponent : bit62~bit52 (11비트)
mantissa : bit51~bit0 (52비트)

이때, single precision과는 지수부의 바이어스가 1023이라는 것만 다르고, 나머지
표현방법은 동일합니다.

double precision의 유효숫자 역시 정수부분을 포함한 가수의 비트길이 53에 의해 결정되며,
2^53 은 약 10^15.9 이므로, 유효숫자는 약 약 15자리가 됩니다.

-----------------------------------------------------------------------------

< 예외 정의 >
1. 플로팅포인트 표현에서 모든 비트가 0인 수는 0으로 정의합니다.
2. 지수부의 모든 비트가 0인 수는 가수의 정수부분을 0으로 계산합니다.
3. 지수부의 모든 비트가 1이고, 가수부의 모든 비트가 0이면 무한대로 정의합니다.
4. 지수부의 모든 비트가 1이고, 가수부가 0이 아니면 NaN (Not a Number)로 정의하여
   예외를 발생하게 됩니다.


Posted by 셈말짓기 :

#include <windows.h>
#include <tchar.h>


#include <iostream>
#include <memory>

class o_1
{
public:
 o_1 () : a_ (0) { std::cout << "o_1()"  << std::endl; }
 virtual ~o_1( ) { std::cout << "~o_1()" << std::endl; }
public:
 virtual void show (void)
 {
  std::cout << "o_1::show("<< a_ <<")" << std::endl;
 }
public:
 int a_;
};

class o_2 : public o_1
{
public:
 o_2 () : o_1(), b_(0) { std::cout << "o_2()"  << std::endl; }
 virtual ~o_2()        { std::cout << "~o_2()" << std::endl; }
public:
 virtual void show (void)
 {
  std::cout << "o_2::show("<< b_ <<")" << std::endl;
 }
public:
 int b_;
};

class o_3 : public o_2
{
public:
 o_3 () : o_2(), c_(0) { std::cout << "o_3()"  << std::endl; }
 virtual ~o_3()        { std::cout << "~o_3()" << std::endl; }
public:
 virtual void show (void)
 {
  std::cout << "o_3::show("<< c_ <<")" << std::endl;
 }
public:
 int c_;
};

unsigned int vftable_of____o_1;
unsigned int vftable_of____o_2;
unsigned int vftable_of____o_3;

unsigned int get__vfp  (void* p)
{
 unsigned int __vfp = 0;

 memcpy (&__vfp, p, 4);

 return __vfp;
}

#pragma warning( push )
#pragma warning( disable: 4313 )
// C4313: 'printf' : '%x' in format string conflicts with argument 1 of type 'xxx'

void init (void)
{
 o_1 *o1=new o_1();
 o_2  o2;
 o_3 *o3=new o_3();

 memcpy (&vftable_of____o_1,  o1, 4);
 memcpy (&vftable_of____o_2, &o2, 4);
 memcpy (&vftable_of____o_3,  o3, 4);

 printf (" \r\n");
 printf ("# o_1::vftable_of____o_1=0x%08x \r\n", vftable_of____o_1);
 printf ("# o_2::vftable_of____o_2=0x%08x \r\n", vftable_of____o_2);
 printf ("# o_3::vftable_of____o_3=0x%08x \r\n", vftable_of____o_3);
 printf (" \r\n");

 delete o1;
 delete o3;
}

void test (void)
{
 o_3 *o = new o_3();
 o_1 *p = o;

 o->a_ = 100;
 o->b_ = 200;
 o->c_ = 300;

 printf (" p    's address=0x%08x \r\n", p);
 printf (" p->a_'s address=0x%08x \r\n", &o->a_);
 printf (" p->b_'s address=0x%08x \r\n", &o->b_);
 printf (" p->c_'s address=0x%08x \r\n", &o->c_);
 p->show ();

 printf (" \r\n");
 printf ("# p's __vfp 0x%08x \r\n", get__vfp(p));
 printf (" \r\n");
 printf ("# p->~o_1() \r\n");
 p->~o_1();
 printf (" \r\n");
 printf ("# p's __vfp 0x%08x \r\n", get__vfp(p));
 printf (" \r\n");
 p->show ();

 printf (" \r\n");
 printf ("# let's get fun! \r\n");
 memcpy (p, &vftable_of____o_3, 4); p->show ();
 memcpy (p, &vftable_of____o_2, 4); p->show ();
 memcpy (p, &vftable_of____o_1, 4); p->show ();


 int   v;
 char *member_variable_ptr;

 member_variable_ptr = (char*)p;

 v = 99;
 member_variable_ptr += 4;
 printf (" \r\n");
 printf ("# one more time! (member_variable_ptr=0x%08x) \r\n", member_variable_ptr);
 memcpy (member_variable_ptr, &v, 4);
 memcpy (p, &vftable_of____o_3, 4); p->show ();
 memcpy (p, &vftable_of____o_2, 4); p->show ();
 memcpy (p, &vftable_of____o_1, 4); p->show ();

 v = 98;
 member_variable_ptr+= 4;
 printf (" \r\n");
 printf ("# one more time! (member_variable_ptr=0x%08x) \r\n", member_variable_ptr);
 memcpy (member_variable_ptr, &v, 4);
 memcpy (p, &vftable_of____o_3, 4); p->show ();
 memcpy (p, &vftable_of____o_2, 4); p->show ();
 memcpy (p, &vftable_of____o_1, 4); p->show ();

 v = 97;
 member_variable_ptr+= 4;
 printf (" \r\n");
 printf ("# one more time! (member_variable_ptr=0x%08x) \r\n", member_variable_ptr);
 memcpy (member_variable_ptr, &v, 4);
 memcpy (p, &vftable_of____o_3, 4); p->show ();
 memcpy (p, &vftable_of____o_2, 4); p->show ();
 memcpy (p, &vftable_of____o_1, 4); p->show ();


 printf (" \r\n");
 printf ("# last time ! \r\n");
 memcpy (p, &vftable_of____o_3, 4);

 delete p;
}

#pragma warning( pop )


int _tmain(int argc, _TCHAR* argv[])
{
 std::cout << "==============================================================" <<std::endl;
 std::cout << "init()" <<std::endl;
 std::cout << "==============================================================" <<std::endl;
 init ();
 std::cout << "==============================================================" <<std::endl;
 std::cout <<std::endl;
 std::cout <<std::endl;
 std::cout <<std::endl;


 std::cout << "==============================================================" <<std::endl;
 std::cout << "test()" <<std::endl;
 std::cout << "==============================================================" <<std::endl;
 test ();
 std::cout << "==============================================================" <<std::endl;
 std::cout <<std::endl;
 std::cout <<std::endl;
 std::cout <<std::endl;

 return 0;
}
-----------------------------------------------------------------------------
==============================================================
init()
==============================================================
o_1()
o_1()
o_2()
o_1()
o_2()
o_3()

# o_1::vftable_of____o_1=0x00418890
# o_2::vftable_of____o_2=0x004188c4
# o_3::vftable_of____o_3=0x004188f4

~o_1()
~o_3()
~o_2()
~o_1()
~o_2()
~o_1()
==============================================================


==============================================================
test()
==============================================================
o_1()
o_2()
o_3()
 p    's address=0x003a6858
 p->a_'s address=0x003a685c
 p->b_'s address=0x003a6860
 p->c_'s address=0x003a6864
o_3::show(300)

# p's __vfp 0x004188f4

# p->~o_1()
~o_3()
~o_2()
~o_1()

# p's __vfp 0x00418890

o_1::show(100)

# let's get fun!
o_3::show(300)
o_2::show(200)
o_1::show(100)

# one more time! (member_variable_ptr=0x003a685c)
o_3::show(300)
o_2::show(200)
o_1::show(99)

# one more time! (member_variable_ptr=0x003a6860)
o_3::show(300)
o_2::show(98)
o_1::show(99)

# one more time! (member_variable_ptr=0x003a6864)
o_3::show(97)
o_2::show(98)
o_1::show(99)

# last time !
~o_3()
~o_2()
~o_1()

==============================================================

Posted by 셈말짓기 :

파괴자를 직접 부르면 어떻게 될까?

object o;

o.~object();

궁금해졌다.

-----------------------------------------------------------------------------
#include <windows.h>
#include <tchar.h>

#include <iostream>

class o_1
{
public:
 o_1 ()         { std::cout << "o_1()"  << std::endl; }
 virtual ~o_1() { std::cout << "~o_1()" << std::endl; }
};

class o_2 : public o_1
{
public:
 o_2 () : o_1() { std::cout << "o_2()"  << std::endl; }
 virtual ~o_2() { std::cout << "~o_2()" << std::endl; }
};

class o_3 : public o_2
{
public:
 o_3 () : o_2() { std::cout << "o_3()"  << std::endl; }
 virtual ~o_3() { std::cout << "~o_3()" << std::endl; }
};

void test1 (void)
{
 o_3  o;

 o_1* p = &o;

 std::cout << "-----------" <<std::endl;
 p->~o_1 ();
 std::cout << "-----------" <<std::endl;
}

void test2 (void)
{
 o_1* p = new o_3 ();

 std::cout << "-----------" <<std::endl;
 p->~o_1 ();
 std::cout << "-----------" <<std::endl;

 delete p;
}

void test3 (void)
{
 o_1* p = new o_3 ();

 std::cout << "-----------" <<std::endl;
 //p->~o_1 ();
 std::cout << "-----------" <<std::endl;

 delete p;
}

int _tmain(int argc, _TCHAR* argv[])
{
 std::cout << "###########" <<std::endl;
 test1();
 std::cout << "###########" <<std::endl;
 test2();
 std::cout << "###########" <<std::endl;
 test3();
 std::cout << "###########" <<std::endl;

 return 0;
}
-----------------------------------------------------------------------------
###########
<- test1() 함수: 잘된다...
o_1()
o_2()
o_3()
-----------
~o_3()
~o_2()
~o_1()
-----------
~o_3()
~o_2()
~o_1()
########### <- test2() 함수: 무엇인가 이상하다???
o_1()
o_2()
o_3()
----------- <- p->~o_1 (); 호출 부분... 부모 클래스 파괴자를 호출한다.
~o_3()
~o_2()
~o_1()
----------- <- delete p; 가 이상하다 = _=??? 무엇일까...
~o_1()
########### <- test3() 함수:
o_1()
o_2()
o_3()
-----------
<- //p->~o_1 ();
-----------   
주석처리 했더니 delete p; 가 제대로 동작한다.
~o_3()
~o_2()
~o_1()
###########
계속하려면 아무 키나 누르십시오 . . .
-----------------------------------------------------------------------------
디버깅을 해보았다.

p->~o_1(); 호출하기전 __vfptr(virtual fucntion pointer) 녀석은 이렇게 가리키고 있었다.

사용자 삽입 이미지

하지만, p->~o_1();을 호출하니 __vfptr 녀석은 이렇게 바뀌어 버렸다.
사용자 삽입 이미지

         test1()역시 p->~o_1();를 수행하면 p의 __vfptr 값도 동일하게 바뀌었다.               


고심끝에 내린 결론은

test1()에서 Stack에 생성된 객체는 파괴될때 가상함수-파괴자를 사용하지 않고 파괴 되므로
위와같은 결과를 얻었고,

test2()에서 Heap에 생성된 객체는 파괴되기전에 직접 p->~o_1(); 호출 하여 __vfptr이
변경됨으로서 delete p;에서 가상함수-파괴자를 이용한 파괴자 호출이 제대로 되지 못하는
것이다.

__vfptr이 변경 되므로 가상함수들이 제대로 동작을 안할 것이라 판단 되었다.
그래서, 소스 코드를 수정해서 다시 테스트 해보았다.
-----------------------------------------------------------------------------
#include <windows.h>
#include <tchar.h>

#include <iostream>

class o_1
{
public:
 o_1 ()         { std::cout << "o_1()"  << std::endl; }
 virtual ~o_1() { std::cout << "~o_1()" << std::endl; }
public:
 virtual void show (void)
 {
  std::cout << "o_1::show()" << std::endl;
 }

};

class o_2 : public o_1
{
public:
 o_2 () : o_1() { std::cout << "o_2()"  << std::endl; }
 virtual ~o_2() { std::cout << "~o_2()" << std::endl; }
public:
 virtual void show (void)
 {
  std::cout << "o_2::show()" << std::endl;
 }

};

class o_3 : public o_2
{
public:
 o_3 () : o_2() { std::cout << "o_3()"  << std::endl; }
 virtual ~o_3() { std::cout << "~o_3()" << std::endl; }
public:
 virtual void show (void)
 {
  std::cout << "o_3::show()" << std::endl;
 }

};

void test1 (void)
{
 o_3  o;

 o_1* p = &o;

 std::cout << "-----------" <<std::endl;
 p->show ();
 o.show();
 std::cout << "-----------" <<std::endl;
 p->~o_1 ();
 std::cout << "-----------" <<std::endl;
 p->show ();
 o.show();
 std::cout << "-----------" <<std::endl;
}

void test2 (void)
{
 o_1* p = new o_3 ();

 std::cout << "-----------" <<std::endl;
 p->~o_1 ();
 std::cout << "-----------" <<std::endl;

 delete p;
}

void test3 (void)
{
 o_1* p = new o_3 ();

 std::cout << "-----------" <<std::endl;
 //p->~o_1 ();
 std::cout << "-----------" <<std::endl;

 delete p;
}

int _tmain(int argc, _TCHAR* argv[])
{
 std::cout << "###########" <<std::endl;
 test1();
 std::cout << "###########" <<std::endl;
 test2();
 std::cout << "###########" <<std::endl;
 test3();
 std::cout << "###########" <<std::endl;

 return 0;
}
-----------------------------------------------------------------------------
########### <- test1() 함수: 잘되는게 아니었다.
o_1()
o_2()
o_3()
-----------
o_3::show() <- p->show (); 정상이다.
o_3::show() <- o.show();   정상이다.
-----------
~o_3()
~o_2()
~o_1()
-----------
o_1::show() <- p->show ();      __vfptr이 변경되었으므로 제대로 동작을 못한다.     
o_3::show() <- o.show();
-----------
~o_3()
~o_2()
~o_1()
########### <- test2() 함수:
o_1()
o_2()
o_3()
-----------
~o_3()
~o_2()
~o_1()
-----------
~o_1()
########### <- test3() 함수:
o_1()
o_2()
o_3()
-----------
-----------
~o_3()
~o_2()
~o_1()
###########
계속하려면 아무 키나 누르십시오 . . .

-----------------------------------------------------------------------------
처음에는 컴파일러 버그라고 생각되었지만 곰곰히 따져보니 아닌 것 같다.
설마, 진짜 컴파일러 버그는 아니겠지... = _ =;

[사용 컴파일러]
Microsoft Visual Studio 2005
Version 8.0.50727.762  (SP.050727-7600)
Microsoft .NET Framework
Version 2.0.50727 SP1

Installed Edition: Professional

-----------------------------------------------------------------------------
추가:
데브피아에 올렸보았었는데 오해하실 수 있는 부분 있는거 같아서 추가합니다.

제가 말하고 싶었던것은 소멸자를 직접 호출했을경우 vftable을 가리키는 __vfptr이
변경된다는 걸 말하고 싶었던겁니다.

좀 더 부연설명을 하자면 메모리 풀 같은 걸 만들때 메모리 풀에서 받은 객체를 사용하고 삭제
후 그대로 또 사용했을 경우 일어나는 현상이 어떻게 될것인가 따져보는 의미입니다.

위의 코드는 일종의 toy code입니다.


제가 컴파일러 버그가 아닐까라고 생각한 부분은 직접 파괴자(소멸자)가 호출된다고 해서
메모리에서 실제로 delete가 일어나는 건 아니기 때문에 vftable을 가리키는 __vfptr가
변경되는게 맞는건지 아닌지
잘 판단이 안되었기 때문에 적어 놓은겁니다.


 

Posted by 셈말짓기 :

Reference-Counting

2008. 8. 18. 13:24 from 셈말짓기/C and C++

#include <windows.h>
#include <tchar.h>

#include <iostream>

/////////////////////////////////////////////////////////////////////////////
//
// Handle
//
/////////////////////////////////////////////////////////////////////////////
template<typename T>
class CRefCountedInstance
{
public:
 CRefCountedInstance ();

public:
 inline void AddRef       (void);
 inline void Release      (void);
 inline void Assign       (T *p);
 inline bool IsReferenced (void);
 inline T*   GetInstance  (void);

private:
 T   *Instance_;
 int  RefCount_;
};

template<typename T>
CRefCountedInstance<T>::CRefCountedInstance () :
 RefCount_ (0),
 Instance_ (0)
{
}

template<typename T>
void CRefCountedInstance<T>::AddRef (void)
{
 RefCount_++;
}

template<typename T>
void CRefCountedInstance<T>::Release (void)
{
 if (RefCount_>0)
 {
  RefCount_--;
 }

 if (RefCount_==0)
 {
  if (Instance_)
  {
   delete Instance_;
  }

  Instance_ = 0;
 }
}

template<typename T>
void CRefCountedInstance<T>::Assign (T *p)
{
 Instance_ = p;
 AddRef ();
}

template<typename T>
bool CRefCountedInstance<T>::IsReferenced (void)
{
 if (RefCount_==0)
  return false;

 return true;
}

template<typename T>
T* CRefCountedInstance<T>::GetInstance (void)
{
 return Instance_;
}

template<typename T>
class Handle
{
public:
 Handle ();
 explicit Handle (T *p);
 Handle (const Handle<T> &copy);
 ~Handle ();

public:
 Handle<T>& operator = (const Handle<T>& rhs);

public:
 inline T& operator*  () const;
 inline T* operator-> () const;
 inline T* Get    (void) const;

private:
 CRefCountedInstance<T>* Rep_;
};

template<typename T>
Handle<T>::Handle () : Rep_(0)
{
}

template<typename T>
Handle<T>::Handle (T *p)
{
 Rep_ = new CRefCountedInstance<T>();
 Rep_->Assign(p);
}

template<typename T>
Handle<T>::Handle (const Handle<T> &copy)
{
 Rep_ = copy.Rep_;

 if (Rep_)
  Rep_->AddRef ();
}

template<typename T>
Handle<T>::~Handle ()
{
 if (Rep_)
 {
  Rep_->Release ();

  if (!Rep_->IsReferenced())
   delete Rep_;
 }
}

template<typename T>
Handle<T>& Handle<T>::operator = (const Handle<T>& rhs)
{
 if (this == &rhs) return *this;

 if (Rep_)
  Rep_->Release ();

 Rep_ = rhs.Rep_;

 if (Rep_)
  Rep_->AddRef ();

 return *this;
}

template<typename T>
T& Handle<T>::operator*() const
{
 return *(Rep_->GetInstance());
}

template<typename T>
T* Handle<T>::operator -> () const
{
 if (Rep_==0)
  return 0;

 return (Rep_->GetInstance());
}

template<typename T>
T* Handle<T>::Get (void) const
{
 if (Rep_==0)
  return 0;

 return (Rep_->GetInstance());
}


/////////////////////////////////////////////////////////////////////////////
//
// Application
//
/////////////////////////////////////////////////////////////////////////////
class Object
{
public:
 explicit Object(int n=0) : Data_(n)
 {
  std::cout << "Object(" << Data_ << ")" << std::endl;
 }

public:
 virtual ~Object()
 {
  std::cout << "~Object(" << Data_ << ")" << std::endl;
 }

public:
 int Data_;
};

Handle<Object> Test (Handle<Object> h)
{
 if (h.Get())
  h->Data_ = 3;

 return h;
}


/////////////////////////////////////////////////////////////////////////////
//
// Startup
//
/////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
 Handle<Object> p1( new Object(1) );
 Handle<Object> p2( new Object(2) );
 Handle<Object> p3;
 Handle<Object> p4;


 std::cout << std::endl;


 std::cout << "p2 = p1;" << std::endl;
 p2 = p1;
 std::cout << std::endl;


 std::cout << "p3 = p1;" << std::endl;
 p3 = p1;
 std::cout << std::endl;


 std::cout << "p4 = Test (p3);" << std::endl;
 p4 = Test (p3);

 std::cout << "p1->Data_ = " << p1->Data_ << std::endl;
 std::cout << "p2->Data_ = " << p2->Data_ << std::endl;
 std::cout << "p3->Data_ = " << p3->Data_ << std::endl;
 std::cout << "p4->Data_ = " << p3->Data_ << std::endl;

 return 0;
}
-----------------------------------------------------------------------------
Object(1)
Object(2)

p2 = p1;
~Object(2)

p3 = p1;

p4 = Test (p3);
p1->Data_ = 3
p2->Data_ = 3
p3->Data_ = 3
p4->Data_ = 3
~Object(3)

Posted by 셈말짓기 :

#if !defined (__REFCOUNTEDAUTOPTR__H__)
#define __REFCOUNTEDAUTOPTR__H__

#pragma once


// ------------------------------------------------------------------------- //
//  Global
// ------------------------------------------------------------------------- //
template<class T>              class CAutoBasicPtr;
template<class T, class lockT> class CRefcountedAutoPtrRep;
template<class T, class lockT> class CRefcountedAutoPtr;


// ------------------------------------------------------------------------- //
//  Class: CAutoBasicPtr
// ------------------------------------------------------------------------- //
template <class T>
class CAutoBasicPtr
{
public:
 explicit CAutoBasicPtr (T *p = NULL)
  : m_pPtr (p)
 {
 };
 
 CAutoBasicPtr (CAutoBasicPtr<T> &rhs)
  : m_pPtr (rhs.release ())
 {
 };
 
 CAutoBasicPtr<T> &operator= (CAutoBasicPtr<T> &rhs)
 {
  if (this != &rhs)
  {
   this->Reset (rhs.Release ());
  }
  return *this;
 };
 
 ~CAutoBasicPtr (void)
 {
  delete this->Get ();
 };

public:
 T &operator *() const
 {
  return *this->Get ();
 };
 
 T *Get (void) const
 {
  return this->m_pPtr;
 };
 
 T *Release (void)
 {
  T *old = this->m_pPtr;
  this->m_pPtr = NULL;
  return old;
 };
 
 void Reset (T *p = NULL)
 {
  if (this->Get () != p)
   delete this->Get ();
  this->m_pPtr = p;
 };
 
protected:
 T *m_pPtr;
};


// ------------------------------------------------------------------------- //
//  Class: CRefcountedAutoPtrRep
// ------------------------------------------------------------------------- //
template<class T, class lockT>
class CRefcountedAutoPtrRep
{
private:
 friend class CRefcountedAutoPtr <T, lockT>;

protected:
 mutable lockT m_Lock;
 CAutoBasicPtr<T> m_Ptr;
 LONG          m_nRefCount;
 
private:
 CRefcountedAutoPtrRep (T* p=NULL)
  : m_Ptr(p), m_nRefCount(0)
 {
 };

 ~CRefcountedAutoPtrRep ()
 {
 };

private:
 static CRefcountedAutoPtrRep<T,lockT>* Create (T *p);
 static CRefcountedAutoPtrRep<T,lockT>* Attach (CRefcountedAutoPtrRep<T,lockT> *&rep);
 static void Detach (CRefcountedAutoPtrRep<T,lockT> *&rep);
 static void Assign (CRefcountedAutoPtrRep<T,lockT> *&rep, CRefcountedAutoPtrRep<T,lockT> *new_rep);
};

template<class T, class lockT>
CRefcountedAutoPtrRep<T,lockT>* CRefcountedAutoPtrRep<T,lockT>::Create (T *p)
{
 CRefcountedAutoPtrRep<T,lockT> *ret = NULL;

 ret = new CRefcountedAutoPtrRep<T,lockT> (p);

 return ret;
}

template<class T, class lockT>
CRefcountedAutoPtrRep<T,lockT>* CRefcountedAutoPtrRep<T,lockT>::Attach (CRefcountedAutoPtrRep<T,lockT> *&rep)
{
 CXASSERT (rep!=NULL);
 
 CSyncGuard<lockT> g(rep->m_Lock);

 rep->m_nRefCount++;

 return rep;
}

template<class T, class lockT>
void CRefcountedAutoPtrRep<T,lockT>::Detach (CRefcountedAutoPtrRep<T,lockT> *&rep)
{
 CXASSERT (rep!=NULL);

 CRefcountedAutoPtrRep<T,lockT> *del = NULL;

 {
  CSyncGuard<lockT> g(rep->m_Lock);

  if (rep->m_nRefCount-- == 0)
   del = rep;
 }
 if (del)
  delete del;
}

template<class T, class lockT>
void CRefcountedAutoPtrRep<T,lockT>::Assign (CRefcountedAutoPtrRep<T,lockT> *&rep, CRefcountedAutoPtrRep<T,lockT> *new_rep)
{
 CXASSERT (rep!=NULL);
 CXASSERT (new_rep!=NULL);

 CRefcountedAutoPtrRep<T,lockT> *del = 0;

 {
  CSyncGuard<lockT> g(rep->m_Lock);

  del = rep;
  rep = new_rep;

  if (del->m_nRefCount-- > 0)
   return;
 }

 delete del;
}


// ------------------------------------------------------------------------- //
//  Class: CRefcountedAutoPtr
// ------------------------------------------------------------------------- //
template<class T, class lockT=CNullSync>
class CRefcountedAutoPtr
{
private:
 friend class CRefcountedAutoPtrRep <T, lockT>;

private:
 CRefcountedAutoPtrRep<T,lockT>* m_pRep;

public:
 CRefcountedAutoPtr (T* p=0)
  : m_pRep(CRefcountedAutoPtrRep<T,lockT>::Create (p))
 {
 };

 CRefcountedAutoPtr (const CRefcountedAutoPtr<T,lockT> &copy)
  : m_pRep( CRefcountedAutoPtrRep<T,lockT>::Attach ( ( (CRefcountedAutoPtr<T, lockT> &)copy) .m_pRep ) )
 {
 };

 virtual ~CRefcountedAutoPtr()
 {
  CRefcountedAutoPtrRep<T,lockT>::Detach (m_pRep);
 };

public:
 inline void operator=(const CRefcountedAutoPtr<T,lockT>& copy)
 {
  CRefcountedAutoPtr<T,lockT> &r = (CRefcountedAutoPtr<T,lockT> &)copy;

  CRefcountedAutoPtrRep<T,lockT>::Assign (m_pRep, CRefcountedAutoPtrRep<T,lockT>::Attach (r.m_pRep));
 };

 inline bool operator==(const CRefcountedAutoPtr<T,lockT>& crep) const
 {
  return (m_pRep == crep.m_pRep);
 };

 inline bool operator!=(const CRefcountedAutoPtr<T,lockT>& crep) const
 {
  return (m_pRep != crep.m_pRep);
 };
 
 inline T* operator->() const
 {
  return m_pRep->m_Ptr.Get();
 };

 inline T* Get(void) const
 {
  return m_pRep->m_Ptr.Get();
 };

 inline LONG Count(void) const
 {
  return m_pRep->m_nRefCount;
 };
};

#endif // !defined(__REFCOUNTEDAUTOPTR__H__)

Posted by 셈말짓기 :

#include <windows.h>
#include <tchar.h>

#include <map>
#include <string>
#include <iostream>

using namespace std;

class GameObject
{
public:
 virtual ~GameObject() {};
};

class SpaceShip: public GameObject
{
};

class SpaceStation: public GameObject
{
};


class Asteriod: public GameObject
{
};

class CollisionMap
{
public:
 typedef void (*HitFunctionPtr) (GameObject&, GameObject&);
public:
 typedef map<pair<string, string>, HitFunctionPtr> HitMap;

public:
 void AddEntry (const string& type1, const string& type2, HitFunctionPtr collisionFunction, bool symmetric = true);

 void RemoveEntry (const string& type1, const string& type2);

 HitFunctionPtr Lookup(const string& type1, const string& type2);

 static CollisionMap& TheCollisionMap ();

public:
 pair<string, string> MakeStringPair(const char *s1, const char *s2);

 CollisionMap () {};
 CollisionMap (const CollisionMap &) {}

public:
 HitMap map_; 

};

class RegisterCollisionFunction
{
public:
 RegisterCollisionFunction (const string& type1, const string& type2, CollisionMap::HitFunctionPtr collisionFunction, bool symetric = true)
 {
  CollisionMap::TheCollisionMap().AddEntry(type1, type2, collisionFunction, symetric);
 }
};

CollisionMap& CollisionMap::TheCollisionMap ()
{
 static CollisionMap map;

 return map;
}

inline pair<string, string> CollisionMap::MakeStringPair(const char *s1, const char *s2)
{
 return pair<string, string>(s1, s2);
}

inline void CollisionMap::AddEntry (const string& type1, const string& type2, HitFunctionPtr collisionFunction, bool symmetric)
{
 string temp1;
 string temp2;

 temp1 = "class " + type1;
 temp2 = "class " + type2;

 map_ [MakeStringPair (temp1.c_str(), temp2.c_str())] = collisionFunction;
}

inline  void CollisionMap::RemoveEntry (const string& type1, const string& type2)
{
 string temp1;
 string temp2;

 temp1 = "class " + type1;
 temp2 = "class " + type2;

 map_.erase(MakeStringPair (temp1.c_str(), temp2.c_str()));
}

inline CollisionMap::HitFunctionPtr CollisionMap::Lookup(const string& type1, const string& type2)
{
 HitMap::iterator mapEntry = map_.find ( MakeStringPair(type1.c_str(), type2.c_str()) );

 if (mapEntry == map_.end () ) return 0;

 return (*mapEntry).second;
}

void ShipShip(GameObject& shipObject1, GameObject& shipObject2)
{
 SpaceShip& ship1 = dynamic_cast<SpaceShip&> (shipObject1);
 SpaceShip& ship2 = dynamic_cast<SpaceShip&> (shipObject2);

 cout << "The space ship is colliding with a space ship" << endl;
}

void ShipAsteriod(GameObject& shipObject, GameObject& asteriodObject)
{
 SpaceShip& ship = dynamic_cast<SpaceShip&> (shipObject);
 Asteriod& asteriod = dynamic_cast<Asteriod&> (asteriodObject);

 cout << "The space ship is colliding with a asteriod" << endl;
}

void ShipSation(GameObject& shipObject, GameObject& stationObject)
{
 SpaceShip& ship = dynamic_cast<SpaceShip&> (shipObject);
 SpaceStation& station = dynamic_cast<SpaceStation&> (stationObject);

 cout << "The space ship is colliding with a space station" << endl;
}


void AsteriodAsteriod(GameObject& asteriodObject1, GameObject& asteriodObject2)
{
 Asteriod& asteriod1 = dynamic_cast<Asteriod&> (asteriodObject1);
 Asteriod& asteriod2 = dynamic_cast<Asteriod&> (asteriodObject2);

 cout << "The asteriod is colliding with a asteriod" << endl;
}

void AsteriodShip(GameObject& asteriodObject, GameObject& shipObject)
{
 Asteriod& asteriod = dynamic_cast<Asteriod&> (asteriodObject);
 SpaceShip& ship = dynamic_cast<SpaceShip&> (shipObject);

 cout << "The asteriod is colliding with a space ship" << endl;
}

void AsteriodSation(GameObject& asteriodObject, GameObject& stationObject)
{
 Asteriod& asteriod = dynamic_cast<Asteriod&> (asteriodObject);
 SpaceStation& station = dynamic_cast<SpaceStation&> (stationObject);

 cout << "The asteriod is colliding with a space staion" << endl;
}

void StationStation(GameObject& stationObject1, GameObject& stationObject2)
{
 SpaceStation& station1 = dynamic_cast<SpaceStation&> (stationObject1);
 SpaceStation& station2 = dynamic_cast<SpaceStation&> (stationObject2);

 cout << "The space station is colliding with a space station" << endl;
}

void StationShip(GameObject& stationObject, GameObject& shipObject)
{
 SpaceStation& station = dynamic_cast<SpaceStation&> (stationObject);
 SpaceShip& ship = dynamic_cast<SpaceShip&> (shipObject);

 cout << "The space staion is colliding with a space ship" << endl;
}

void StationAsteriod(GameObject& stationObject, GameObject& asteriodObject)
{
 SpaceStation& station = dynamic_cast<SpaceStation&> (stationObject);
 Asteriod& asteriod = dynamic_cast<Asteriod&> (asteriodObject);

 cout << "The space station is colliding with a asteriod" << endl;
}

void AsteriodStation(GameObject& aa, GameObject& bb)
{
 Asteriod& a = dynamic_cast<Asteriod&> (aa);
 SpaceStation& b = dynamic_cast<SpaceStation&> (bb);

 cout << "The space station is colliding with a asteriod" << endl;
}

void ProcessCollision(GameObject& object1, GameObject& object2)
{
 CollisionMap::HitFunctionPtr phf = CollisionMap::TheCollisionMap().Lookup(typeid(object1).name(), typeid(object2).name());

 if (phf)
  phf(object1, object2);
 else
 {
  cout << "Unknown object type" << endl;
 }
}

RegisterCollisionFunction cf1 ("SpaceShip", "Asteriod", &ShipAsteriod);
RegisterCollisionFunction cf2 ("SpaceShip", "SpaceStation", &ShipSation);
RegisterCollisionFunction cf3 ("SpaceShip", "SpaceShip", &ShipShip);

RegisterCollisionFunction cf4 ("Asteriod", "Asteriod", &AsteriodAsteriod);
RegisterCollisionFunction cf5 ("Asteriod", "SpaceShip", &AsteriodShip);
RegisterCollisionFunction cf6 ("Asteriod", "SpaceStation", &AsteriodSation);

RegisterCollisionFunction cf7 ("SpaceStation", "SpaceStation", &StationStation);
RegisterCollisionFunction cf8 ("SpaceStation", "SpaceShip", &StationShip);
RegisterCollisionFunction cf9 ("SpaceStation", "Asteriod", &StationAsteriod);

int _tmain(int argc, _TCHAR* argv[])
{
 GameObject* ship = new SpaceShip;
 GameObject* station = new SpaceStation;
 GameObject* asteriod = new Asteriod;


 ProcessCollision(*station,*ship);
 ProcessCollision(*ship, *ship);
 ProcessCollision(*ship, *asteriod);

 delete ship;
 delete station;
 delete asteriod;

 return 0;
}
----------------------------------------------------------------------
The space staion is colliding with a space ship
The space ship is colliding with a space ship
The space ship is colliding with a asteriod

Posted by 셈말짓기 :

#include <windows.h>
#include <tchar.h>

#include <map>
#include <string>
#include <iostream>

using namespace std;

class GameObject
{
public:
 virtual void Collide(GameObject& otherObject) = 0;
 virtual ~GameObject() {};
};

class SpaceShip: public GameObject
{
private:
 typedef void (SpaceShip::*HitFunctionPtr) (GameObject&);
 typedef map< std::string, HitFunctionPtr > HitMap;

public:
 virtual void Collide (GameObject& otherObject);
 virtual void HitSpaceShip (GameObject& spaceShip);
 virtual void HitSpaceStation (GameObject& spaceStation);
 virtual void HitAsteriod (GameObject& asteroid);

private:
 static HitFunctionPtr Lookup (const GameObject& whatWeHit);
 static HitMap* InitializeCollisionMap ();
};

class SpaceStation: public GameObject
{
private:
 typedef void (SpaceStation::*HitFunctionPtr) (GameObject&);
 typedef map<std::string, HitFunctionPtr> HitMap;
public:
 virtual void Collide (GameObject& otherObject);
 virtual void HitSpaceShip (GameObject& spaceShip);
 virtual void HitSpaceStation (GameObject& spaceStation);
 virtual void HitAsteriod (GameObject& asteroid);

private:
 static HitFunctionPtr Lookup (const GameObject& whatWeHit);
 static HitMap* InitializeCollisionMap ();
};

class Asteroid: public GameObject
{
private:
 typedef void (Asteroid::*HitFunctionPtr) (GameObject&);
 typedef map<std::string, HitFunctionPtr> HitMap;
public:
 virtual void Collide (GameObject& otherObject);
 virtual void HitSpaceShip (GameObject& spaceShip);
 virtual void HitSpaceStation (GameObject& spaceStation);
 virtual void HitAsteriod (GameObject& asteroid);

private:
 static HitFunctionPtr Lookup (const GameObject& whatWeHit);
 static HitMap* InitializeCollisionMap ();
};

SpaceShip::HitMap* SpaceShip::InitializeCollisionMap ()
{
 HitMap* phm = new HitMap;

 (*phm) ["class SpaceShip"]    = &HitSpaceShip;
 (*phm) ["class SpaceStation"] = &HitSpaceStation;
 (*phm) ["class Asteroid"]     = &HitAsteriod;

 return phm;
}

SpaceShip::HitFunctionPtr
SpaceShip::Lookup (const GameObject& whatWeHit)
{
 static auto_ptr<HitMap> collisionMap (InitializeCollisionMap () );

 HitMap::iterator mapEntry = collisionMap->find ( string (typeid (whatWeHit).name ()) );

 if (mapEntry == collisionMap->end () ) return 0;

 return (*mapEntry).second;
}

void SpaceShip::Collide (GameObject& otherObject)
{
 HitFunctionPtr hfp = Lookup (otherObject);

 if (hfp)
 {
  (this->*hfp)(otherObject);
 }
 else
 {
  cout << "Unknown object type" << endl;
 }
}

void SpaceShip::HitSpaceShip (GameObject& spaceShip)
{
 SpaceShip& ship = dynamic_cast<SpaceShip&> (spaceShip);

 cout << "The space ship is colliding with a space ship";
 cout << endl;
}

void SpaceShip::HitSpaceStation (GameObject& spaceStation)
{
 SpaceStation& station = dynamic_cast<SpaceStation&> (spaceStation);

 cout << "The space ship is colliding with a space station";
 cout << endl;
}

void SpaceShip::HitAsteriod (GameObject& obj)
{
 Asteroid& asteroid = dynamic_cast<Asteroid&> (obj);

 cout << "The space ship is colliding with a asteroid";
 cout << endl;
}

SpaceStation::HitMap* SpaceStation::InitializeCollisionMap ()
{
 HitMap* phm = new HitMap;

 (*phm) ["class SpaceShip"   ] = &HitSpaceShip;
 (*phm) ["class SpaceStation"] = &HitSpaceStation;
 (*phm) ["class Asteroid"    ] = &HitAsteriod;

 return phm;
}

SpaceStation::HitFunctionPtr
SpaceStation::Lookup (const GameObject& whatWeHit)
{
 static auto_ptr<HitMap> collisionMap (InitializeCollisionMap () );

 HitMap::iterator mapEntry = collisionMap->find ( string(typeid (whatWeHit).name ()) );

 if (mapEntry == collisionMap->end () ) return 0;

 return (*mapEntry).second;
}

void SpaceStation::Collide (GameObject& otherObject)
{
 HitFunctionPtr hfp = Lookup (otherObject);

 if (hfp)
 {
  (this->*hfp)(otherObject);
 }
 else
 {
  cout << "Unknown object type" << endl;
 }
}

void SpaceStation::HitSpaceShip (GameObject& spaceShip)
{
 SpaceShip& ship = dynamic_cast<SpaceShip&> (spaceShip);

 cout << "The space ship is colliding with a space ship";
 cout << endl;
}

void SpaceStation::HitSpaceStation (GameObject& spaceStation)
{
 SpaceStation& station = dynamic_cast<SpaceStation&> (spaceStation);

 cout << "The space ship is colliding with a space station";
 cout << endl;
}

void SpaceStation::HitAsteriod (GameObject& obj)
{
 Asteroid& asteroid = dynamic_cast<Asteroid&> (obj);

 cout << "The space ship is colliding with a asteroid";
 cout << endl;
}

Asteroid::HitMap* Asteroid::InitializeCollisionMap ()
{
 HitMap* phm = new HitMap;

 (*phm) ["class SpaceShip"   ] = &HitSpaceShip;
 (*phm) ["class SpaceStation"] = &HitSpaceStation;
 (*phm) ["class Asteroid"    ] = &HitAsteriod;

 return phm;
}

Asteroid::HitFunctionPtr
Asteroid::Lookup (const GameObject& whatWeHit)
{
 static auto_ptr<HitMap> collisionMap (InitializeCollisionMap () );

 HitMap::iterator mapEntry = collisionMap->find ( string(typeid (whatWeHit).name ()) );

 if (mapEntry == collisionMap->end () ) return 0;

 return (*mapEntry).second;
}

void Asteroid::Collide (GameObject& otherObject)
{
 HitFunctionPtr hfp = Lookup (otherObject);

 if (hfp)
 {
  (this->*hfp)(otherObject);
 }
 else
 {
  cout << "Unknown object type" << endl;
 }
}

void Asteroid::HitSpaceShip (GameObject& spaceShip)
{
 SpaceShip& ship = dynamic_cast<SpaceShip&> (spaceShip);

 cout << "The space ship is colliding with a space ship";
 cout << endl;
}

void Asteroid::HitSpaceStation (GameObject& spaceStation)
{
 SpaceStation& station = dynamic_cast<SpaceStation&> (spaceStation);

 cout << "The space ship is colliding with a space station";
 cout << endl;
}

void Asteroid::HitAsteriod (GameObject& obj)
{
 Asteroid& asteroid = dynamic_cast<Asteroid&> (obj);

 cout << "The space ship is colliding with a asteroid";
 cout << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
 SpaceShip    ship;
 SpaceStation station;
 Asteroid  asteroid;

 ship.Collide(station);
 ship.Collide(asteroid);
 ship.Collide(ship);
 ship.Collide(asteroid);

 return 0;
}
--------------------------------------------------------------------------
The space ship is colliding with a space station
The space ship is colliding with a asteroid
The space ship is colliding with a space ship
The space ship is colliding with a asteroid

Posted by 셈말짓기 :

#include <windows.h>
#include <tchar.h>

#include <typeinfo.h> // Compile Option: /GR
#include <iostream>

using namespace std;

class GameObject
{
public:
 virtual void Collide(GameObject& otherObject) = 0;
 virtual ~GameObject();
};

class SpaceShip: public GameObject
{
public:
 virtual void Collide(GameObject& otherObject);
};

class SpaceStation: public GameObject
{
public:
 virtual void Collide(GameObject& otherObject);
};


class Asteroid: public GameObject
{
public:
 virtual void Collide(GameObject& otherObject);
};

GameObject::~GameObject()
{
}

void SpaceShip::Collide(GameObject& otherObject)
{
 const type_info& objectType = typeid(otherObject);

 if(objectType == typeid(SpaceShip) )
 {
  cout << "The space ship is colliding with a space ship";
  cout << endl;
 }
 else if (objectType == typeid(SpaceStation) )
 {
  cout << "The space ship is colliding with a space station";
  cout << endl;  
 }
 else if (objectType == typeid(Asteroid) )
 {
  cout << "The space ship is colliding with a asteroid";
  cout << endl;  
 }
 else
 {
  cout << "The space ship is colliding with a unknown object";
  cout << endl;
  cout << " Shall we throw a unknown object type exception";
  cout << endl;
 }
}

void SpaceStation::Collide(GameObject& otherObject)
{
 const type_info& objectType = typeid(otherObject);

 if(objectType == typeid(SpaceShip) )
 {
  cout << "The space station is colliding with a space ship";
  cout << endl;
 }
 else if (objectType == typeid(SpaceStation))
 {
  cout << "The space station is colliding with a space station";
  cout << endl;  
 }
 else if (objectType == typeid(Asteroid))
 {
  cout << "The space station is colliding with a asteroid";
  cout << endl;  
 }
 else
 {
  cout << "The space station is colliding with a unknown object";
  cout << endl;
  cout << " Shall we throw a unknown object type exception";
  cout << endl;
 }
}

void Asteroid::Collide(GameObject& otherObject)
{
 const type_info& objectType = typeid(otherObject);

 if(objectType == typeid(SpaceShip) )
 {
  cout << "The asteroid is colliding with a space ship";
  cout << endl;
 }
 else if (objectType == typeid(SpaceStation))
 {
  cout << "The asteroid is colliding with a space station";
  cout << endl;  
 }
 else if (objectType == typeid(Asteroid))
 {
  cout << "The asteroid is colliding with a asteroid";
  cout << endl;  
 }
 else
 {
  cout << "The asteroid is colliding with a unknown object";
  cout << endl;
  cout << " Shall we throw a unknown object type exception";
  cout << endl;
 }
}

int _tmain(int argc, _TCHAR* argv[])
{
 SpaceShip       ship;
 SpaceStation    station;
 Asteroid asteroid;

 GameObject *p=&ship;

 ship.Collide(station);
 ship.Collide(asteroid);
 ship.Collide(ship);
 ship.Collide(*p);

 return 0;
}
-----------------------------------------------------------------------
The space ship is colliding with a space station
The space ship is colliding with a asteroid
The space ship is colliding with a space ship
The space ship is colliding with a space ship

Posted by 셈말짓기 :

#include <windows.h>
#include <tchar.h>

#include <typeinfo>
#include <iostream>

using namespace std;

class SpaceShip;
class SpaceStation;
class Asteriod;

class GameObject
{
public:
 virtual void Collide(GameObject& otherObject) = 0;

public:
 virtual void Collide(SpaceShip& otherObject) = 0;
 virtual void Collide(SpaceStation& otherObject) = 0;
 virtual void Collide(Asteriod& otherObject) = 0;

 virtual ~GameObject();
};

class SpaceShip: public GameObject
{
public:
 virtual void Collide(GameObject& otherObject);
public:
 virtual void Collide(SpaceShip& otherObject);
 virtual void Collide(SpaceStation& otherObject);
 virtual void Collide(Asteriod& otherObject);
};

class SpaceStation: public GameObject
{
public:
 virtual void Collide(GameObject& otherObject);
public:
 virtual void Collide(SpaceShip& otherObject);
 virtual void Collide(SpaceStation& otherObject);
 virtual void Collide(Asteriod& otherObject);
};


class Asteriod: public GameObject
{
public:
 virtual void Collide(GameObject& otherObject);
public:
 virtual void Collide(SpaceShip& otherObject);
 virtual void Collide(SpaceStation& otherObject);
 virtual void Collide(Asteriod& otherObject);
};

GameObject::~GameObject()
{
}

void SpaceShip::Collide(GameObject& otherObject)
{
 otherObject.Collide(*this);
}

void SpaceShip::Collide(SpaceShip& otherObject)
{
 cout << "The space ship is colliding with a space ship";
 cout << endl;
}

void SpaceShip::Collide(SpaceStation& otherObject)
{
 cout << "The space ship is colliding with a space station";
 cout << endl;
}

void SpaceShip::Collide(Asteriod& otherObject)
{
 cout << "The space ship is colliding with a asteriod";
 cout << endl;
}

void SpaceStation::Collide(GameObject& otherObject)
{
 otherObject.Collide(*this);
}

void SpaceStation::Collide(SpaceShip& otherObject)
{
 cout << "The space station is colliding with a space ship";
 cout << endl;
}

void SpaceStation::Collide(SpaceStation& otherObject)
{
 cout << "The space station is colliding with a space station";
 cout << endl;
}

void SpaceStation::Collide(Asteriod& otherObject)
{
 cout << "The space station is colliding with a asteriod";
 cout << endl;
}

void Asteriod::Collide(GameObject& otherObject)
{
 otherObject.Collide(*this);
}

void Asteriod::Collide(SpaceShip& otherObject)
{
 cout << "The space ship is colliding with a space ship";
 cout << endl;
}

void Asteriod::Collide(SpaceStation& otherObject)
{
 cout << "The space ship is colliding with a space station";
 cout << endl;
}

void Asteriod::Collide(Asteriod& otherObject)
{
 cout << "The space ship is colliding with a asteriod";
 cout << endl;
}

int _tmain (int argc, _TCHAR* argv[])
{
 GameObject  *p1;
 GameObject  *p2;

 SpaceShip    ship;
 SpaceStation station;
 Asteriod     asteriod;

 p1 = &ship;
 p2 = &ship;     p1->Collide(*p2);
 p2 = &station;  p1->Collide(*p2);
 p2 = &asteriod; p1->Collide(*p2);

 return 0;
}
------------------------------------------------------
The space ship is colliding with a space ship
The space station is colliding with a space ship
The space ship is colliding with a space ship

Posted by 셈말짓기 :

//////////////////////////////////////////////////////////////////////////////////////
//
// 템플릿 클래스 메소드 특화
//
//
//////////////////////////////////////////////////////////////////////////////////////
#include <string>

#include <windows.h>

template <class CharType>
class Message
{
public:
 void Print (void);
 void Set   (std::basic_string < CharType > s);

public:
 std::basic_string < CharType > text_;
};

template <class CharType>
void Message<CharType>::Set (std::basic_string < CharType > s)
{
 text_ = s;
}

template <class CharType>
void Message<CharType>::Print (void)
{
 OutputDebugStringW (text_.c_str());
}

template <>
void Message<char>::Print (void)
{
 printf (text_.c_str());
}

int _tmain(int argc, _TCHAR* argv[])
{
 Message<wchar_t> b;

 b.Set (L"bbb\r\n");
 b.Print();


 Message<char> a;

 a.Set ("aaa\r\n");
 a.Print();


 return 0;
}
--------------------------------------------------------------------------------------
aaa (콘솔창)
--------------------------------------------------------------------------------------
bbb (디버깅창)





//////////////////////////////////////////////////////////////////////////////////////
//
// 템플릿 클래스 특화 (Specialization of template class)
//
//
//////////////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <iostream>

template<class T>
class Min
{
public:
 const T& Is (const T &a, const T &b)
 {
  std::cout << "template<class T> class Min::Is ("
      << static_cast<int>(a) << ", "
      << static_cast<int>(b) << ")"
      << std::endl;

  return (a<b) ? a: b;
 }
};

template<>
class Min <char>
{
public:
 const char& Is (const char &a, const char &b)
 {
  std::cout << "template<> class Min<char>::Is ( \'"
      << a << "\', "
      << b << "\' )"
      << std::endl;

  return (a<b) ? a: b;
 }
};

int _tmain(int argc, _TCHAR* argv[])
{
 Min<int>  a;
 //Min<>     b; <- error
 Min<char> c;
 //Min<>     d; <- error

 a.Is (1,2);
 //b.Is (3,4);
 c.Is ('a','b');
 //d.Is ('c','d');

 return 0;
}
--------------------------------------------------------------------------------------
template<class T> class Min::Is (1, 2)
template<> class Min<char>::Is ( 'a', b' )





//////////////////////////////////////////////////////////////////////////////////////
//
// 함수 템플릿 특화 (Specialization of function template)
//
//
//////////////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <iostream>

template<class T>
const T& Min (const T &a, const T &b)
{
 std::cout << "template<class T> const T& Min ("
           << static_cast<int>(a) << ", "
     << static_cast<int>(b) << ")"
     << std::endl;

 return (a<b) ? a: b;
}

template<>
const char& Min <char> (const char &a, const char &b)
{
 std::cout << "template<> const char& Min <char> ( \'"
           << a << "\', "
     << b << "\' )"
     << std::endl;

 return (a<b) ? a: b;
}

int _tmain(int argc, _TCHAR* argv[])
{
 Min<int>  ( 1 ,  2 );
 Min<>     ( 3 ,  4 );
 Min<char> ('c', 'd');
 Min<>     ('a', 'b');

 return 0;
}
--------------------------------------------------------------------------------------
template<class T> const T& Min (1, 2)
template<class T> const T& Min (3, 4)
template<> const char& Min <char> ( 'c', d' )
template<> const char& Min <char> ( 'a', b' )

//
// cf>
//   함수 템플릿은 아래와 같이 정의 할 수 있지만
//   template <class T, int X>
//   void foo_func (T a)
//   {
//   }
//   아래와 같이 기본 템플릿 인수는 정의 할 수 없다.
//   template <class T, int X=0>
//   void foo_func (T a)
//   {
//   }
//   기본 템플릿 인수는 클래스 탬플릿에서만 사용이 가능하다.
//
//   또한, 부분특화 템플릿 함수는 사용 될 수 없다.
//





//////////////////////////////////////////////////////////////////////////////////////
//
// 템플릿 클래스 부분특화 (Partial specialization of template class)
//
//
//////////////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <iostream>

// partial specialization

class partial_specialization
{
public:
 partial_specialization ()
 {
  std::cout << "partial_specialization ()" << std::endl;
 }
 ~partial_specialization ()
 {
  std::cout << "~partial_specialization ()" << std::endl;
 }
};

template <class T1, class T2> class foo
{
public:
 foo ()
 {
  std::cout << "foo ()" << std::endl;
 }

 ~foo ()
 {
  std::cout << "~foo ()" << std::endl;
 }
};

template <class T1> class foo <T1, partial_specialization>
{
public:
 foo ()
 {
  std::cout << "foo() 2" << std::endl;
 }

 ~foo ()
 {
  std::cout << "~foo() 2" << std::endl;
 }
};

int _tmain(int argc, _TCHAR* argv[])
{
 foo<int, int>                    a;
 foo<int, partial_specialization> b;

 return 0;
}
--------------------------------------------------------------------------------------
foo ()
foo() 2
~foo() 2
~foo ()

Posted by 셈말짓기 :
template<
    typename output_policy,
    typename language_policy
>
class HelloWorld
  : public output_policy,
    public language_policy
{
    using output_policy::Print;
    using language_policy::Message;
 
public:
 
    //behaviour method
    void Run()
    {
        //two policy methods
        Print( Message() );
    }
 
};
 
 
#include <iostream>
 
class HelloWorld_OutputPolicy_WriteToCout
{
protected:
 
    template< typename message_type >
    void Print( message_type message )
    {
        std::cout << message << std::endl;
    }
 
};
 
 
#include <string>
 
class HelloWorld_LanguagePolicy_English
{
protected:
 
    std::string Message()
    {
        return "Hello, World!";
    }
 
};
 
class HelloWorld_LanguagePolicy_German{
protected:
 
    std::string Message()
    {
        return "Hallo Welt!";
    }
 
};
 
 
int main()
{
 
/* example 1 */
 
    typedef
        HelloWorld<
            HelloWorld_OutputPolicy_WriteToCout,
            HelloWorld_LanguagePolicy_English
        >
            my_hello_world_type;
 
    my_hello_world_type hello_world;
    hello_world.Run(); //returns Hello World!
 
 
/* example 2 
 * does the same but uses another policy, the language has changed
 */
 
    typedef
        HelloWorld<
            HelloWorld_OutputPolicy_WriteToCout,
            HelloWorld_LanguagePolicy_German
        >
            my_other_hello_world_type;
 
    my_other_hello_world_type hello_world2;
    hello_world2.Run(); //returns Hallo Welt!
}
Posted by 셈말짓기 :
// TestCPPCe.cpp : 응용 프로그램에 대한 진입점을 정의합니다.
//

#include "stdafx.h"
#include "TestCPPCe.h"
#include <tchar.h>
#include <windows.h>
#include <commctrl.h>


////////////////////////////////////////////////////////////////////////
template <typename T>
class RefObjectA
{
public:
 typedef void (T::*ref_object_method_ptr) (void);

 T                     *_ref_object_instance;
 ref_object_method_ptr  _ref_object_method;

public:
 void setInstance (T *instance, ref_object_method_ptr object_method)
 {
  _ref_object_instance = instance;
  _ref_object_method   = object_method;
 }

public:
 void test (void)
 {
  OutputDebugString (_T("===================================================\r\n"));
  OutputDebugString (_T("RefObjectA<T>::test()\r\n"));
  OutputDebugString (_T("===================================================\r\n"));

  (_ref_object_instance->*_ref_object_method) ();

  OutputDebugString (_T("===================================================\r\n"));
  OutputDebugString (_T("\r\n"));
  OutputDebugString (_T("\r\n"));
 }
};
////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////
template <typename T>
class RefObjectB
{
public:
 typedef void (T::*ref_object_method_ptr) (void);

 T                     &_ref_object_instance;
 ref_object_method_ptr  _ref_object_method;

 RefObjectB (T &instance, ref_object_method_ptr object_method);
 void test  (void);
};

template <typename T>
RefObjectB<T>::RefObjectB (T &instance, ref_object_method_ptr object_method) :
 _ref_object_instance  (instance),
 _ref_object_method    (object_method)
{
}

template <typename T>
void RefObjectB<T>::test (void)
{
 OutputDebugString (_T("===================================================\r\n"));
 OutputDebugString (_T("RefObjectB<T>::test()\r\n"));
 OutputDebugString (_T("===================================================\r\n"));

 (_ref_object_instance.*_ref_object_method) ();
 (_ref_object_instance.*_ref_object_method) ();
 (_ref_object_instance.*_ref_object_method) ();

 OutputDebugString (_T("===================================================\r\n"));
 OutputDebugString (_T("\r\n"));
 OutputDebugString (_T("\r\n"));
}
////////////////////////////////////////////////////////////////////////



////////////////////////////////////////////////////////////////////////
class Object
{
public:
 RefObjectA <Object> _friend_object1;
 RefObjectB <Object> _friend_object2;
 int                 _test_value;


 void init (void)
 {
  _friend_object1.setInstance (this, &Object::test);  
 }

 Object();
 void test(void);
};

Object::Object () :
 _test_value(0),
 _friend_object2(*this, &Object::test)
{
}

void Object::test (void)
{
 TCHAR message[32];

 _test_value++;
 
 _stprintf (message, _T("Object::test() = %d\r\n"), _test_value);
 OutputDebugString (message);  
}

////////////////////////////////////////////////////////////////////////


int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPTSTR    lpCmdLine,
                   int       nCmdShow)
{
 Object obj;

 obj.init ();

 obj._friend_object1.test ();
 obj._friend_object2.test ();


 return 0;
}

----------------------------------------------------------------------


모듈 로드: TestCPPCe.exe
모듈 로드: coredll.dll
===================================================
RefObjectA<T>::test()
===================================================
Object::test() = 1
===================================================


===================================================
RefObjectB<T>::test()
===================================================
Object::test() = 2
Object::test() = 3
Object::test() = 4
===================================================


'[cf56df16] TestCPPCe.exe' 프로그램이 0 (0x0) 코드에서 끝났습니다

Posted by 셈말짓기 :