【问题标题】:union in c++ with a single non trivial typec++ 中的联合,具有单个非平凡类型
【发布时间】:2016-05-12 00:14:13
【问题描述】:

我有一个简单的结构,它可以携带结果或错误,不能同时携带两者。 两者都是同一类型,但为了清楚起见,我想要两个成员。 从阅读cppreference.com 看来,以下代码 sn-p 将是有效的 c++? 在联合析构函数中使用放置删除来整理 non trivial 类(在此实例中为 std::string)。

struct Result {
  union {
    std::string resultText;
    std::string errorText;
    ~(){ resultText.~string();}
  };
};

看起来,要使用它,包含结构需要实现 5 成员规则才能显式复制/移动 resultText。

【问题讨论】:

  • 这是一个奇怪的联合用例 - 一个私有字符串和两个 getter 有什么问题(如 getResultText()getErrorText())?您甚至可以添加一个仅调试标志以确保您获得正确的文本。
  • 您也可以有一个简单的结构,其中包含std::stringbool(甚至是枚举)来指示结果是错误还是实际结果。我必须同意@VittorioRomeo,为此使用联合是一个非常奇怪的想法。
  • 顺便说一句,你的结构实际上错过了一个鉴别器实际上从联合中使用什么。
  • 由于c++没有强大的typedef,你可以将std::string包装在类(struct Ok {std::string text;}; struct Error {std::string text;};)中,然后使用一些变体类(using Result = boost::variant<Ok, Error>)。
  • c++ 代码中的联合通常有一个好的用例吗?我承认,这是一种做一些我永远不想在生产代码中看到的愚蠢事情的练习。但有趣的是,在我的大部分 c++ 职业生涯中,我什至从未考虑过该语言会支持具有非平凡成员的联合。

标签: c++


【解决方案1】:

联合只会降低代码的可读性。并且取决于你如何使用它也会增加维护。实际上,尽管有 std::string 成员,但您提到“实施 5 规则”这一事实表明您的课程将成为维护的噩梦。

我会看看这些选项(问题中没有足够的细节来确定什么是最好的):

  • 使用异常。您可以通过派生自 std::exception

  • 来制作自定义异常
  • 使用Boost.Optional

    boost::optional<std::string> do_something() { ... };
    
    std::string result = do_something().value_or("error!");
    

【讨论】:

  • 您可能想提一下,std::optional 在最新的 c++ 标准中尚不存在。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-18
  • 1970-01-01
  • 2012-05-28
  • 1970-01-01
  • 2015-08-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多