伪代码也能跑——for

· · Tech. & Eng.

本人很闲,这个想法是我自己想出的,如有雷同,那我就很唐。

怎么错别字那么多(

不保证包对,但是对于遍历整数应该是包对的。如果发现错误,欢迎留言,若没有更正,可以私信作者。

使用方法

for (<type> <name> : <begin> to <end>),定义一个 <type> <name> 变量并遍历 [<begin>, <end>]

for (<type> <name> : <begin> until <end>),定义一个 <type> <name> 变量并遍历 [<begin>, <end>)

down_todown_until 同理,只不过是 ++ 换为了 --

支持 to, up_to, down_to 其中 up_toto 相同。支持 until, up_until, down_until 其中 up_untiluntil 相同。

若没有明确规定不使用 safe 版的 todown_to 实现,默认使用 safe 版,safe 版会多占用若干空间并多一倍的比较常数。

同时支持在上面的那六个宏标识后接 _safe_fast 明确指定使用那一版,例如 to_fast 明确规定使用 fast 版实现

注意事项

如果 <end> 是一个带 operator, 的表达式,需要用小括号括一下 <end>

为了符合有关 for: 有关 operator!=(itreator) 的要求,fast 版实现中 to 中的 <end> 需要对 operator++() 有定义,同理 down_to 中的 <end> 需要对 operator--() 有定义。

until 系列仅有 fast 版实现,因为 <end> 不涉及 ++-- 操作。

实现方法

tountil 等替换为 ,标识符,,标识符和左参先结合然后和右参结合,生成一个可遍历的 range,使用 c++14range-for 对其遍历。

代码

想用的话可以吧这个东西粘入某一个文件中,如 pseudo_code_extend.h,使用 #include "pseudo_code_extend.h",或者直接粘在代码开始的位置。

可以使用 #define __UNUSE__PSEUDO_CODE_EXTENDS__ 明确禁止使用这些可能和变量冲突的宏表示。

可以使用 #define __UNUSE__SAFE_FOR_LOOP__#define __USING__SAFE_FOR_LOOP__ 0 明确规定 to, up_to, down_to 使用 fast 版实现。

#include <type_traits>
#ifdef __UNUSE__SAFE_FOR_LOOP__
#define __USING__SAFE_FOR_LOOP__ 0
#endif
#ifndef __USING__SAFE_FOR_LOOP__
#define __USING__SAFE_FOR_LOOP__ 1
#endif
#ifndef __UNUSE__PSEUDO_CODE_EXTENDS__
#define __USING__PSEUDO_CODE_EXTEND__OF__FOR_LOOP__
#endif
namespace __pseudo_code_extend {
    namespace __for_loop {
        namespace safe { // safe for only to mod
            struct fft_translator {};
            struct ffdt_translator {};
            template<typename T>
            struct fft_range {
                struct iterator {
                    T x;
                    bool e;
                    const fft_range *base;
                    const T &operator*() const { return x; }
                    bool operator!=(const iterator &b) const { return x != b.x || e != b.e; }
                    iterator &operator++() {
                        if (x == base->e) e = true;
                        else ++x;
                        return *this;
                    }
                };
                T b, e;
                iterator begin() const { return {b, false, this}; }
                iterator end() const { return {e, true, this}; }
            };
            template<typename T2, typename T>
            fft_range<T2> operator,(fft_range<T2> ans, T &&e) {
                ans.e = e;
                return ans;
            }
            template<typename T>
            fft_range<std::decay_t<T> > operator,(T &&b, fft_translator) {
                fft_range<std::decay_t<T> > ans;
                ans.b = b;
                return ans;
            }
            template<typename T>
            struct ffdt_range {
                struct iterator {
                    T x;
                    bool e;
                    const ffdt_range *base;
                    const T &operator*() const { return x; }
                    bool operator!=(const iterator &b) const { return x != b.x || e != b.e; }
                    iterator &operator++() {
                        if (x == base->e) e = true;
                        else --x;
                        return *this;
                    }
                };
                T b, e;
                iterator begin() const { return {b, false, this}; }
                iterator end() const { return {e, true, this}; }
            };
            template<typename T2, typename T>
            ffdt_range<std::decay_t<T2> > operator,(ffdt_range<T2> ans, T &&e) {
                ans.e = e;
                return ans;
            }
            template<typename T>
            ffdt_range<std::decay_t<T> > operator,(T &&b, ffdt_translator) {
                ffdt_range<std::decay_t<T> > ans;
                ans.b = b;
                return ans;
            }
        }
        namespace fast {
            struct fft_translator {};
            struct ffu_translator {};
            struct ffdt_translator {};
            struct ffdu_translator {};
            template<typename T>
            struct fft_range {
                struct iterator {
                    T x;
                    const T &operator*() const { return x; }
                    bool operator!=(const iterator &b) const { return x != b.x; }
                    iterator &operator++() { ++x; return *this; }
                };
                T b, e;
                iterator begin() const { return {b}; }
                iterator end() const { return {e}; }
            };
            template<typename T>
            struct ffu_range_begin { T b; };
            template<typename T2, typename T>
            fft_range<T2> operator,(fft_range<T2> ans, T &&e) {
                ++(ans.e = e);
                return ans;
            }
            template<typename T>
            fft_range<std::decay_t<T> > operator,(T &&b, fft_translator) {
                fft_range<std::decay_t<T> > ans;
                ans.b = b;
                return ans;
            }
            template<typename T2, typename T>
            fft_range<T2> operator,(ffu_range_begin<T2> ans_u, T &&e) {
                fft_range<T2> ans;
                ans.b = ans_u.b;
                ans.e = e;
                return ans;
            }
            template<typename T>
            ffu_range_begin<std::decay_t<T> > operator,(T &&b, ffu_translator) {
                return {b};
            }
            template<typename T>
            struct ffdt_range {
                struct iterator {
                    T x;
                    const T &operator*() const { return x; }
                    bool operator!=(const iterator &b) const { return x != b.x; }
                    iterator &operator++() { --x; return *this; }
                };
                T b, e;
                iterator begin() const { return {b}; }
                iterator end() const { return {e}; }
            };
            template<typename T>
            struct ffdu_range_begin { T b; };
            template<typename T2, typename T>
            ffdt_range<T2> operator,(ffdt_range<T2> ans, T &&e) {
                --(ans.e = e);
                return ans;
            }
            template<typename T>
            ffdt_range<std::decay_t<T> > operator,(T &&b, ffdt_translator) {
                ffdt_range<std::decay_t<T> > ans;
                ans.b = b;
                return ans;
            }
            template<typename T2, typename T>
            ffdt_range<T2> operator,(ffdu_range_begin<T2> ans_u, T e) {
                ffdt_range<T2> ans;
                ans.b = ans_u.b;
                ans.e = e;
                return ans;
            }
            template<typename T>
            ffdu_range_begin<std::decay_t<T> > operator,(T &&b, ffdu_translator) {
                return {b};
            }
        }
    }
}
#ifdef __USING__PSEUDO_CODE_EXTEND__OF__FOR_LOOP__
#if __USING__SAFE_FOR_LOOP__
#define to , __pseudo_code_extend::__for_loop::safe::fft_translator() ,
#define up_to to
#define down_to , __pseudo_code_extend::__for_loop::safe::ffdt_translator() ,
#else
#define to , __pseudo_code_extend::__for_loop::fast::fft_translator() ,
#define up_to to
#define down_to , __pseudo_code_extend::__for_loop::fast::ffdt_translator() ,
#endif
#define until , __pseudo_code_extend::__for_loop::fast::ffu_translator() ,
#define up_until until
#define down_until , __pseudo_code_extend::__for_loop::fast::ffdu_translator() ,
#define to_safe , __pseudo_code_extend::__for_loop::safe::fft_translator() ,
#define until_safe , __pseudo_code_extend::__for_loop::fast::ffu_translator() ,
#define up_to_safe to_safe
#define up_until_safe until_safe
#define down_to_safe , __pseudo_code_extend::__for_loop::safe::ffdt_translator() ,
#define down_until_safe , __pseudo_code_extend::__for_loop::fast::ffdu_translator() ,
#define to_fast , __pseudo_code_extend::__for_loop::fast::fft_translator() ,
#define until_fast , __pseudo_code_extend::__for_loop::fast::ffu_translator() ,
#define up_to_fast to_fast
#define up_until_fast until_fast
#define down_to_fast , __pseudo_code_extend::__for_loop::fast::ffdt_translator() ,
#define down_until_fast , __pseudo_code_extend::__for_loop::fast::ffdu_translator() ,
#endif

使用示例

#include "pseudo_code_extend.h"
#include <bits/stdc++.h>
using namespace std;
signed main() {
    set<int> st{1, 2, 3, 4, 5, 6, 7, 8, 9};
    for (auto i : st.begin() to_fast st.end()) {
    // 错误,++std::set::end() 未定义
    // 所以 ++std::set::end() 可能为一个别的位置的迭代器
    // 我的电脑上测试 --(++st.end()) == st.find(7)
        cout << distance(st.begin(), i) << " " << *i << endl;
    }
    for (auto i : st.begin() to_safe st.end()) { // 正确,to 也可
        cout << distance(st.begin(), i) << " " << *i << endl;
    }
    for (auto i : --st.end() down_to st.begin()) {
        cout << *i << " ";
    }
    cout << endl;
    for (int i : 2 to 5) {
        cout << i << " ";
    }
    cout << endl;
    for (int i : 2 until 5) {
        cout << i << " ";
    }
    cout << endl;
    for (int i : 5 down_to 2) {
        cout << i << " ";
    }
    cout << endl;
    for (int i : 5 down_until 2) {
        cout << i << " ";
    }
    cout << endl;
    for (int i : 5 down_until_safe 2) {
        cout << i << " ";
    }
    cout << endl;
    for (int i : 5 down_until_fast 2) {
        cout << i << " ";
    }
    cout << endl;
    vector<int> vec{1, 10, -10, 42};
    for (vector<int>::iterator i : vec.begin() + 1 to vec.end() - 1) {
        cout << *i << " ";
    }
    cout << endl;
    for (auto i : vec.begin() to vec.end() - 1) {
        cout << *i << " ";
    }
    cout << endl;
    for (vector<int>::iterator i : vec.end() - 1 down_to_fast vec.begin()) {
    // 虽然 STL 的 --begin() 也是 UB,但是在 vector 里没有出错,很幸运
        cout << *i << " ";
    }
    cout << endl;
    for (vector<int>::iterator i : vec.end() - 1 down_to vec.begin()) {
        cout << *i << " ";
    }
    cout << endl;
    return 0;
}

期望输出(关于前几行,可能不同,因为第一个使用实例是用于论证 fast 版的 to 可能出错):

0 1
1 2
2 3
3 4
4 5
5 6
6 7
7 8
0 1
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 9
9 8 7 6 5 4 3 2 1 
2 3 4 5 
2 3 4 
5 4 3 2 
5 4 3 
5 4 3 
5 4 3 
10 -10 42 
1 10 -10 42 
42 -10 10 1 
42 -10 10 1 

补充说明

如果 #define from : 可能更优雅。

fftFor-From-To 的缩写,其他同理。

更加广义的定义(例如 typeid(<begin>) 不一定等于 typeid(<end>))我懒得写了。。。