有没有办法将此“ for i” c ++预处理程序宏转换为现代C ++(11+)?

bin*_*rez 4 c++ c-preprocessor

我正在寻找一种以更现代的方式替换此C ++预处理程序宏的方法。

#define fori(FORI_TYPE, FORI_FROM, FORI_TO) \
            for(FORI_TYPE i{FORI_FROM}; \
            ((FORI_FROM) < (FORI_TO)) ? (i < (FORI_TO)) : (i > (FORI_TO)); \
            ((FORI_FROM) < (FORI_TO)) ? ++i : --i )
Run Code Online (Sandbox Code Playgroud)

理想情况下,我将能够摆脱所有?运算符(在这里constexpr有用吗?)并且“ fori”不会像处理处理器版本(?运算符的评估)那样产生任何开销成本。此外,键入安全。

用法示例:

fori(size_t, 0, n)
{
    cout << i << endl;
}
Run Code Online (Sandbox Code Playgroud)

Lig*_*ica 7

对于它的价值,您总是需要知道要迭代哪个方向,因此您不能摆脱那些开销。也就是说,通过远离宏,您至少可以使优化更容易(部分通过提供输入const以促进重复/相似条件在其上的折叠,部分通过预先计算“步距”以消除其中的某些条件)完全)。

就宏而言,这还算不错(尽管它可能使用一()两个)。

真正“现代”的事情是使用计数迭代器与之相关的东西irange

例如,天真地调整Neil的代码以提供自动步方向检测:

#include <iostream>

template <class T>
class range
{
private:
    class iter
    {
    private:
        T at, step;
    public:
        iter(T at, T step) : at(at), step(step) {}
        bool operator!=(iter const& other) const { return at != other.at; }
        T const& operator*() const { return at; }
        iter& operator++() { at += step; return *this; }
    };

    T begin_val;
    T end_val;
    T step_val;

public:

    range(const T begin_val, const T end_val)
        : begin_val(begin_val)
        , end_val(end_val)
        , step_val(begin_val > end_val ? -1 : 1)
    {}

    iter begin() { return iter(begin_val, step_val); }
    iter end() { return iter(end_val, step_val); }
};

int main()
{
   for (auto i : range<unsigned>(42, 10))
      std::cout << i << ' ';
   std::cout << '\n';
}

// Output: 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 
Run Code Online (Sandbox Code Playgroud)

现场演示

或者,坦率地说,您可以编写以下代码并完成操作:

#include <iostream>

int main()
{
   for (unsigned int i = 42; i > 10; --i)
      std::cout << i << ' ';
   std::cout << '\n';
}

// Output: 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 
Run Code Online (Sandbox Code Playgroud)

现场演示

每个人都会明白这一点;无需技巧。

无论哪种情况,尽管有上面的示例,我实际上建议不要为此使用未签名的类型