【问题标题】:C++ data type with custom range [0, 64]?具有自定义范围 [0, 64] 的 C++ 数据类型?
【发布时间】:2021-01-05 09:29:37
【问题描述】:

我寻找了类似的问题,但没有找到我的答案。

基本上,我需要声明/定义一个特定范围从 0 到包括 64 的变量。 我使用枚举吗?一个结构?我可以在声明变量时这样做吗? 我想在结构中使用它。

当然,我可以编写一些 if/else 检查,但必须有一种更简单的方法,而不需要创建数组 [64]。

【问题讨论】:

  • 是否包含 64?如果没有,您可以使用位域。
  • 有定宽integer types
  • 0 和 64 都包括在内。如果有帮助,它应该代表 Minecraft 中的库存堆栈。最大堆栈大小为 64。0 为空。
  • 这取决于你想如何使用它以及你为什么想要它?例如是为了节省空间还是检测超出范围的错误?

标签: c++ struct custom-data-type


【解决方案1】:

如果你只需要一个受约束的整数,你可以在构造函数中检查范围。像这样:

#include <stdexcept>

template<int max>
class ConstrInt {
public:
   ConstrInt(int val) {
      if (val > max)
         throw std::out_of_range("");
      m_val = val; 
   }

   int value() const {
      return m_val;
   }
private:
   int m_val;
};



int main(){
   ConstrInt<64> a{1};
   auto aa = a.value();
   ConstrInt<64> b{65};  // exception for > 64
}

【讨论】:

  • 其实我希望我可以使用 char(更小)并将其限制为 [0, 64]。
  • 我不能在不手动拼出每个值的情况下定义一个范围从 0 到包括 64 的枚举吗?
  • @Kampfkeksgeschwader:枚举的最小范围已经四舍五入到刚好低于 2 的下一个幂(即 127),而且您还会错过整数类型的算术运算。
【解决方案2】:

我是否使用枚举?

我看不出它有什么用。

一个结构体?

如果你想定义一个自定义的数据类型,那么就想定义一个类(结构就是类)。

声明变量时可以这样做吗?

如果你的意思是这样,你可以定义自定义数据类型的变量。

当然,我可以编写一些 if/else 检查,但必须有一种更简单的方法,而不需要创建数组 [64]。

没有必要仅仅为了检查一个值是否在一个范围内而创建一个数组。这是一个示例检查:

if (x >= 0 && x <= 64)

【讨论】:

    【解决方案3】:

    您可以定义一个带有unsigned char 的类,并使其像内置的无符号整数类型一样环绕,这样0 - 1 会产生64,而64 + 1 会产生0

    例子:

    template<unsigned End = 64>
    class usmall {
    public:
        // implicit conversion constructor, making sure the value is in the range [0, End]
        usmall(unsigned char v = 0) : data(v % (End + 1)) {}
    
        // implicit user defined conversion operator
        operator unsigned char () const { return data; }
    
        // pre increment and decrement operators
        usmall& operator++() { if(data==End) data = 0; else ++data; return *this; }
        usmall& operator--() { if(data==0) data = End; else --data; return *this; }
    
        // post increment and decrement operators
        usmall operator++(int) { usmall rv(*this); ++*this; return rv; }
        usmall operator--(int) { usmall rv(*this); --*this; return rv; }
    
        // common arithmetic operators
        usmall& operator+=(const usmall& rhs) {
            data = (data + rhs.data) % (End + 1);
            return *this;
        }
        
        usmall& operator-=(const usmall& rhs) {
            if(data < rhs.data) data += (End + 1);
            data -= rhs.data;
            return *this;
        }
    
        usmall& operator*=(const usmall& rhs) {
            data = (data * rhs.data) % (End + 1);
            return *this;
        }
        
        usmall& operator/=(const usmall& rhs) {
            data /= rhs.data;
            return *this;
        }
    
    private:
        unsigned char data;
    };
    
    // free arithmetic functions
    template<unsigned End>
    auto operator+(const usmall<End>& lhs, const usmall<End>& rhs) {
        usmall rv(lhs);
        rv += rhs;
        return rv;
    }
    
    template<unsigned End>
    auto operator-(const usmall<End>& lhs, const usmall<End>& rhs) {
        usmall rv(lhs);
        rv -= rhs;
        return rv;
    }
    
    template<unsigned End>
    auto operator*(const usmall<End>& lhs, const usmall<End>& rhs) {
        usmall rv(lhs);
        rv *= rhs;
        return rv;
    }
    
    template<unsigned End>
    auto operator/(const usmall<End>& lhs, const usmall<End>& rhs) {
        usmall rv(lhs);
        rv /= rhs;
        return rv;
    }
    

    例子:

    #include <iostream>
    
    int main() {
        usmall foo = 3;
        usmall bar = 30;
        usmall baz = foo * bar;
        std::cout << static_cast<unsigned>(baz) << '\n'; // prints 25
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-07
      • 1970-01-01
      • 1970-01-01
      • 2016-08-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多