You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多语言模式表示方法及C++代码重复模式优化咨询

Handling Repetitive Code Patterns (C++ & Cross-Language Comparisons)

Great question! Dealing with boilerplate code where logic repeats but targets different members is a common pain point. Let's walk through how to clean up your C++ code first, then look at how other languages handle this same pattern.


C++ Optimization Solutions

1. Member Pointers + Generic Helper Function

The most straightforward type-safe approach is to extract the core logic into a helper function that takes a pointer to the class member container. This way, you only write the check logic once:

#include <vector>
#include <algorithm>

class layerclass {
public:
    std::vector<int> a;
    std::vector<int> b;
    std::vector<int> c;

private:
    // Generic check that works with any of our vector members
    bool isIn(const std::vector<int> layerclass::*container, int x) const {
        return std::find((this->*container).begin(), (this->*container).end(), x) != (this->*container).end();
    }

public:
    bool isInA(int x) const { return isIn(&layerclass::a, x); }
    bool isInB(int x) const { return isIn(&layerclass::b, x); }
    bool isInC(int x) const { return isIn(&layerclass::c, x); }
};

class innerlayer : public layerclass {
public:
    layerclass* outerlayer;

private:
    bool isIn(const std::vector<int> layerclass::*container, int x) const {
        if (layerclass::isIn(container, x)) {
            return true;
        }
        return outerlayer->isIn(container, x);
    }

public:
    bool isInA(int x) const { return isIn(&layerclass::a, x); }
    bool isInB(int x) const { return isIn(&layerclass::b, x); }
    bool isInC(int x) const { return isIn(&layerclass::c, x); }
};

Now you only need to update the isIn helper if your logic changes—no more copying and pasting the same check three times.

2. C++17 Auto Template Parameters (Advanced)

For a more modern, concise approach, use C++17's auto template parameters to bind directly to member pointers at compile time:

#include <vector>
#include <algorithm>

class layerclass {
public:
    std::vector<int> a;
    std::vector<int> b;
    std::vector<int> c;

    template<auto ContainerPtr>
    bool isIn(int x) const {
        return std::find((this->*ContainerPtr).begin(), (this->*ContainerPtr).end(), x) != (this->*ContainerPtr).end();
    }

    // Convenience wrappers for external use
    bool isInA(int x) const { return isIn<&layerclass::a>(x); }
    bool isInB(int x) const { return isIn<&layerclass::b>(x); }
    bool isInC(int x) const { return isIn<&layerclass::c>(x); }
};

class innerlayer : public layerclass {
public:
    layerclass* outerlayer;

    template<auto ContainerPtr>
    bool isIn(int x) const {
        if (layerclass::isIn<ContainerPtr>(x)) {
            return true;
        }
        return outerlayer->isIn<ContainerPtr>(x);
    }

    bool isInA(int x) const { return isIn<&layerclass::a>(x); }
    bool isInB(int x) const { return isIn<&layerclass::b>(x); }
    bool isInC(int x) const { return isIn<&layerclass::c>(x); }
};

This approach is fully type-safe and avoids runtime overhead, since the template is resolved at compile time.

If you need a fast fix, macros can generate the repetitive functions, but they come with downsides like poor readability and debugging difficulty. Use this sparingly:

#include <vector>
#include <algorithm>

#define DEFINE_IS_IN(NAME) \
bool isIn##NAME(int x) const { \
    return std::find(NAME.begin(), NAME.end(), x) != NAME.end(); \
}

#define DEFINE_INNER_IS_IN(NAME) \
bool isIn##NAME(int x) const { \
    if (layerclass::isIn##NAME(x)) return true; \
    return outerlayer->isIn##NAME(x); \
}

class layerclass {
public:
    std::vector<int> a;
    std::vector<int> b;
    std::vector<int> c;

    DEFINE_IS_IN(a)
    DEFINE_IS_IN(b)
    DEFINE_IS_IN(c)
};

class innerlayer : public layerclass {
public:
    layerclass* outerlayer;

    DEFINE_INNER_IS_IN(a)
    DEFINE_INNER_IS_IN(b)
    DEFINE_INNER_IS_IN(c)
};

