型情報を値に埋め込む実装を追加

以前のエントリで言っていた型情報を値に埋め込む件を試してみました。
次のようなイメージの実装になっています。

enum Type{
  TYPE_NULL = 0,
  TYPE_BASE = 1,
  TYPE_INT = 2,
  TYPE_FLOAT = 3,
  
  TYPE_MASK = (1<<1) | (1<<0),
  TYPE_SHIFT = 2
};

class Value{

  union{
    int_t value_;
    float_t fvalue_;
    void* pvalue_;
  };
  
public:
  
  void set_null(){
    value_ = TYPE_NULL;
  }

  void set_p(void* p){
    union{
      int_t value;
      void* pvalue;
    } u;
    u.pvalue = p;
    u.value |= TYPE_BASE;
    value_ = u.value;
  }

  void set_i(int_t v){
    value_ = (v<<TYPE_SHIFT) | TYPE_INT;
  }

  void set_f(float_t v){
    union{
      int_t value;
      float_t fvalue;
    } u;
    u.fvalue = v;
    u.value = (u.value & ~TYPE_MASK) | TYPE_FLOAT;
    value_ = u.value;
  }

  int_t type() const{
    return value_ & TYPE_MASK; 
  }
  
  int_t ivalue() const{ 
    return value_ >> TYPE_SHIFT; 
  }
  
  float_t fvalue() const{ 
    union{
      int_t value;
      float_t fvalue;
    } u;
    u.value = (value_ & ~TYPE_MASK);
    return u.fvalue;
  }
  
  void* pvalue() const{
    union{
      int_t value;
      void* pvalue;
    } u;
    u.value = (value_ & ~TYPE_MASK);
    return u.pvalue; 
  }
  
};

これにより実行速度、メモリ使用量ともに若干上がるはずですが、移植性と、整数、浮動少数点数の精度が2bitほど犠牲になります。
それは大抵の環境、大抵の状況では困ることにはならないと思いますが、デフォルトは埋め込まない実装にしてあります。
XTAL_USE_COMPRESSED_ANY をマクロ定義してコンパイルするとこの実装に切り替わります。