воскресенье, 29 июля 2018 г.

Обработка перечислений (enum)

  Код с применением switch

 /* handler.h */    
   
 #ifndef HANDLER_H  
 #define HANDLER_H  
   
 typedef enum {    
   RED,    
   GREEN,    
   BLUE,    
   MAX_COLOR;  
 } COLOR;   
   
 bool handleRedColor(unsigned int nIntensity_);  
 bool handleGreenColor(unsigned int nIntensity_);  
 bool handleBlueColor(unsigned int nIntensity_);  
 bool handleColor(COLOR oTypeColor_, unsigned int nIntensity_);  
   
 #endif /* HANDLER_H */  
 /* handler.с */  
   
 #include <handler.h>  
   
 bool handleRedColor(unsigned int nIntensity_  ) { /* ... */ return true; }  
 bool handleGreenColor(unsigned int nIntensity_) { /* ... */ return true; }  
 bool handleBlueColor(unsigned int nIntensity_ ) { /* ... */ return true; }  
   
 bool handleColor(COLOR oTypeColor_, unsigned int nIntensity_)  
 {  
   switch ( oTypeColor_ ) {  
    case RED   : return handleRedColor(nIntensity_);  
    case GREEN : return handleGreenColor(nIntensity_);  
    case BLUE  : return handleBlueColor(nIntensity_);  
   }  
   return false;  
 }  
Преимущества:
  • в функции  handleColor(..) не нужно проверять входной параметр oTypeColor на валидность, так как вызов функции-обработчика будет производится только для валидных значений, а для всех невалидных будет возвращаться false
  • при изменении enum COLOR будет выводиться предупреждение компилятора о том, что в switch не обрабатывается соответствцющий элемент (только gcc ?)
Недостатки:
  • при изменении enum нужно править код, обрабатываемый switch (код вызова обработчиков)

Код без применением switch

 /* handler.h */    
   
 #ifndef HANDLER_H  
 #define HANDLER_H  
   
 typedef enum {    
   RED,    
   GREEN,    
   BLUE,    
   MAX_COLOR;  
 } COLOR;   
   
 bool handleRedColor(unsigned int nIntensity_);  
 bool handleGreenColor(unsigned int nIntensity_);  
 bool handleBlueColor(unsigned int nIntensity_);  
 bool handleColor(COLOR oTypeColor_, unsigned int nIntensity_);  
   
 #endif /* HANDLER_H */  
 /* handler.c */  

 #include <handler.h>
   
 bool handleRedColor(unsigned int nIntensity_  ) { /* ... */ return true; }  
 bool handleGreenColor(unsigned int nIntensity_) { /* ... */ return true; }  
 bool handleBlueColor(unsigned int nIntensity_ ) { /* ... */ return true; }  
   
 typedef bool(HANDLER_COLOR) (unsigned int nIntensity_);  
   
 static HANDLER_COLOR aHandlerList[MAX_COLOR] =  
 {  
    handleRedColor,  
    handleGreenColor,  
    handleBlueColor   
 };  
   
   
 bool handleColor(COLOR oTypeColor_, unsigned int nIntensity_)  
 {  
    if ( oTypeColor_ < 0            ) { return false; }  
    if ( oTypeColor_ >= __MAX_COLOR ) { return false; }  
    return aHandlerList[oTypeColor_](nIntensity_);  
 }  
Преимущества:
  • при изменении enum не нужно править код вызова обработчиков
Недостатки:
  • функции  handleColor(..) нужно проверять входной параметр oTypeColor_на валидность
  • вручную отслеживать соответствие наличия и порядка следования массива обработчиков  enum-у COLOR

Код без применением switch с использованием X-Macros


https://stackoverflow.com/questions/6635851/real-world-use-of-x-macros
https://en.wikipedia.org/wiki/X_Macro
 /* handler.h */    
     
 #ifndef HANDLER_H   
 #define HANDLER_H   
    
 #define HANDLER_TABLE               \  
     ENTRY(RED  , handleRedColor  )  \  
     ENTRY(GREEN, handleGreenColor)  \  
     ENTRY(BLUE , handleBlueColor )   
    
 typedef enum {  
  #define ENTRY(OBJ_TYPE, OBJ_HANDLER) OBJ_TYPE,  
   HANDLER_TABLE  
  #undef ENTRY  
   MAX_COLOR;   
 } COLOR;   
   
 bool handleRedColor(unsigned int nIntensity_);  
 bool handleGreenColor(unsigned int nIntensity_);  
 bool handleBlueColor(unsigned int nIntensity_);  
   
 bool handleColor(COLOR oTypeColor_, unsigned int nIntensity_);  
   
 #endif /* HANDLER_H */  
 /* handler.c */  
   
 #include <handler.h>

 bool handleRedColor(unsigned int nIntensity_  ) { /* ... */ return true; }  
 bool handleGreenColor(unsigned int nIntensity_) { /* ... */ return true; }  
 bool handleBlueColor(unsigned int nIntensity_ ) { /* ... */ return true; }  
   
 typedef bool(HANDLER_COLOR) (unsigned int nIntensity_);  
   
 static HANDLER_COLOR aHandlerList[MAX_COLOR] =  
 {  
   #define ENTRY(OBJ_TYPE, OBJ_HANDLER) OBJ_HANDLER,  
     HANDLER_TABLE  
   #undef ENTRY  
 };  
   
 bool handleColor(COLOR oTypeColor_, unsigned int nIntensity_)  
 {  
    if ( oTypeColor_ < 0          ) { return false; }  
    if ( oTypeColor_ >= MAX_COLOR ) { return false; }  
    return aHandlerList[oTypeColor_](nIntensity_);  
 }  
Преимущества:
  • при изменении enum не нужно править код вызова обработчиков
  • очень просто отслеживать пару элемент - обработчик
Недостатки:
  • в функции  handleColor(..) нужно проверять входной параметр oTypeColor на валидность

воскресенье, 22 июля 2018 г.

Неопределённый результат: i = i++

http://alenacpp.blogspot.com/2005/11/sequence-points.html
https://habr.com/post/216189/
https://ru.stackoverflow.com/questions/590020/О-порядке-вычисления-выражений

Согласно стандарту C++ порядок вычисления аргументов функции не специфицирован, что означает, что компиляторы могут выбрать любой порядок вычисления аргументов.
Из стандарта C++ (1.9 Program execution)
"3 Certain other aspects and operations of the abstract machine are described in this International Standard as unspecified
(for example, order of evaluation of arguments to a function)."

§5/4 Стандарт говорит:
"Между двумя точками следования скалярный объект должен менять хранимое значение при вычислении выражения не более одного раза."

ТОЧКИ СЛЕДОВАНИЯ НЕАКТУАЛЬНЫ ДЛЯ СОВРЕМЕННОГО СТАНДАРТА С++ !!!