【问题标题】:Getter for boost::variant objectboost::variant 对象的吸气剂
【发布时间】:2012-10-08 06:22:13
【问题描述】:

我有一个getter对象,它返回一个Type类型的对象,定义如下:

typedef boost::variant<int, std::string> Empty;

通常情况下,我既没有要返回的 int 也没有要返回的字符串,而是必须返回一个空状态。你认为我如何返回这个状态?

a) typedef 一个 Empty 类型并将其添加到变体中:boost::variant&lt;int, std::string, Empty&gt;

b) 返回类型()

c) 抛出异常

d) 返回一个 boost::shared_ptr,在为空的情况下指向 NULL。

【问题讨论】:

  • 这个“空类型”是由boost::empty 提供的,事实上,当且仅当当前值是@987654327 时,variant.empty() 函数才会return 为真@ 类型。在所有其他情况下,它将返回 false

标签: c++ boost


【解决方案1】:

正确的答案是使用boost::blank 来表示其中可以没有任何内容的变体。因此,您的变体 typedef 如下所示:

typedef boost::variant<boost::blank, int, std::string> Empty;

blank 是专门为此设计的,variant 有基于它的特殊代码。通过使用它,您可以在复制时获得无内存分配保证(如果成员未在复制时分配)。所以这很好。

由于您的变体可以是“空的”,因此您的所有处理访问者都可以处理它是很重要的。添加额外的访问者路径通常比基于optional 或其他内容的多个条件更方便。不同的代码路径将针对访问者进行本地化,这通常比optional&lt;variant&gt; 更有意义。

【讨论】:

    【解决方案2】:

    将其包装在boost::optional 中,这有一个简单的测试(可转换为布尔值)来确定是否分配了有效值 - 然后您不需要以“空”状态污染您的变体。例如

    boost::optional<boost::variant<... > > some_func()
    {
    :
    }
    

    当你真正需要返回一些东西时,记得在你的函数中使用就地构造。

    【讨论】:

      【解决方案3】:

      如果方法可能无法返回对象,这是一种常见的方法 - 使方法返回布尔值:

      bool get_value(Type& type) {
        if ( /*check variant emptyness*/) // one can use this - http://stackoverflow.com/a/7668530/670719
          return false;
        // else assign type 
      }
      

      对您的解决方案的评论:

      a) 如果您将返回 Empty,您仍然需要在方法调用后进行检查。那么,如果已经有内置的 bool,为什么还要添加更多类型。

      b) Type() 可以与合法变量具有相同的值

      c) 例外是针对特殊情况,但根据您的描述“它经常”

      d) 你的问题是你不能使用 Type 并且同时不能返回 boost::variant,所以添加一个带有额外所有权问题的类型会带来更多关于在没有解决初始问题的情况下发生的问题干净的界面。

      【讨论】:

      • 这是一种常见的方法,但不是特别干净的方法。使用返回类型返回数据,而不是输出参数。
      • 该方法很干净,因为它仅使用内置 bool 并且用户将知道使用模型,因为他将无法编译 Type type = instance.get_value(). 如果请求者不想透露这一点他在boost::variant 中存储了一个值(这是实现的细节)我无法获得使用boost::optional 或检查Empty 等的解决方案。这些解决方案既不灵活也不矫枉过正。
      • 抱歉,您的论点不符合。这样做的正确方法是使用返回值,故事结束。有几种不同的方法可以实现该目标(特别是空变体,使用选项类型,或者,作为行人的方法,使用pair&lt;result_type, bool&gt;,例如std::set::insert)。所有这些都更干净,并且不要泄漏实现细节,尽管你已经声称。这些解决方案都不是“不灵活的”。这些解决方案都不是“矫枉过正”(这甚至意味着什么?从语法上讲,它们肯定比您的代码更少繁重)。
      • 事实上,pair&lt;result_type, bool&gt; 需要在用户端使用比我的方法更多的代码。并且将其作为返回值没有任何好处,因为您仍然必须在分配之前检查值的可用性。不灵活意味着如果您通常返回的不是“boost::variant”而是具体类型
      • 错了。根本区别在于您的代码需要在事先 声明和初始化一个变量。这不仅设置了句法障碍,而且在某些情况下还改变了语义。例如,它阻止变量为const。关于“更灵活”,我上一条评论给出了三种解决方案,其中两种适用于所有类型。使用variant,如果您正确使用该变体,您不必在使用它之前检查该值的可用性。这就是它的主要优势之一。
      猜你喜欢
      • 2018-11-16
      • 2018-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-28
      • 1970-01-01
      • 2019-11-26
      • 2014-02-24
      相关资源
      最近更新 更多