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

如何用惯用方式精简临时类实例代码以实现DRY原则?

问题描述

编写代码时常遇到这类场景:需要定义多个同一类型的实例,它们共享通用前缀,且定义差异很小,但难以写出既紧凑又易用的代码。

比如初始代码存在重复的前缀和构造调用:

auto blue_foo = std::make_unique<float[]>(n);
auto blue_bar = std::make_unique<float[]>(m);
auto blue_baz = std::make_unique<float[]>(k);

尝试用结构体分组来优化调用方式(比如blue.foo代替blue_foo),但结构体定义又过于冗余:

struct {
    std::unique_ptr<float[]> foo, bar, baz;
} blue = {
    std::make_unique<float[]>(n),
    std::make_unique<float[]>(m),
    std::make_unique<float[]>(k),
};

想简化结构体成员的类型声明(比如auto foo, bar, baz;)但语法不允许;用lambda封装构造逻辑也仅能减少少量重复,效果有限:

auto make_data = [](std::size_t size) { return std::make_unique<float[]>(size); };

struct { auto foo, bar, baz; } blue = { make_data(n), make_data(m), make_data(k) };

需求:针对这类仅单次使用的代码片段,找到紧凑且可读的惯用优化方法。

惯用优化方法

1. 结构化绑定 + std::tuple(C++17+)

无需定义结构体,直接用tuple打包实例,通过结构化绑定获取命名变量,既消除前缀重复,又保持代码紧凑:

auto [blue_foo, blue_bar, blue_baz] = std::make_tuple(
    std::make_unique<float[]>(n),
    std::make_unique<float[]>(m),
    std::make_unique<float[]>(k)
);

如果需要分组访问(类似blue.foo),可以结合匿名结构体和即时lambda初始化:

auto blue = []{
    struct {
        std::unique_ptr<float[]> foo, bar, baz;
    } data{
        std::make_unique<float[]>(n),
        std::make_unique<float[]>(m),
        std::make_unique<float[]>(k)
    };
    return data;
}();

调用时依然可以用blue.foo,且无需额外的结构体声明。

2. 简化构造逻辑的模板函数

用极简模板函数封装重复的make_unique调用,减少构造代码的重复:

template<typename T>
constexpr auto make_array_ptr(std::size_t size) {
    return std::make_unique<T[]>(size);
}

// 分组使用版本
auto blue = []{
    struct {
        decltype(make_array_ptr<float>(0)) foo, bar, baz;
    } data{
        make_array_ptr<float>(n),
        make_array_ptr<float>(m),
        make_array_ptr<float>(k)
    };
    return data;
}();

// 非分组简化版本
auto [foo, bar, baz] = std::make_tuple(
    make_array_ptr<float>(n),
    make_array_ptr<float>(m),
    make_array_ptr<float>(k)
);

3. C++20指定初始化器优化结构体定义

利用C++20的指定初始化器,让结构体初始化的可读性大幅提升,避免顺序错误风险,结构也更清晰:

struct {
    std::unique_ptr<float[]> foo;
    std::unique_ptr<float[]> bar;
    std::unique_ptr<float[]> baz;
} blue = {
    .foo = std::make_unique<float[]>(n),
    .bar = std::make_unique<float[]>(m),
    .baz = std::make_unique<float[]>(k)
};

4. 宏(极端场景下使用)

如果变量数量极多,可以用宏消除前缀和构造重复,但注意宏的可读性和调试性较差,非必要不使用:

#define MAKE_BLUE_ARRAY(name, size) \
    auto blue_##name = std::make_unique<float[]>(size);

MAKE_BLUE_ARRAY(foo, n);
MAKE_BLUE_ARRAY(bar, m);
MAKE_BLUE_ARRAY(baz, k);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 23:32:10