C++ boost::any的访问者模式
我发现了这一点,但我需要一个不依赖于c++11的实现。我试着将其转换为仅使用boost,但遇到了一些问题 以下是我的想法:C++ boost::any的访问者模式,c++,boost,visitor-pattern,boost-any,C++,Boost,Visitor Pattern,Boost Any,我发现了这一点,但我需要一个不依赖于c++11的实现。我试着将其转换为仅使用boost,但遇到了一些问题 以下是我的想法: #include <boost/any.hpp> #include <boost/function.hpp> #include <boost/bind.hpp> #include <boost/lambda/lambda.hpp> #include <boost/unordered_map.hpp> struct
#include <boost/any.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/unordered_map.hpp>
struct type_info_hash {
std::size_t operator()(std::type_info const & t) const {
return t.hash_code();
}
};
struct equal_ref {
template <typename T> bool operator()(boost::reference_wrapper<T> a,boost::reference_wrapper<T> b) const {
return a.get() == b.get();
}
};
struct any_visitor {
boost::unordered_map<boost::reference_wrapper<std::type_info const>, boost::function<void(boost::any&)>, type_info_hash, equal_ref> fs;
template <typename T> void insert_visitor(boost::function<void(T)> f) {
try {
fs.insert(std::make_pair(boost::ref(typeid(T)), boost::bind(f, boost::any_cast<T>(boost::lambda::_1))));
} catch (boost::bad_any_cast& e) {
std::cout << e.what() << std::endl;
}
}
bool operator()(boost::any & x) {
boost::unordered_map<boost::reference_wrapper<std::type_info const>, boost::function<void(boost::any&)>, type_info_hash, equal_ref>::iterator it = fs.find(boost::ref(x.type()));
if (it != fs.end()) {
it->second(x);
return true;
} else {
return false;
}
}
};
struct abc {};
void fa(int i) { std::cout << "fa(" << i << ")" << std::endl; }
void fb(abc) { std::cout << "fb(abc())" << std::endl; }
int main() {
any_visitor f;
f.insert_visitor<int>(fa);
f.insert_visitor<abc>(fb);
std::vector<boost::any> xs;
xs.push_back(1);
xs.push_back(abc());
xs.push_back(1.5);
for (auto & x : xs) {
if (!f(x)) std::cout << "no visitor registered" << std::endl;
}
}
#包括
#包括
#包括
#包括
#包括
结构类型\u信息\u散列{
std::size\u t运算符()(std::type\u info const&t)const{
返回t.hash_代码();
}
};
结构等分参考{
模板bool运算符()(boost::reference_包装器a,boost::reference_包装器b)常量{
返回a.get()==b.get();
}
};
构造任何访问者{
boost::无序的_映射fs;
模板void insert_访问者(boost::函数f){
试一试{
insert(std::make_pair(boost::ref(typeid(T)),boost::bind(f,boost::any_cast(boost::lambda::_1));
}捕获(增强::坏的\u任何\u投射和e){
std::cout您不能将\u 1
强制转换为t
(在绑定表达式时)
您需要一个惰性强制转换。可以定义一个函数并使用嵌套的绑定表达式,或者使用Boost Phoenix和一个自定义的any\u cast
actor
以下是嵌套绑定方法:
#include <boost/any.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/unordered_map.hpp>
struct type_info_hash {
std::size_t operator()(std::type_info const & t) const {
return 42; // t.hash_code();
}
};
struct equal_ref {
template <typename T> bool operator()(boost::reference_wrapper<T> a,boost::reference_wrapper<T> b) const {
return a.get() == b.get();
}
};
struct any_visitor {
boost::unordered_map<boost::reference_wrapper<std::type_info const>, boost::function<void(boost::any&)>, type_info_hash, equal_ref> fs;
template <typename T> static T any_cast_f(boost::any& any) { return boost::any_cast<T>(any); }
template <typename T> void insert_visitor(boost::function<void(T)> f) {
try {
fs.insert(std::make_pair(boost::ref(typeid(T)), boost::bind(f, boost::bind(any_cast_f<T>, boost::lambda::_1))));
} catch (boost::bad_any_cast& e) {
std::cout << e.what() << std::endl;
}
}
bool operator()(boost::any & x) {
boost::unordered_map<boost::reference_wrapper<std::type_info const>, boost::function<void(boost::any&)>, type_info_hash, equal_ref>::iterator it = fs.find(boost::ref(x.type()));
if (it != fs.end()) {
it->second(x);
return true;
} else {
return false;
}
}
};
struct abc {};
void fa(int i) { std::cout << "fa(" << i << ")" << std::endl; }
void fb(abc) { std::cout << "fb(abc())" << std::endl; }
int main() {
any_visitor f;
f.insert_visitor<int>(fa);
f.insert_visitor<abc>(fb);
std::vector<boost::any> xs;
xs.push_back(1);
xs.push_back(abc());
xs.push_back(1.5);
for (auto it=xs.begin(); it!=xs.end(); ++it)
if (!f(*it)) std::cout << "no visitor registered" << std::endl;
}
尝试使用可扩展的任何
struct f_方法
{
typedef void(boost::mpl::_1::*签名)()const;
模板
结构包装器
:公共电话
{
void f()常量
{
返回此->调用(f_方法());
}
};
结构实现
{
void运算符()(int i)常量
{
std::您是否考虑过使用boost::variant
对哪些访问者提供开箱即用的支持?使用any
假定类型可以是任何类型,即类型系统中的所有类型。variant
假定您可能希望在对象中使用类型的子集。访问者更接近一个变量
作为不同的函数必须被定义。我的意图是使用它从boost::program\u options中写出配置文件,它使用boost::any。注意,我替换了类型\u info\u散列函数体,让它在我的系统上编译。嵌套的绑定表达式rock,尽管:)看起来我忘记删除-std=c++11标志了在处理这个问题时,我需要编写我自己的type\u info hash\u代码方法。我还没有删除main中循环中的“auto”。我也注意到了这些;但修复起来没有lambda->nested bind难:)(暗中拍摄:也许您想知道Boost扩展库是如何尝试进行可移植的typeinfo比较的,我记得为此阅读了相关文章:)
fa(1)
fb(abc())
no visitor registered
struct f_method
{
typedef void (boost::mpl::_1::* signature) () const;
template <typename T>
struct wrapper
: public T
{
void f() const
{
return this->call(f_method());
}
};
struct implementation
{
void operator() (int i) const
{
std::cout << "fa(" << i << ")" << std::endl;
}
void operator() (abc) const
{
std::cout << "fb(abc())" << std::endl;
}
template <typename T>
void operator() (const T& t) const
{
std::cout << "Errr" << std::endl;
}
};
};
typedef xany<boost::mpl::list<f_method> > any;
int main() {
std::vector<any> xs;
xs.push_back(1);
xs.push_back(abc());
xs.push_back(1.5);
for (auto it=xs.begin(); it!=xs.end(); ++it)
(*it).f();
}