如何解决变体 apply_visitor 不支持 3 个参数的问题?
How to get around variant apply_visitor not supporting 3 args?
出于某种原因,使用 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
函数?
您正在查看 Boost 1.36 的文档,它是 released in 2008. If you look at the 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);
文档还指出
Overloads accepting three or more operands invoke the function call operator of the given visitor on the content of the given variant operands. ... Those functions are actually defined in a header boost/variant/multivisitors.hpp
... That header must be manually included if multi visitors are meant for use.
因此请确保您使用的是最新的 Boost 版本,包括相关的 header,为 3 参数示例定义缺失的 operator()
重载,您的代码应该可以编译。
出于某种原因,使用 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
函数?
您正在查看 Boost 1.36 的文档,它是 released in 2008. If you look at the 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);
文档还指出
Overloads accepting three or more operands invoke the function call operator of the given visitor on the content of the given variant operands. ... Those functions are actually defined in a header
boost/variant/multivisitors.hpp
... That header must be manually included if multi visitors are meant for use.
因此请确保您使用的是最新的 Boost 版本,包括相关的 header,为 3 参数示例定义缺失的 operator()
重载,您的代码应该可以编译。