升压访问者模式::任何 [英] visitor pattern for boost::any

查看:166
本文介绍了升压访问者模式::任何的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现这个 https://gist.github.com/2945472 ,但我需要不依赖于c。将实施++ 11。我想我的手在将其转换为只使用升压,但我有一些麻烦。

I found this https://gist.github.com/2945472 but I need an implementation that does not depend on c++11. I tried my hand at converting it to use only boost, but I'm having some trouble.

下面是我想出了:

#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;
    }
}

我插入地图时得到一个bad_any_cast。不应该any_cast只有它 - 被称为>第二(X)?我在做什么错了?

I'm getting a bad_any_cast when inserting into the map. Shouldn't any_cast only be called by it->second(x) ? What am I doing wrong?

推荐答案

您不能施放 _1 T (在绑定前pression的时间)。

You can't cast _1 to T (at the time of the bind expression).

您需要一个懒惰的演员。也许是定义一个函数,并使用嵌套绑定前pression,或使用升压凤凰城自定义的 any_cast 演员。

You need a lazy cast. Perhaps define a function and use a nested bind expression, or use Boost Phoenix with a custom any_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;
}

打印输出:

fa(1)
fb(abc())
no visitor registered

这篇关于升压访问者模式::任何的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