How Other Languages Handle This Pattern

Python

Python's dynamic nature lets you generate methods on the fly or use attribute access to avoid repetition:

class LayerClass:
    def __init__(self):
        self.a = []
        self.b = []
        self.c = []
    
    def _is_in(self, container_name, x):
        return x in getattr(self, container_name)

# Dynamically create is_in_a, is_in_b, is_in_c
for name in ['a', 'b', 'c']:
    def make_method(name):
        def method(self, x):
            return self._is_in(name, x)
        return method
    setattr(LayerClass, f"is_in_{name}", make_method(name))

class InnerLayer(LayerClass):
    def __init__(self, outer_layer):
        super().__init__()
        self.outer_layer = outer_layer
    
    def _is_in(self, container_name, x):
        if super()._is_in(container_name, x):
            return True
        return self.outer_layer._is_in(container_name, x)

# Generate the same methods for InnerLayer
for name in ['a', 'b', 'c']:
    def make_method(name):
        def method(self, x):
            return self._is_in(name, x)
        return method
    setattr(InnerLayer, f"is_in_{name}", make_method(name))

Java

Java uses suppliers or method references to pass the target container, with type safety enforced at compile time:

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Supplier;

class LayerClass {
    private List<Integer> a = new ArrayList<>();
    private List<Integer> b = new ArrayList<>();
    private List<Integer> c = new ArrayList<>();

    private boolean isIn(Supplier<List<Integer>> containerSupplier, int x) {
        return containerSupplier.get().contains(x);
    }

    public boolean isInA(int x) {
        return isIn(() -> a, x);
    }

    public boolean isInB(int x) {
        return isIn(() -> b, x);
    }

    public boolean isInC(int x) {
        return isIn(() -> c, x);
    }

    // Getters needed for InnerLayer access
    protected List<Integer> getA() { return a; }
    protected List<Integer> getB() { return b; }
    protected List<Integer> getC() { return c; }
}

class InnerLayer extends LayerClass {
    private LayerClass outerLayer;

    public InnerLayer(LayerClass outerLayer) {
        this.outerLayer = Objects.requireNonNull(outerLayer);
    }

    private boolean isIn(Supplier<List<Integer>> containerSupplier, int x) {
        if (super.isIn(containerSupplier, x)) {
            return true;
        }
        return outerLayer.isIn(containerSupplier, x);
    }

    @Override
    public boolean isInA(int x) {
        return isIn(() -> getA(), x);
    }

    @Override
    public boolean isInB(int x) {
        return isIn(() -> getB(), x);
    }

    @Override
    public boolean isInC(int x) {
        return isIn(() -> getC(), x);
    }
}

TypeScript/JavaScript

Dynamic property access combined with type safety (in TypeScript) makes this pattern easy to handle:

class LayerClass {
    a: number[] = [];
    b: number[] = [];
    c: number[] = [];

    private _isIn(containerName: keyof LayerClass, x: number): boolean {
        return this[containerName].includes(x);
    }

    isInA(x: number): boolean { return this._isIn('a', x); }
    isInB(x: number): boolean { return this._isIn('b', x); }
    isInC(x: number): boolean { return this._isIn('c', x); }
}

class InnerLayer extends LayerClass {
    outerLayer: LayerClass;

    constructor(outerLayer: LayerClass) {
        super();
        this.outerLayer = outerLayer;
    }

    private _isIn(containerName: keyof LayerClass, x: number): boolean {
        if (super._isIn(containerName, x)) {
            return true;
        }
        return this.outerLayer._isIn(containerName, x);
    }

    isInA(x: number): boolean { return this._isIn('a', x); }
    isInB(x: number): boolean { return this._isIn('b', x); }
    isInC(x: number): boolean { return this._isIn('c', x); }
}

Key Takeaway

Across all languages, the core strategy is the same: extract the reusable logic into a single function, and pass the varying part (like the target container) as a parameter. Static languages lean on type-safe mechanisms like member pointers or suppliers, while dynamic languages use more flexible attribute access and method generation.

内容的提问来源于stack exchange,提问作者user2183336

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:05:46