如何使 std::variants 的使用在语法上更加“可口”?

ein*_*ica 2 c++ idioms syntactic-sugar c++17 std-variant

这是受到我给新手用户的回答的启发,我建议他们使用 anstd::variant而不是 union。

通过工会,您可能会遇到如下情况:

struct Box {
    struct Item { float value; };
    using Boxes = std::vector<Box>;

    union Value {
        Item item;
        Boxes boxes;
    };

    Value contents;
    std::string label;
};
Run Code Online (Sandbox Code Playgroud)

(不完全是最初的问题,我在这里接受了一些诗意的许可。)并且使用一个变体,该类可能如下所示:

struct Box {
    struct Item { float value; };
    using Boxes = std::vector<Box>;

    std::variant<Item, Boxes> contents;
    std::string label;
};
Run Code Online (Sandbox Code Playgroud)

问题是,使用第一个变体,我可以写

if (box.contents.boxes.size() > 2) { foo(); }
Run Code Online (Sandbox Code Playgroud)

如果我已经确定会有子框,这就会起作用。

对于std::variant,我必须写:

if (std::get<Boxes>(box.contents).size() > 2) { foo(); }
Run Code Online (Sandbox Code Playgroud)

我觉得第二个版本的可读性要差得多,有点混乱,而且很分散注意力。另外 - 我必须知道 的类型boxes

在我的代码中,我可以做些什么来让我的用户无需进行此类std::get()调用,并使他们的生活更加愉快?

yur*_*hek 5

只需添加一些访问器包装std::get

struct Box {
    struct Item { float value; };
    using Boxes = std::vector<Box>;

    std::variant<Item, Boxes> contents;
    std::string label;

    decltype(auto) item()       { return std::get<Item>(contents); }
    decltype(auto) item() const { return std::get<Item>(contents); }

    decltype(auto) boxes()       { return std::get<Boxes>(contents); }
    decltype(auto) boxes() const { return std::get<Boxes>(contents); }
};
Run Code Online (Sandbox Code Playgroud)

然后是这样的:

if (box.boxes().size() > 2) { foo(); }
Run Code Online (Sandbox Code Playgroud)