【问题标题】:Is there a modern way to enclose a int to a range?有没有一种现代方法可以将一个 int 包含在一个范围内?
【发布时间】:2021-08-19 09:11:23
【问题描述】:

我会澄清的。我想用下一个在 [min,max] 范围内创建一个 int 变量 属性:

  1. 它必须支持 int 的“+”(加号)和“-”(减号)操作。
  2. 任何大于 max 的值都应该循环到 [min + 余数。
  3. 任何小于 min 的值都应循环到 max - 余数]。

示例:

int a in range (2,7);
a = 3;
a = a + 3; // a is 6 now
a = a + 1; // a is 7 now
a = a + 1; // a is greater than 7 so we loop to 2 a = 2
a = a - 3; // shoul be 2 - 3 = -1 but insted will be 5 (2 - 1 -> 7 - 2 -> 5)

我知道我可以用 mod(又名% 运算符)编写上限。但我认为代码将难以阅读。

或者使用 if 语句。但随后性能会下降。

所以它有一些现代的方式来做到这一点?一些std:: 解决方案?还是很酷的语法?

【问题讨论】:

    标签: c++ c++17 c++20


    【解决方案1】:
    template<class T, T min, T max>
    struct bounded_value {
      static_assert(min <= max);
    private:
      T t;
    public:
      explicit operator T() const& { return t; }
      explicit operator T() && { return std::move(t); }
    
      inline static constexpr T delta = max-min;
    
      bounded_value& operator+=( bounded_value const& o ) & {
        t += o.t;
        if (t >= max)
          t -= delta;
        else if (t < min)
          t += delta;
        return *this;
      }
      bounded_value& operator-=( bounded_value const& o ) & {
        t -= o.t;
        if (t >= max)
          t -= delta;
        else if (t < min)
          t += delta;
        return *this;
      }
      static T bound( T in ) {
        if (in > max)
        {
          std::size_t count = (max-in)/delta;
          in -= delta * count;
        }
        else if (in <= min)
        {
          std::size_t count = (min-in)/delta;
          in += delta * count;
        }
        return in;
      }
      bounded_value& operator*=( bounded_value const& o ) & {
        t = bound(t * o.t);
        return *this;
      }
      bounded_value& operator/=( bounded_value const& o ) & {
        t = bound(t / o.t);
        return *this;
      }
    
      friend bounded_value operator+(bounded_value lhs, bounded_value const& rhs)
      {
        lhs += rhs;
        return lhs;
      }
      friend bounded_value operator-(bounded_value lhs, bounded_value const& rhs)
      {
        lhs -= rhs;
        return lhs;
      }
      friend bounded_value operator*(bounded_value lhs, bounded_value const& rhs)
      {
        lhs *= rhs;
        return lhs;
      }
      friend bounded_value operator/(bounded_value lhs, bounded_value const& rhs)
      {
        lhs /= rhs;
        return lhs;
      }
    
      bounded_value& operator++(){ *this += 1; return *this; }
      bounded_value operator++(int){ auto tmp = *this; ++*this; return tmp;}
      bounded_value& operator--(){ *this -= 1; return *this; }
      bounded_value operator--(int){ auto tmp = *this; ++*this; return tmp;}
    
      auto operator<=>(bounded_value const&) const =default;
      bool operator==(bounded_value const&) const =default;
    
      bounded_value( T in ):t( bound(std::move(in)) ) {}
      bounded_value():t(min) {}
      ~bounded_value()=default;
      bounded_value( bounded_value const& )=default;
      bounded_value( bounded_value && )=default;
      bounded_value& operator=( bounded_value const& )=default;
      bounded_value& operator=( bounded_value && )=default;
    };
    

    这是一个很快的。

    Live example.

    我可能应该在+- 上添加std::ptrdiff_t 重载,以支持bounded_value&lt;Foo*, globalbuf+10, globalbuf+100&gt;

    请注意,这假设对有界值的操作不会溢出/低于底层T

    在执行+- 时,最多进行两次检查,一次减法/加法,以使其保持在范围内;没有分裂。在进行*/ 时,最多进行两次检查,一次除法、一次乘法和一次加法/减法。

    【讨论】:

    • 我相信这甚至适用于大小小于int 的整数数据类型的“溢出”,因为在算术运算期间会提升整数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多