绑定pretty打印机与升压迭代时的boost ::凤演员::融合 [英] Binding a pretty-printer to boost::phoenix actors when iterating with boost::fusion

查看:219
本文介绍了绑定pretty打印机与升压迭代时的boost ::凤演员::融合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这问题是一个后续<一个href=\"http://stackoverflow.com/questions/35893937/pointers-to-class-members-when-iterating-with-boostfusion/35898342#35898342\">Pointers类成员的boost ::融合,在那里接受的解决方案迭代工作时。

This question is a follow-up to Pointers to class members when iterating with boost::fusion, where the accepted solution works.

现在,我想不仅给(原始)值添加到属性映射,但使用pretty打印机,以提高是如何显示的值。该机制也将在此时使用的值是不平凡的打印

Now, I want not only to add the (primitive) values to the property-map, but use a pretty-printer to improve how the values are displayed. This mechanism will also be used in case the values are not trivial to print.

所以,有一些pretty打印机是这样的:

So, there is some pretty-printer like this:

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

template<>
std::string prettyPrinter(const std::string& s)
{
    return "The string id: " + s;
}

template<>
std::string prettyPrinter(const int& i)
{
    return "The int id: " + std::to_string(i);
}

和我通过绑定prettyPrinter到的boost ::凤凰男主角扩大从previous问题解决方案:

and I expanded the solution from the previous question by binding the prettyPrinter to the boost::phoenix actor:

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

struct Edge {
    int id;
};

BOOST_FUSION_ADAPT_STRUCT(Vertex, id)
BOOST_FUSION_ADAPT_STRUCT(Edge, id)

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

    using Bundle = typename property_map<T_Graph, Tag>::type;
    using T_Seq  = typename 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();
            using TempType = typename fusion::result_of::value_at<T_Seq, decltype(i)>::type;

            //
            // Interesting part starts here:
            //
            dp.property(
                name,
                make_transform_value_property_map(
                    phoenix::bind(
                        prettyPrinter<TempType>,
                        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);
}

什么我现在寻找的是一个更优雅的解决方案的可能性,因为@sehe指出int类型的评论,在使用凤凰::绑定可能不是最佳的事在这里。

What I am now looking for is the possibility of a more elegant solution, since @sehe pointed out int a comment, that using phoenix::bind might not be the optimal thing to do here.

推荐答案

c您显示有在$ C $一些随机误差。在没有 prettyPrinter 重载将汇编。还有如 SEQ 没有这样的事情。你适应的结构为不存在的成员。

There are some random errors in the code you show. None of the prettyPrinter overloads would compile. There's no such thing as Seq. You adapt the structs for members that don't exist.

所有这些事情放在一边,你在这里竞相一种次优行:函数模板和专业不拌匀(的为什么不专门函数模板,[HSutter,2001 ¹)。

All these things aside, you are racing a suboptimal line here: function templates and specializations don't mix well (Why not specialize function templates, [HSutter,2001]¹).

您似乎对的硬编码意图的你的类型,以及在pretty打印逻辑。

You seem intent on hard-coding your types as well as the pretty-print logic.

口头禅

类型推演和ADL是你的朋友可扩展的机制。

我会写在pretty打印接口大致是:

I'd write the pretty print interface roughly like:

#include <string>

namespace pretty_printing
{
    namespace default_impl {
        std::string do_pretty_print(const std::string& s) {
            return "The string id: " + s;
        }

        std::string do_pretty_print(const int i) {
            return "The int id: " + std::to_string(i);
        }
    }

    struct pretty_print_f {
        using result_type = std::string;

        template <typename T> result_type operator()(T&& v) const { 
            using namespace default_impl; // enable ADL
            return do_pretty_print(std::forward<T>(v));
        }
    };
}

您现在可以超载 DO_ pretty_print


  • 在你想要的任何方式(包括通过提供通用的过载)

  • 在安全的地方,就像为朋友你的类型的成员,或(模板)在你的类型相关联的命名空间(S)功能

  • in any way you want (including by providing generic overloads)
  • in safe places, like as friend members of your types, or as (template) functions in the associated namespace(s) of your types

他们会神奇地在 POI

现在,我建议使用的boost ::凤::功能&LT;&GT; 而不是的boost ::凤凰::绑定来的更清洁的呼叫到达现场:

Now, I suggest using boost::phoenix::function<> instead of boost::phoenix::bind to arrive at a much cleaner call-site:

auto name = fusion::extension::struct_member_name<T_Seq, i>::call();
px::function<pretty_printing::pretty_print_f> pretty_print;

dp.property(
    name,
    make_transform_value_property_map(pretty_print(px::at_c<i>(arg1)), bundle)
);

键简化是为了让编译器做它最擅长的:用推测参数类型重载

Key to the simplification is to let the compiler do what it does best: overload resolution with deduced argument types.

<大骨节病> 住在Coliru

#include <string>

namespace pretty_printing
{
    namespace default_impl {
        std::string do_pretty_print(const std::string& s) {
            return "The string id: " + s;
        }

        std::string do_pretty_print(const int i) {
            return "The int id: " + std::to_string(i);
        }
    }

    struct pretty_print_f {
        using result_type = std::string;

        template <typename T> result_type operator()(T&& v) const { 
            using namespace default_impl;
            return do_pretty_print(std::forward<T>(v));
        }
    };
}

#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 {
    int more;
    std::string 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;
    namespace px = boost::phoenix;
    using namespace px::arg_names;

    using Bundle = typename property_map<T_Graph, Tag>::type;
    using T_Seq  = typename 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();
            px::function<pretty_printing::pretty_print_f> pretty_print;

            dp.property(
                name,
                make_transform_value_property_map(pretty_print(px::at_c<i>(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);
}


¹参见GotW#49 http://www.gotw.ca/gotw/049。 HTM 和<一个href=\"http://stackoverflow.com/questions/7108033/template-specialization-vs-function-overloading?lq=1\">Template专业化VS函数重载例如

这篇关于绑定pretty打印机与升压迭代时的boost ::凤演员::融合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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