如何绕过变体apply_visitor不支持3 args?

时间:2017-09-27 23:58:27

标签: c++ boost variant

出于某种原因,使用boost的变体(我知道有一个c ++ 17版本,我在这里提供向后兼容性,加上c ++ 17还没有完全支持clang ++)会导致一些奇怪的行为使用访客范例时:

2个参数,作品

#include <iostream>
#include <boost/variant.hpp>

using boost::variant;

typedef boost::variant<double, std::string> term_t;

class plus_visitor : public boost::static_visitor<term_t> {
public:
    term_t operator()(double lhs, double rhs) const{
        return {lhs + rhs};
    }
    term_t operator()(double lhs, std::string rhs) const{
        return {lhs + std::stoi(rhs)};
    }
    term_t operator()(std::string lhs, int rhs) const{
        return operator()(rhs, lhs);
    }
    term_t operator()(std::string lhs, std::string rhs) const{
        return std::stoi(lhs) + std::stoi(rhs);
    }
};

int main(){
    // term_t lhs {3.0};
    term_t rhs {"10"};
    term_t lhs {"3"};
    term_t res = boost::apply_visitor(plus_visitor(), lhs, rhs);
    std::cout << res << std::endl;
    return 0;
}

按预期输出13。

3个参数,爆炸

#include <iostream>
#include <boost/variant.hpp>

using boost::variant;

typedef boost::variant<double, std::string> term_t;

class plus_visitor : public boost::static_visitor<term_t> {
public:
    term_t operator()(double lhs, double rhs, double x) const{
        return {lhs + rhs + x};
    }
    term_t operator()(double lhs, std::string rhs, double x) const{
        return {lhs + std::stoi(rhs) + x};
    }
    term_t operator()(std::string lhs, double rhs, double x) const{
        return operator()(rhs, lhs, x);
    }
    term_t operator()(std::string lhs, std::string rhs, double x) const{
        return std::stoi(lhs) + std::stoi(rhs) + x;
    }
};

int main(){
    term_t rhs {"10"};
    term_t lhs {"3"};
    term_t x {3.0};
    term_t res = boost::apply_visitor(plus_visitor(), lhs, rhs, x);
    std::cout << res << std::endl;
    return 0;
}

这是什么交易? apply_visitor仅适用于2个参数吗?

诊断

我查看了文档,发现:

http://www.boost.org/doc/libs/1_36_0/doc/html/boost/apply_visitor.html

apply_visitor仅适用于二元参数或一元参数!这糟透了!我如何解决这个问题并在语法中提供第三个而不是完全丑陋?还有另一个boost库函数允许更多输入吗?为什么boost库不使用可变参数模板来允许任意大小的apply_visitor函数?

1 个答案:

答案 0 :(得分:2)

您正在查看Boost 1.36的文档,该文档为released in 2008。如果您查看documentation for the current release,则会列出以下apply_visitor重载

template<typename MultiVisitor, typename Variant1, typename Variant2, 
         typename Variant3> 
  typename MultiVisitor::result_type OR decltype(auto) 
  apply_visitor(MultiVisitor & visitor, Variant1 & operand1, 
                Variant2 & operand2, Variant3 & operand3, ... other_operands);
template<typename MultiVisitor, typename Variant1, typename Variant2, 
         typename Variant3> 
  typename MultiVisitor::result_type OR decltype(auto) 
  apply_visitor(const MultiVisitor & visitor, Variant1 & operand1, 
                Variant2 & operand2, Variant3 & operand3, ... other_operands);

文档还说明了

  

接受三个或更多操作数的重载在给定变体操作数的内容上调用给定访问者的函数调用操作符。 ... 这些功能实际上是在标题boost/variant/multivisitors.hpp 中定义的... 如果要使用多个访问者,则必须手动包含该标题。

因此,请确保您使用的是最新的Boost版本,包含相关的标头,为3参数示例定义缺少的operator()重载,并且您的代码应该编译。