{"id":993,"date":"2015-02-02T22:22:45","date_gmt":"2015-02-03T06:22:45","guid":{"rendered":"http:\/\/www.elbeno.com\/blog\/?p=993"},"modified":"2015-06-30T21:17:04","modified_gmt":"2015-07-01T04:17:04","slug":"how-to-print-anything-in-c-postscript","status":"publish","type":"post","link":"https:\/\/www.elbeno.com\/blog\/?p=993","title":{"rendered":"How to print anything in C++ (postscript)"},"content":{"rendered":"<p><a href=\"https:\/\/www.elbeno.com\/blog\/?p=951\">Part 1<\/a> <a href=\"https:\/\/www.elbeno.com\/blog\/?p=958\">Part 2<\/a> <a href=\"https:\/\/www.elbeno.com\/blog\/?p=964\">Part 3<\/a> <a href=\"https:\/\/www.elbeno.com\/blog\/?p=967\">Part 4<\/a> <a href=\"https:\/\/www.elbeno.com\/blog\/?p=973\">Part 5<\/a> <a href=\"https:\/\/www.elbeno.com\/blog\/?p=993\">Postscript<\/a><\/p>\n<p>Refactoring! My initial plan for customizing opener\/closer\/separator for containers turned out to be unwieldy: I realized that it wouldn&#8217;t be possible for me to provide default specializations and also allow clients to specialize. Also, you may have noticed that the code for printing <code>pair<\/code>s, <code>tuple<\/code>s, strings and arrays didn&#8217;t allow for customization at all. So I reworked the customization, allowing a formatter object as a parameter to <code>prettyprint()<\/code> and providing a default one:<\/p>\n<pre lang=\"cpp\">\r\ntemplate <typename T>\r\ninline stringifier<std::remove_reference_t<T>, default_formatter>\r\nprettyprint(T&& t)\r\n{\r\n  return stringifier<std::remove_reference_t<T>, default_formatter>(\r\n      std::forward<T>(t), default_formatter());\r\n}\r\n\r\ntemplate <typename T, typename F>\r\ninline stringifier<std::remove_reference_t<T>, F>\r\nprettyprint(T&& t, F&& f)\r\n{\r\n  return stringifier<std::remove_reference_t<T>, F>(\r\n      std::forward<T>(t), std::forward<F>(f));\r\n}\r\n<\/pre>\n<p>The <code>default_formatter<\/code> looks like this:<\/p>\n<pre lang=\"cpp\">\r\nstruct default_formatter\r\n{\r\n  \/\/ default separator, opener and closer\r\n  template <typename T>\r\n  constexpr const char* separator(const T&) const\r\n  { return \",\"; }\r\n\r\n  template <typename T>\r\n  constexpr const char* opener(const T&) const\r\n  { return \"{\"; }\r\n\r\n  template <typename T>\r\n  constexpr const char* closer(const T&) const\r\n  { return \"}\"; }\r\n\r\n  \/\/ use [] for vectors\r\n  template <typename T>\r\n  constexpr const char* opener(const std::vector<T>&) const\r\n  { return \"[\"; }\r\n\r\n  template <typename T>\r\n  constexpr const char* closer(const std::vector<T>&) const\r\n  { return \"]\"; }\r\n\r\n  \/\/ etc (more omitted)\r\n  ...\r\n};\r\n<\/pre>\n<p>And now I can pass the formatter object through to each specialization of <code>stringifier_select<\/code>, and use it appropriately for <code>pair<\/code>s, <code>tuple<\/code>s, strings and arrays, as well as iterables. When I want to override the formatter, I simply specify a new formatter type, implement the opener\/closer\/separator functions for the type in question the way I want to, and pass an instance to <code>prettyprint<\/code>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Part 1 Part 2 Part 3 Part 4 Part 5 Postscript Refactoring! My initial plan for customizing opener\/closer\/separator for containers turned out to be unwieldy: I realized that it wouldn&#8217;t be possible for me to provide default specializations and also allow clients to specialize. Also, you may have noticed that&#8230;<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[22,8],"tags":[],"class_list":["post-993","post","type-post","status-publish","format-standard","hentry","category-cpp","category-programming"],"_links":{"self":[{"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/993","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=993"}],"version-history":[{"count":5,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/993\/revisions"}],"predecessor-version":[{"id":1003,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/993\/revisions\/1003"}],"wp:attachment":[{"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=993"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=993"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=993"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}