如何解决不支持 3 个参数的变体 apply_visitor?
Posted
技术标签:
【中文标题】如何解决不支持 3 个参数的变体 apply_visitor?【英文标题】:How to get around variant apply_visitor not supporting 3 args? 【发布时间】:2017-09-27 23:58:27 【问题描述】:出于某种原因,使用 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
函数?
【问题讨论】:
顺便说一句,你忘记了很多重载(第三个参数是std::string
的重载)
@Jarod42 我知道。我只是想在这里证明一个观点
好吧,事实证明。如果你想使用 boost,你将不得不处理这个限制。如果您需要两个以上的参数,请将它们替换为单个结构,包含任意数量的值。
有更新版本,可用:boost.org/doc/libs/1_65_1/doc/html/boost/apply_visitor.html
【参考方案1】:
您正在查看 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()
重载,并且您的代码应该可以编译。
【讨论】:
知道了。谢谢!我希望他们能让这一点更加明显。此外,阅读此 boost 库中的错误消息非常困难。 :( @OneRaynyDay Google 搜索很少会找到最新的 Boost 版本文档,但如果您正在查看旧文档,顶部会出现一个黄色框,表示您没有查看最新版本发布并具有最新文档的链接(尽管该链接在某些情况下已损坏:))以上是关于如何解决不支持 3 个参数的变体 apply_visitor?的主要内容,如果未能解决你的问题,请参考以下文章