【发布时间】:2013-04-03 14:01:25
【问题描述】:
我是否需要使用带有 boost::variant 的访问者类,例如 class Visitor : public boost::static_visitor<>?
如果没有,是否有理由不使用访问者?有理由更喜欢访问者课程吗?
我问这个问题是因为访问者类对于 boost::variant 的使用来说显得多余。
【问题讨论】:
标签: c++ boost-variant apply-visitor
我是否需要使用带有 boost::variant 的访问者类,例如 class Visitor : public boost::static_visitor<>?
如果没有,是否有理由不使用访问者?有理由更喜欢访问者课程吗?
我问这个问题是因为访问者类对于 boost::variant 的使用来说显得多余。
【问题讨论】:
标签: c++ boost-variant apply-visitor
您不必使用访问者,您可以使用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<T>() 替代方案;通常,当我只需要检查一种(或两种)类型并且(根本)不关心所有其他类型时。另一种方法是使用具有template <typename T> void operator()(T const&) const; 重载的访问者,这不一定更干净。
【讨论】:
SomeVariantVariable.which() 查询底层类型,这将返回一个typedef boost::variant<Type1, Type2> variant_variable 声明的索引并指示哪个类型:Type1 = 0,Type2 = 1?
switch 就可以了,然后打电话给get();但是此时您只是重新实现了调用访问者的代码......除了如果有人在列表中间添加一个类型,那么索引就会移动,因此get() 可能会返回您必须考虑的空值(或崩溃)。
如果想对变体进行一些操作,例如一些检查,那么您可能希望将其作为访问者。
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
}
【讨论】: