{"id":967,"date":"2015-02-02T00:38:07","date_gmt":"2015-02-02T08:38:07","guid":{"rendered":"http:\/\/www.elbeno.com\/blog\/?p=967"},"modified":"2015-06-30T21:17:19","modified_gmt":"2015-07-01T04:17:19","slug":"how-to-print-anything-in-c-part-4","status":"publish","type":"post","link":"https:\/\/www.elbeno.com\/blog\/?p=967","title":{"rendered":"How to print anything in C++ (part 4)"},"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>Callable things. There are several types:<\/p>\n<ul>\n<li>functions<\/li>\n<li>member functions<\/li>\n<li><code>std::function<\/code>s<\/li>\n<li>bind expressions<\/li>\n<li>lambdas<\/li>\n<li>objects that support <code>operator()<\/code> (function objects)<\/li>\n<\/ul>\n<p>So, going back to my tag code, so far (with everything I&#8217;ve added) and including callable things, it will look like:<\/p>\n<pre lang=\"cpp\">\r\ntemplate <typename T>\r\nusing stringifier_tag = std::conditional_t<\r\n  is_outputtable<T>::value,\r\n  is_outputtable_tag,\r\n  std::conditional_t<\r\n    is_callable<T>::value,\r\n    is_callable_tag,\r\n    std::conditional_t<\r\n      is_iterable<T>::value,\r\n      is_iterable_tag,\r\n      std::conditional_t<\r\n        is_pair<T>::value,\r\n        is_pair_tag,\r\n        std::conditional_t<\r\n          is_tuple<T>::value,\r\n          is_tuple_tag,\r\n          void>>>>>;\r\n<\/pre>\n<p>This is getting to be a large nested &#8220;if-statement&#8221;, but it&#8217;s easy to follow, and the compiler doesn&#8217;t mind, so I don&#8217;t. Basically, this is the preferential order I want to use for outputting things. But then I discovered something puzzling, that took me a while to figure out. (In my defence, I discovered it late at night when I was probably not too sharp!)<\/p>\n<pre lang=\"cpp\">\r\n\/\/ this outputs \"1\"!\r\ncout << [](){} << endl;\r\n<\/pre>\n<p>Lambdas (and in fact, functions) can be passed to <code>operator&lt;&lt;<\/code> - which means they'll get <code>is_outputtable_tag<\/code> and produce 1 when printed. Not good. I want to print \"&lt;callable (function)&gt;\" or \"&lt;callable (function object)&gt;\". (I'm OK with lambdas and function objects coinciding here.) So why does printing a plain lambda work at all? Well, the answer (which took me too long to see, and doubtless you, learned reader, have already seen) is that a non-capturing lambda has an implicit conversion to a function pointer. And that, like all pointers, has an implicit conversion to <code>bool<\/code>. Anything non-zero (like a perfectly good pointer) is <code>true<\/code>, and when you print <code>true<\/code> (without using <code>boolalpha<\/code>), you get 1.<\/p>\n<p>Hm. Think think think.<\/p>\n<p>So, I think there is going to be a compromise here. And that compromise is going to be triggered if someone deliberately writes a function object with a conversion to <code>bool<\/code> and supporting <code>operator&lt;&lt;<\/code>. Because lambdas have <code>operator()<\/code> and a conversion to <code>bool<\/code>, and I don't want to use <code>operator&lt;&lt;<\/code> on them. So, it's <code>void_t<\/code> to the rescue again, and by now I have macroed the detection code.<\/p>\n<pre lang=\"cpp\">\r\n#define SFINAE_DETECT(name, expr)                \\\r\n  template <typename T>                          \\\r\n  using name##_t = decltype(expr);               \\\r\n  template <typename T, typename = void>         \\\r\n  struct has_##name : public std::false_type {}; \\\r\n  template <typename T>                          \\\r\n  struct has_##name<T, void_t<name##_t<T>>>      \\\r\n    : public std::true_type {};\r\n<\/pre>\n<p>I want to know if something's implicitly convertible to <code>bool<\/code>:<\/p>\n<pre lang=\"cpp\">\r\nvoid bool_conversion_test(bool);\r\nSFINAE_DETECT(bool_conversion, \r\n              bool_conversion_test(std::declval<T>()))\r\n<\/pre>\n<p>I don't need to implement anything for <code>bool_conversion_test<\/code> because it's never called, just used to check well-formedness of conversion. I also want to know if something has a function call operator:<\/p>\n<pre lang=\"cpp\">\r\nSFINAE_DETECT(call_operator, &T::operator())\r\n<\/pre>\n<p>And now I can massage <code>is_outputtable<\/code> appropriately: something that has <code>operator&lt;&lt;<\/code> but is not a function and is not a function object convertible to <code>bool<\/code>:<\/p>\n<pre lang=\"cpp\">\r\ntemplate<typename T>\r\nusing is_outputtable = typename std::conditional<\r\n  has_operator_output<T>::value &&\r\n  !std::is_function<T>::value &&\r\n  !(has_call_operator<T>::value && has_bool_conversion<T>::value),\r\n  std::true_type, std::false_type>::type;\r\n<\/pre>\n<p>Now that I've eliminated the callable types from the outputtable types, the detection of a callable type is fairly straightforward, between what the STL gives me and what is easy to make myself:<\/p>\n<pre lang=\"cpp\">\r\ntemplate <typename T>\r\nstruct is_std_function : public std::false_type {};\r\n\r\ntemplate <typename T>\r\nstruct is_std_function<std::function<T>> : public std::true_type {};\r\n\r\ntemplate<typename T>\r\nusing is_callable = typename std::conditional<\r\n  has_call_operator<T>::value\r\n  || is_std_function<T>::value\r\n  || std::is_function<T>::value\r\n  || std::is_bind_expression<T>::value,\r\n  std::true_type, std::false_type>::type;\r\n<\/pre>\n<p>And now all that's left is to distinguish between the callable types themselves for the purposes of printing. This can be done with judicious use of <code>std::enable_if<\/code>.<\/p>\n<pre lang=\"cpp\">\r\ntemplate <typename T>\r\nconstexpr static std::enable_if_t<is_std_function<T>::value, \r\n                                  const char*>\r\ncallable_type() { return \"(std::function)\"; }\r\n\r\ntemplate <typename T>\r\nconstexpr static std::enable_if_t<std::is_function<T>::value, \r\n                                  const char*>\r\ncallable_type() { return \"(function)\"; }\r\n\r\ntemplate <typename T>\r\nconstexpr static\r\nstd::enable_if_t<std::is_bind_expression<T>::value,\r\n                 const char*>\r\ncallable_type() { return \"(bind expression)\"; }\r\n\r\ntemplate <typename T>\r\nconstexpr static\r\nstd::enable_if_t<!is_std_function<T>::value && \r\n                  has_call_operator<T>::value,\r\n                 const char*>\r\ncallable_type() { return \"(function object)\"; }\r\n<\/pre>\n<p>Finally, I am ready to write the actual printing code for callable types.<\/p>\n<pre lang=\"cpp\">\r\ntemplate <typename T>\r\nstruct stringifier_select<T, is_callable_tag>\r\n{\r\n  explicit stringifier_select(T) {}\r\n\r\n  std::ostream& output(std::ostream& s) const\r\n  {\r\n    return s << \"<callable \"\r\n             << callable_type<T>()\r\n             << '>';\r\n  }\r\n};\r\n<\/pre>\n<p>Phew!<\/p>\n<p>Recap: so far, we can print:<\/p>\n<ul>\n<li>things that have <code>operator&lt;&lt;<\/code><\/li>\n<li>containers<\/li>\n<li><code>pair<\/code> and <code>tuple<\/code><\/li>\n<li>callable things<\/li>\n<li>and by default, things that just say \"unknown\"<\/li>\n<\/ul>\n<p>Next, what to do about strings and arrays?<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Part 1 Part 2 Part 3 Part 4 Part 5 Postscript Callable things. There are several types: functions member functions std::functions bind expressions lambdas objects that support operator() (function objects) So, going back to my tag code, so far (with everything I&#8217;ve added) and including callable things, it will look&#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-967","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\/967","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=967"}],"version-history":[{"count":7,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/967\/revisions"}],"predecessor-version":[{"id":998,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/967\/revisions\/998"}],"wp:attachment":[{"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=967"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=967"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=967"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}