尝试高度封装的写法,但出现神秘编译错误

P3372 【模板】线段树 1

DengStar @ 2024-08-30 18:03:26

RT,我尝试实现了一个封装版本的写法,在本地正常编译并且通过了样例,但在洛谷上 CE。编译信息如下:

No valid executable file was produced by the compiler
/nix/store/p58l5qmzifl20qmjs3xfpl01f0mqlza2-binutils-2.40/bin/ld: ./ccetxk7b.o:(.bss+0x0): multiple definition of `_init'; /nix/store/gqghjch4p1s69sv4mcjksb2kb65rwqjy-glibc-2.38-23/lib/crti.o:(.init+0x0): first defined here
collect2: 错误:ld 返回 1

网上有人说这可能是因为使用了万能头文件并且 using namespace std;,但我删去了这一行之后仍然 CE,自己找不出原因,望大佬解答。
提交记录
代码:

// P3372 【模板】线段树 1
#include<bits/stdc++.h>

typedef long long i64;
constexpr int MAXN = 1e5 + 10;
int n, m, a[MAXN];

template<class Info, class Tag>
struct SegTree
{
    #define lson (id << 1)
    #define rson (id << 1 | 1)

    const int len;
    Tag tag[MAXN << 2];
    Info info[MAXN << 2];

    SegTree() {}

    void update(int id)
    {
        info[id] = info[lson] + info[rson]; 
    }

    void apply(int id, const Tag &v, int l, int r) // 修改id的tag和info 
    {
        info[id].apply(v, l, r);
        tag[id].apply(v);
    }

    void pushdown(int id, int l, int r) // 把id的tag清空,修改左右子的tag和info 
    {
        int mid = (l + r) >> 1;
        apply(lson, tag[id], l, mid);
        apply(rson, tag[id], mid + 1, r);
        tag[id] = Tag(); // 清空tag 
    }

    SegTree(int _len, Info *init): len(_len) 
    {
        std::function<void(int, int, int)> buildtree = [&](int id, int l, int r) // 递归函数,不能用auto 
        {
            if(l == r)
            {
                info[id] = init[l];
                return;
            }

            int mid = (l + r) >> 1;
            buildtree(lson, l, mid), buildtree(rson, mid + 1, r);
            update(id);
        };
        buildtree(1, 1, n);
    }

    void change(int id, int l, int r, int L, int R, const Tag &v)
    {
        if(l == L && r == R)
        {
            apply(id, v, l, r);
            return;
        }

        pushdown(id, l, r);
        int mid = (l + r) >> 1;
        if(R <= mid) change(lson, l, mid, L, mid, v);
        else if(L >= mid + 1) change(rson, mid + 1, r, mid + 1, R, v);
        else change(lson, l, mid, L, mid, v), change(rson, mid + 1, r, mid + 1, R, v);
        update(id);
    }

    void change(int L, int R, const Tag &v)
    {
        change(1, 1, n, L, R, v);
    }

    Info query(int id, int l, int r, int L, int R)
    {
        if(l == L && r == R) return info[id];

        pushdown(id, l, r);
        int mid = (l + r) >> 1;
        if(R <= mid) return query(lson, l, mid, L, mid);
        else if(L >= mid + 1) return query(rson, mid + 1, r, mid + 1, R);
        else return query(lson, l, mid, L, mid) + query(rson, mid + 1, r, mid + 1, R);
    }

    Info query(int L, int R)
    {
        return query(1, 1, n, L, R);
    }

    #undef lson
    #undef rson
};

struct Tag
{
    i64 c;
    Tag() {c = 0;}
    Tag(i64 _c): c(_c) {}
    void apply(const Tag &rhs) {c += rhs.c;} // Tag的复合 
};

struct Info
{
    i64 sum;
    Info () {}
    Info (i64 _sum): sum(_sum) {}
    Info operator + (const Info &rhs) {return Info(sum + rhs.sum);}
    void apply(const Tag &tag, int l, int r) {sum += 1ll * (r - l + 1) * tag.c;} // 计算tag对info的影响 
    i64 getans() {return sum;}
}_init[MAXN];

int main()
{
    std::cin >> n >> m;
    for(int i = 1; i <= n; i++) std::cin >> a[i];
    for(int i = 1; i <= n; i++) _init[i] = Info(a[i]);

    SegTree<Info, Tag> tr(n, _init);
    for(int i = 1, opt, x, y; i <= m; i++)
    {
        std::cin >> opt >> x >> y;
        if(opt == 1)
        {
            i64 k;
            std::cin >> k;
            tr.change(x, y, Tag(k));
        }
        else if(opt == 2) std::cout << tr.query(x, y).getans() << std::endl;
    }

    return 0;
}

by Grammar__hbw @ 2024-08-30 18:05:51

@DengStar _init不能被你自己定义,因为编译器会在main函数前面加一个_init函数用来初始化全局变量


by DengStar @ 2024-08-30 18:06:00

好吧我知道了,调试信息中已经说明了,_init 是一个关键字。
我本以为最多 init 是关键字,没想到 _init 也是关键字,逆天了


by DengStar @ 2024-08-30 18:11:11

@Grammar__hbw 好吧,谢谢大佬,我才知道/wul


by CarrotMeow @ 2024-08-30 18:16:22

@DengStar 这好像不算「高度封装」吧。


by IOIer @ 2024-08-30 18:26:25

这貌似不能算高度封装


by DengStar @ 2024-08-30 18:40:38

@CarrotMeow 对于我来说算了/xk 毕竟不是工程代码,到这一步已经足够了


|