gpt4 book ai didi

c++ - 类设计-使用可选的?变体?不透明?

转载 作者:行者123 更新时间:2023-12-01 14:53:27 24 4
gpt4 key购买 nike

我想上一堂关于PCI总线位置的类(class)。为了便于讨论,它们以三种形式出现:

  • [domain]:[bus]:[device]。[function]
  • [domain]:[bus]:[device]
  • [总线]:[设备]。[功能]

  • 并说每个字段都是一个非负整数值(为了简单起见,我们甚至说 unsigned)。

    关于如何定义此类,我抓狂了。我可以在域和函数字段中使用 std::optional;但是,它们都不都是可选的。我可以使用3种类型的变体,但随后需要定义单独的类型,这些类型有很多重叠。我可以只保留4个 unsigned和一个3值的枚举,该枚举的格式有效-但这有点麻烦,我需要用getter来使类不透明。如果我尝试以某种方式使用工会,也是一样。

    似乎我所做的每一个选择都将成为一个浮躁的类。如何最大程度地减少对此的不满?

    注意:尽管我怀疑C++ 20会给您任何东西,但是任何语言标准版本都可以解决。

    最佳答案

    根据我的评论,我想知道这样的事情是否可行:

    enum class pci_format { domain_function, domain, function };

    template <pci_format E> struct tag { };

    class pci_location {
    public:
    pci_location (tag<pci_format::domain_function>, unsigned domain, unsigned bus,
    unsigned device, unsigned function)
    : format_(pci_format::domain_function)
    , domain_(domain)
    , bus_(bus)
    , device_(device)
    , function_(function)
    { }

    // Repeat for other values of pci_format.

    pci_format format () const { return format_; }

    bool has_domain () const {
    return (format_ == pci_format::domain_function)
    or (format_ == pci_format::domain);
    }

    unsigned domain () const {
    if (not has_domain()) { throw std::runtime_error("Domain not available."); }
    return domain_;
    }

    // Repeat for other fields.

    private:
    pci_format format_;
    unsigned domain_;
    unsigned bus_;
    unsigned device_;
    unsigned function_
    };

    您基本上将为每种PCI“格式”创建一个特定的构造函数。当然,您也可以将每个 unsigned存储为 std::optional<unsigned>,但这将迫使用户“取消引用”每个可选对象,即使他们确定必须包含值也是如此。

    一种或另一种方式是,他们必须检查位置所在的“格式”,因此在我看来,为此使用枚举更加用户友好。然后,用户只需检查一次即可确切知道哪些字段可用。

    我想您可以在所有这些之上放置一个访问者,以便他们可以简单地提供针对每种“格式”执行的代码:
    struct pci_location_visitor {
    virtual void visit (tag<pci_format::domain_function>, pci_location const & obj) = 0;
    // Repeat for other enum values.
    };

    // Add to pci_location:
    void accept (pci_location_visitor & visitor) {
    switch (format_) {
    case pci_format::domain_function:
    return visitor.visit(tag<pci_format::domain_function>{}, *this);
    default: throw std::runtime_error("Format not supported for visitation.");
    }
    }

    然后最重要的是,您可以创建一个访问者,该访问者可以由一堆可调用对象(即lambda)构造而成,因此可以按以下方式使用所有访问者:
    pci_location const & loc = getIt();
    auto printSomething = make_pci_location_visitor(
    [](tag<pci_format::domain_function>, pci_location const & e) { std::cout << e.domain(); }
    , [](tag<pci_format::domain>, pci_location const & e) { std::cout << e.bus(); }
    , [](tag<pci_format::function>, pci_location const & e) { std::cout << e.function(); }
    );
    loc.accept(printSomething);

    有关如何构造此类访问者的示例,请参见 overloaded example on cppreference.com中的 std::visit类。

    关于c++ - 类设计-使用可选的?变体?不透明?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60442920/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com