与升压::融合迭代时,指针类成员 [英] Pointers to class members when iterating with boost::fusion

查看:122
本文介绍了与升压::融合迭代时,指针类成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用捆绑像以下属性一个boost ::图:

I have a boost::graph that uses bundled properties like the following:

struct Vertex
{
    std::string id;
};

如果我想使用的boost :: dynamic_properties的信息(例如,用于graphml幅面打印),我可以使用类似的东西:

If I want to use this information in boost::dynamic_properties (e.g. for printing in graphml-format), I can use something like that:

template<typename T>
std::string myPrettyPrinter(const T& t);

int main()
{
    using namespace boost;
    MyGraph g;
    dynamic_properties dp;
    dp.property("id",
        make_transform_value_property_map(
            & myPrettyPrinter<std::string>,
            get(&Vertex::id, g)
        )
    );
}

由于捆绑的属性可能会改变未来,我想是通用对创作的的dynamic_properties 。因此,我使用boost ::融合

Since the bundled property might change in the future, I want to be generic about the creation of the dynamic_properties. Therefore, I use boost::fusion

struct Vertex
{
    std::string id;
};


BOOST_FUSION_ADAPT_STRUCT(
    Vertex,
    id
)


template<typename T>
std::string myPrettyPrinter(const T& t);


template <typename T_Seq, typename T_Graph>
void member_iterator(boost::dynamic_properties& dp, T_Graph& g)
{
    using namespace boost;
    using Indices = mpl::range_c<
        unsigned,
        0,
        fusion::result_of::size<T_Seq>::value
    >;

    fusion::for_each(
        Indices(),
        [&](auto i)
        {
            using I = decltype(i);
            dp.property(
                fusion::extension::struct_member_name<T_Seq, i>::call(),
                make_transform_value_property_map(
                    & myPrettyPrinter<
                        typename fusion::result_of::value_at<T_Seq, I>::type
                    >,
                    get(
                        // This works but is not generic,
                        // since it relies on the specific
                        // member name "id":
                        & T_Seq::id,
                        g
                    )
                )
            );
        }
    );
}


int main()
{
    MyGraph g;
    boost::dynamic_properties dp;
    member_iterator<Vertex>(dp, g);
}

我的问题是,我不能找到一种方法,当然preSS行&放大器; T_Seq :: ID 在一个通用的方法。我一直在寻找到融合::扩展:: struct_member_name ,但没有成功。

My problem is, that I can't find a way to express the line &T_Seq::id in a generic way. I have been looking into fusion::extension::struct_member_name, but was not successful.

我搜索任何一个通用的方法来取代有问题的线路或一个不同的方法完全遍历顶点

I search for either a generic way to replace the problematic line or a different approach entirely to iterate over the members of Vertex.

推荐答案

无论真棒现有的答案,我总是毫不犹豫地使用宏。

Regardless of the awesome existing answer, I always hesitate to use macros.

在这种情况下,我注意到,因为的boost :: property_map&LT的一切都变得困难,图表,标签&GT; 接口。我估摸着,你可以只使用了 vertex_bundle_t 代替。

In this case I noticed everything became difficult because of the boost::property_map<Graph, Tag> interface. I reckoned, you could just use the vertex_bundle_t instead.

下面是不使用宏都一个简单的演示,以及工程为顶点和边束。 (你可以删除调试输出,并添加pretty打印钩回)。

Here's a simple demo using no macros at all, and that works for the vertex and edge bundles. (You could remove the debug output and add the pretty print hook back in).

<大骨节病> 住在Coliru

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/find.hpp>
#include <boost/phoenix/fusion/at.hpp>
#include <boost/phoenix.hpp>
#include <boost/mpl/range_c.hpp>

#include <iostream>

struct Vertex {
    std::string id;
    int numeric_value;
};
struct Edge {
    std::string more;
    int awesome_sauce;
};

BOOST_FUSION_ADAPT_STRUCT(Vertex, id, numeric_value)
BOOST_FUSION_ADAPT_STRUCT(Edge, more, awesome_sauce)

template <typename Tag, typename T_Graph>
void member_iterator(boost::dynamic_properties& dp, T_Graph& g)
{
    using namespace boost;

    using Bundle = typename boost::property_map<T_Graph, Tag>::type;
    using T_Seq  = typename boost::property_traits<Bundle>::value_type;

    using Indices = mpl::range_c<unsigned, 0, fusion::result_of::size<T_Seq>::value>;

    fusion::for_each(
        Indices{},
        [&, bundle=get(Tag{}, g)](auto i) {
            auto name = fusion::extension::struct_member_name<T_Seq, i>::call();
            std::cout << "Adding " << name << "\n";

            dp.property(
                name,
                make_transform_value_property_map(phoenix::at_c<i>(phoenix::arg_names::arg1), bundle)
            );
        }
    );
}

using MyGraph = boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, Vertex, Edge>;

int main()
{
    MyGraph g;
    boost::dynamic_properties dp;

    member_iterator<boost::vertex_bundle_t>(dp, g);
    member_iterator<boost::edge_bundle_t>(dp, g);
}

打印

Adding id
Adding numeric_value
Adding more
Adding awesome_sauce

这篇关于与升压::融合迭代时,指针类成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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