问题描述
这问题是一个后续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.
所有这些事情放在一边,你在这里竞相一种次优行:函数模板和专业不拌匀(的¹)。
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
他们会神奇地在 骨节病>
#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 和<一个href=\"http://stackoverflow.com/questions/7108033/template-specialization-vs-function-overloading?lq=1\">Template专业化VS函数重载例如
这篇关于绑定pretty打印机与升压迭代时的boost ::凤演员::融合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!