c++ - 如何将几个 bool 标志包装到结构中以将它们传递给具有方便语法的函数

标签 c++ design-patterns interface c++17 flags

在一些测试代码中有一个这样的辅助函数:

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);
}

Here's my attempt :

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/

相关文章:

c++ - 使用类型为 'array' 的类成员

java - 我可以判断是否调用了抽象方法吗?

c# - 多态性——使用从接口(interface)继承的对象而不是直接使用接口(interface)

java - 向项目中 100 个不同位置调用的方法添加参数 - 正确的方法是什么?

c# - 我应该如何将行为注入(inject)实体

java - java中的MouseMotionListener如何工作?

c# - 如何在 C# 中创建选择加入方法继承?

c++ - 模板类是否在 C++ 的不同编译单元中编译了多次?

C++ 防止 const 方法通过成员指针或引用更改数据

c++ - 比较c++中同一 vector 的元素