在一些测试代码中有一个这样的辅助函数:
auto make_condiment(bool salt, bool pepper, bool oil, bool garlic) {
// assumes that first bool is salt, second is pepper,
// and so on...
//
// Make up something according to flags
return something;
};
这基本上建立了 something
基于一些bool
ean 标志。
我关心的是每个 bool
的含义硬编码在参数的名称中,这很糟糕,因为在调用站点很难记住哪个参数意味着什么(是的,IDE 可以通过在选项卡完成时显示这些名称来完全消除问题,但仍然......) :
// at the call site:
auto obj = make_condiment(false, false, true, true); // what ingredients am I using and what not?
因此,我想传递一个描述设置的对象。此外,只需将它们聚合在一个对象中,例如std::array<bool,4>
.
相反,我想启用这样的语法:
auto obj = make_smart_condiment(oil + garlic);
这将生成相同的 obj
作为之前对 make_condiment
的调用.
这个新函数是:
auto make_smart_condiment(Ingredients ingredients) {
// retrieve the individual flags from the input
bool salt = ingredients.hasSalt();
bool pepper = ingredients.hasPepper();
bool oil = ingredients.hasOil();
bool garlic = ingredients.hasGarlic();
// same body as make_condiment, or simply:
return make_condiment(salt, pepper, oil, garlic);
}
struct Ingredients {
public:
enum class INGREDIENTS { Salt = 1, Pepper = 2, Oil = 4, Garlic = 8 };
explicit Ingredients() : flags{0} {};
explicit Ingredients(INGREDIENTS const& f) : flags{static_cast<int>(f)} {};
private:
explicit Ingredients(int fs) : flags{fs} {}
int flags; // values 0-15
public:
bool hasSalt() const {
return flags % 2;
}
bool hasPepper() const {
return (flags / 2) % 2;
}
bool hasOil() const {
return (flags / 4) % 2;
}
bool hasGarlic() const {
return (flags / 8) % 2;
}
Ingredients operator+(Ingredients const& f) {
return Ingredients(flags + f.flags);
}
}
salt{Ingredients::INGREDIENTS::Salt},
pepper{Ingredients::INGREDIENTS::Pepper},
oil{Ingredients::INGREDIENTS::Oil},
garlic{Ingredients::INGREDIENTS::Garlic};
但是,我有一种重新发明轮子的感觉。
是否有更好的或标准的方法来完成上述任务?
是否有我可以/应该使用的设计模式?
最佳答案
我认为您可以使用 std::bitset
删除一些样板文件。这是我想出的:
#include <bitset>
#include <cstdint>
#include <iostream>
class Ingredients {
public:
enum Option : uint8_t {
Salt = 0,
Pepper = 1,
Oil = 2,
Max = 3
};
bool has(Option o) const { return value_[o]; }
Ingredients(std::initializer_list<Option> opts) {
for (const Option& opt : opts)
value_.set(opt);
}
private:
std::bitset<Max> value_ {0};
};
int main() {
Ingredients ingredients{Ingredients::Salt, Ingredients::Pepper};
// prints "10"
std::cout << ingredients.has(Ingredients::Salt)
<< ingredients.has(Ingredients::Oil) << "\n";
}
您没有得到 +
类型语法,但它非常接近。不幸的是,您必须保留 Option::Max
,但还算不错。此外,我决定不使用枚举类
,这样它就可以作为Ingredients::Salt
访问并隐式转换为int
。如果您想使用 enum class
,您可以显式访问和转换。
关于c++ - 如何将几个 bool 标志包装到结构中以将它们传递给具有方便语法的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68303872/