有时在我的代码中,我发现自己想要定义同一个类的多个示例,定义中的差异相对于其整体长度来说很小,并且共享一些公共指示符。而且-我努力重构代码,以便它既紧凑又易于使用。
示例:我从以下内容开始:
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
的结构中,这样我就可以写
do_stuff_with(blue.foo, blue.baz, 123);
型
而不是
do_stuff_with(blue_foo, blue_baz, 123);
型
但是-然后我需要更多的重复:
struct {
std::unique_ptr<float[]> foo, bar, baz;
} blue = {
std::make_unique<float[]>(n),
std::make_unique<float[]>(m),
std::make_unique<float[]>(k),
};
型
太浪费了!我至少想写这样的东西:
struct { auto foo, bar, baz; } foo = {
std::make_unique<float[]>(n),
std::make_unique<float[]>(m),
std::make_unique<float[]>(k),
};
型
但这不可能
另外,我不想重复make_unique调用。我可以写一个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) };
型
但是lambda需要写很多东西,它并不能保存那么多。即使这样也有一些重复。
什么是使我的初始代码段紧凑且可读的惯用方法?
备注:在这个例子中,代码片段并没有重复很多次,只有一次。如果我重复使用foo,bar和baz的组合,我会写一个类来保存它们。
4条答案
按热度按时间3wabscal1#
我能想到的最短(但不一定是最容易理解的)版本是使用一个可变参数模板立即调用lambda:
字符串
https://godbolt.org/z/9c8cvc8oW
它没有任何重复,但我不确定你会称之为惯用法。
如果您可以使用
new
而不是std::make_unique
并重复new float[x]
三次,则可以简化此操作并提高可读性:型
tkqqtvp12#
在您的特定示例中,所有成员都具有相同的类型,这使得
std::array
成为一个可行的选项:字符串
这消除了大部分重复,但
std::make_unique
仍然会被调用三次。对于较小的示例,您可以如下解决此问题:型
对于更大的示例,即使多次调用
make
也有问题,您可以编写如下代码:型
如果不使用
std::array
,而是使用T(&data)[N]
参数(类似于std::to_array
),则可以获得语法transform({n, m, k}, make);
。wnavrhmk3#
你可以创建一个helper函数,返回
unique_ptr
的std::tuple
,然后使用structure bindings。大致思路如下:字符串
ymdaylpp4#
@NathanOliver提出了一个有趣的建议,使用字典/
std::map
。但这仍然让我重复了一堆代码。如果我们有一个let,它有一个合适的Transformer,将key-ctor-arguments对转换为key-constructed-values对,并且如果我们可以示例化它,而不存在任何模板二义性问题,那么我们可以这样写:字符串
优点:
blue
一起传递损害: