C++ 如何将`boost::static_visitor`实例传递给函数
我在项目中经常使用C++ 如何将`boost::static_visitor`实例传递给函数,c++,templates,boost,visitor,boost-variant,C++,Templates,Boost,Visitor,Boost Variant,我在项目中经常使用boost::variant。我的同事们现在想出了一个主意,通过传递特定的boost::static\u visitor实例来定制访问类型。她有如下代码: #include <boost/variant.hpp> #include <iostream> typedef boost::variant<int, std::string> TVar; struct Visitor1 : public boost::static_visitor&
boost::variant
。我的同事们现在想出了一个主意,通过传递特定的boost::static\u visitor
实例来定制访问类型。她有如下代码:
#include <boost/variant.hpp>
#include <iostream>
typedef boost::variant<int, std::string> TVar;
struct Visitor1 : public boost::static_visitor<int> {
template<typename T>
result_type operator()(const T&) {
return 42;
}
};
struct Visitor2 : public boost::static_visitor<int> {
template<typename T>
result_type operator()(const T&) {
return 21;
}
};
int adder(const boost::static_visitor<int>& visitor, const TVar& visitable) {
return visitable.apply_visitor(visitor) + 1;
}
int main(int argc, char **args) {
Visitor1 v1;
Visitor2 v2;
TVar x;
std::cout << adder(v1, x) << std::endl;
std::cout << adder(v2, x) << std::endl;
}
#包括
#包括
typedef boost::变型TVar;
结构访问者1:public boost::static\u访问者{
模板
结果类型运算符()(常量T&){
返回42;
}
};
结构访问者2:public boost::static\u访问者{
模板
结果类型运算符()(常量T&){
返回21;
}
};
整数加法器(常量boost::static_visitor&visitor、常量TVar&visitable){
返回访问表。应用_访问者(访问者)+1;
}
int main(int argc,char**args){
访问者1 v1;
访问者2 v2;
tvarx;
std::cout对于apply\u visitor
有一个重载,它只接受访问者。这将返回一个部分应用的函数对象,适合您的需要,我想:
此重载返回一个
就个人而言,我喜欢向访问者对象添加重载,如下所示:
struct MyVisitor {
typedef void result_type;
template <typename... Ts>
result_type operator()(boost::variant<Ts...> const& v) const {
return boost::apply_visitor(*this, v);
}
// optionally repeat for non-const `v`
// normal variant handling overloads
};
struct MyVisitor{
typedef void result_type;
模板
结果类型运算符()(boost::variant const&v)const{
返回boost::apply_visitor(*this,v);
}
//可选地对非常量'v重复此操作`
//正常变量处理重载
};
这样,您就可以简单地将访问者对象用作函数对象。static\u visitor
不是多态基类,不能这样对待。它的名字很简单:它是一个static(静态类型)访问者。需要将访问者的静态类型作为要调用的类型。请注意,这是不可避免的,因为成员函数模板不能是虚拟的。在您的情况下,这意味着adder
必须成为函数模板,由访问者类型模板化:
template <class Visitor>
int adder(const Visitor& visitor, const TVar& visitable) {
return visitable.apply_visitor(visitor) + 1;
}
从技术上讲,访问者本身已经是一个合适的可调用对象,因此即使没有显式使用apply\u visitor
,它也应该可以工作:
int main(int argc, char **args) {
Visitor1 v1;
Visitor2 v2;
TVar x;
std::cout << adder(v1, x) << std::endl;
std::cout << adder(v2, x) << std::endl;
}
intmain(intargc,char**args){
访问者1 v1;
访问者2 v2;
tvarx;
std::cout首先,您应该将访问者的操作符()重载标记为const
:
struct Visitor1 : public boost::static_visitor<int> {
template<typename T>
result_type operator()(const T&) const {
return 42;
}
};
struct Visitor2 : public boost::static_visitor<int> {
template<typename T>
result_type operator()(const T&) const {
return 21;
}
};
Ouch!太明显了。谢谢你的帮助。我真的不习惯这个模板。非常有趣。我甚至没有意识到这个调用。但我仍然不确定如何使用它。假设我有auto y=boost::apply\u visitor(v1)
。我如何将y
传递给我的加法器
函数?传递它就像传递可调用对象的任何位置一样(使用模板类型参数推断参数类型,或使用std::function
或类似方法清除该类型)非常感谢。我认为Angew已经向我展示了如何做到这一点。:-)事实上。这也是他的方法的一部分,似乎也是一个非常酷的解决方案。不幸的是,它没有编译。我的visual studio编译器有问题吗?它应该支持C++11。它说从boost::apply\u visitor\u t
转换为const std::函数&
不可能。我将传递的变量visitorApplier
作为常量引用。刚刚发现,您可以用adder(v1,x)
替换adder(boost::apply_visitor(v1,x)
。这样您甚至可以缩短解决方案。
struct Visitor1 : public boost::static_visitor<int> {
template<typename T>
result_type operator()(const T&) const {
return 42;
}
};
struct Visitor2 : public boost::static_visitor<int> {
template<typename T>
result_type operator()(const T&) const {
return 21;
}
};
template <typename T>
int adder(const T& visitor, const TVar& visitable) {
return visitable.apply_visitor(visitor) + 1;
}