您将如何修复此代码?

template <typename T> void closed_range(T begin, T end)
{
    for (T i = begin; i <= end; ++i) {
        // do something
    }
}
  • T 被限制为整数类型,可以是这些类型中更宽的类型,可以是有符号或无符号
  • begin 可以是 numeric_limits<T>::min()
  • end 可以是numeric_limits<T>::max()(在这种情况下++i会在上面的代码中溢出)

  • 我有几种方法,但没有一种是我真正喜欢的。

    最佳答案

    也许,

    template <typename T> void closed_range(T begin, const T end)
        if (begin <= end) {
            do {
                // do something
            } while (begin != end && (++begin, true));
        }
    }
    

    诅咒,我的第一次尝试是错误的,上面的修复并不像我希望的那么漂亮。怎么样:
    template <typename T> bool advance(T &value) { ++value; return true; }
    
    template <typename T> void closed_range(T first, const T last)
        if (first <= last) {
            do {
                // do something
            } while (first != last && advance(first));
        }
    }
    

    即使 T 不是整数类型, std::advance 也没有歧义,因为 std::advance 有 2 个参数。因此,如果出于某种原因您想要一个封闭范围的迭代器,模板也可以与例如随机访问迭代器一起使用。

    或者一些集合论怎么样?显然,如果您只在一个封闭范围内编写一个循环,这将是巨大的矫枉过正,但如果您想做很多事情,那么它会使循环代码正确无误。不确定效率:在一个非常紧凑的循环中,您可能需要确保对 endof 的调用被提升:
    #include <limits>
    #include <iostream>
    
    template <typename T>
    struct omega {
        T val;
        bool isInfinite;
        operator T() { return val; }
        explicit omega(const T &v) : val(v), isInfinite(false) { }
        omega &operator++() {
            (val == std::numeric_limits<T>::max()) ? isInfinite = true : ++val;
            return *this;
        }
    };
    
    template <typename T>
    bool operator==(const omega<T> &lhs, const omega<T> &rhs) {
        if (lhs.isInfinite) return rhs.isInfinite;
        return (!rhs.isInfinite) && lhs.val == rhs.val;
    }
    template <typename T>
    bool operator!=(const omega<T> &lhs, const omega<T> &rhs) {
        return !(lhs == rhs);
    }
    
    template <typename T>
    omega<T> endof(T val) {
        omega<T> e(val);
        return ++e;
    }
    
    template <typename T>
    void closed_range(T first, T last) {
        for (omega<T> i(first); i != endof(last); ++i) {
            // do something
            std::cout << i << "\n";
        }
    }
    
    int main() {
        closed_range((short)32765, std::numeric_limits<short>::max());
        closed_range((unsigned short)65533, std::numeric_limits<unsigned short>::max());
        closed_range(1, 0);
    }
    

    输出:
    32765
    32766
    32767
    65533
    65534
    65535
    

    omega<T> 对象上使用其他运算符时要小心。我只为演示实现了绝对最小值,并且 omega<T> 隐式转换为 T ,因此您会发现您可以编写可能丢弃 omega 对象“无限性”的表达式。您可以通过声明(不一定定义)一整套算术运算符来解决这个问题;或者如果 isInfinite 为真,则在转换中抛出异常;或者只是不要担心,因为您不会意外地将结果转换回 omega,因为构造函数是显式的。但例如,omega<int>(2) < endof(2) 为真,但 omega<int>(INT_MAX) < endof(INT_MAX) 为假。

    关于c++ - 在封闭范围内循环,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2457389/

    10-09 14:09