【问题标题】:Is the boost::variant visitor class a requirement?boost::variant 访问者类是必需的吗?
【发布时间】:2013-04-03 14:01:25
【问题描述】:

我是否需要使用带有 boost::variant 的访问者类,例如 class Visitor : public boost::static_visitor<>

如果没有,是否有理由不使用访问者?有理由更喜欢访问者课程吗?

我问这个问题是因为访问者类对于 boost::variant 的使用来说显得多余。

【问题讨论】:

    标签: c++ boost-variant apply-visitor


    【解决方案1】:

    您不必使用访问者,您可以使用get<T>()完美查询底层类型。

    这导致这样的代码:

    int foo(boost::variant<int, std::string, Bar> const& v) {
        if (int const* i = get<int>(&v)) {
            return *i;
        }
        if (std::string const* s = get<std::string>(&v)) {
            return boost::lexical_cast<int>(*s);
        }
        if (Bar const* b = get<Bar>(&v)) {
            return b->toInt();
        }
    
        std::abort(); // ?
    }
    

    这可以说是丑陋的......而且还有一个问题,如果您突然将一种类型添加到变体中,您需要检查代码中的每一次使用,以检查您是否在某处丢失了if .

    另一方面,如果您使用变体,如果您未能处理案例(类型),您将收到编译时错误通知。

    在我看来,使用boost::static_visitor 是无限优越的......虽然我已经使用了几次get&lt;T&gt;() 替代方案;通常,当我只需要检查一种(或两种)类型并且(根本)不关心所有其他类型时。另一种方法是使用具有template &lt;typename T&gt; void operator()(T const&amp;) const; 重载的访问者,这不一定更干净。

    【讨论】:

    • 难道我不能简单地使用SomeVariantVariable.which() 查询底层类型,这将返回一个typedef boost::variant&lt;Type1, Type2&gt; variant_variable 声明的索引并指示哪个类型:Type1 = 0,Type2 = 1?
    • @Mushy:可以,然后switch 就可以了,然后打电话给get();但是此时您只是重新实现了调用访问者的代码......除了如果有人在列表中间添加一个类型,那么索引就会移动,因此get() 可能会返回您必须考虑的空值(或崩溃)。
    【解决方案2】:

    如果想对变体进行一些操作,例如一些检查,那么您可能希望将其作为访问者。

    struct to_str : boost::static_visitor<std::string>
    {
       template<class T>
       std::string operator()(T const & x) const
       {
          return boost::lexical_cast<std::string>(x);
       }
    };
    

    另一方面,如果您愿意,例如检查它是否int 并对其进行处理,您可能会使用boost::get 例如

    if(const int * my_int = boost::get<int>(&my_var)) //no-throw form
    {
      //do smth with int
    }
    

    【讨论】:

      猜你喜欢
      • 2011-04-06
      • 1970-01-01
      • 1970-01-01
      • 2023-04-05
      • 2011-10-26
      • 2016-07-20
      • 1970-01-01
      • 2013-12-25
      • 1970-01-01
      相关资源
      最近更新 更多