{"id":103900,"date":"2020-06-22T07:00:00","date_gmt":"2020-06-22T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=103880"},"modified":"2020-07-02T06:51:31","modified_gmt":"2020-07-02T13:51:31","slug":"20200622-00-2","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20200622-00\/?p=103900","title":{"rendered":"Mundane std::tuple tricks: Getting started"},"content":{"rendered":"<p>The C++ standard library <code>tuple<\/code> is quite versatile. It&#8217;s a handy way of grabbing a bunch of types or values into a single unit, and the C++ standard library also provides a number of helpers to manipulate them.<\/p>\n<p>For example, <code>make_tuple<\/code> lets you manufacture a tuple from values, which is handy if you want to capture a template parameter pack into something you can manipulate.<\/p>\n<pre>[](auto... args)\r\n{\r\n auto args_tuple = std::make_tuple(std::move(args)...);\r\n}\r\n<\/pre>\n<p>We learned earlier that <code>std::tuple_element_t<\/code> lets you pluck a single type out of a tuple, and <code>std::get<\/code> lets you extract a single value.<\/p>\n<p>And then there&#8217;s <code>tuple_cat<\/code> which concatenates two tuples. Though it concatenates values, not types. But writing a version that concatenates types isn&#8217;t hard.<\/p>\n<pre>template&lt;typename T1, typename T2&gt; struct tuple_cat_helper;\r\ntemplate&lt;typename... T1, typename...T2&gt;\r\nstruct tuple_cat_helper&lt;std::tuple&lt;T1...&gt;, std::tuple&lt;T2...&gt;&gt;\r\n{\r\n    using type = std::tuple&lt;T1..., T2...&gt;;\r\n};\r\n\r\ntemplate&lt;typename T1, typename T2&gt;\r\nusing tuple_cat_t = typename tuple_cat_helper&lt;T1, T2&gt;::type;\r\n\r\n\/\/ example is std::tuple&lt;int, char, double&gt;\r\nusing example = tuple_cat_t&lt;std::tuple&lt;int&gt;,\r\n                            std::tuple&lt;char, double&gt;&gt;;\r\n<\/pre>\n<p>We define a templated <code>tuple_cat_helper<\/code> with a specialization that sucks out the tuple types and generates a new tuple whose types are the concatenation of the two type lists. And then we provide a type alias that reaches in and grabs the <code>type<\/code> dependent type.<\/p>\n<p>Or you can be sneaky and let the existing <code>tuple_cat<\/code> do the heavy lifting:<\/p>\n<pre>template&lt;typename T1, typename T2&gt;\r\nusing tuple_cat_t = decltype(std::tuple_cat(std::declval&lt;T1&gt;(),\r\n                                            std::declval&lt;T2&gt;()));\r\n<\/pre>\n<p>And since <code>tuple_cat<\/code> can concatenate multiple tuples, we can write<\/p>\n<pre>template&lt;typename... Tuples&gt;\r\nusing tuple_cat_t = decltype(std::tuple_cat(std::declval&lt;Tuples&gt;()...));\r\n<\/pre>\n<p>Getting more while doing less.<\/p>\n<p>This is all great for putting tuples together, but there&#8217;s nothing in the standard library for taking tuples apart.<\/p>\n<p>We&#8217;ll start that next time.<\/p>\n<p><b>Bonus chatter<\/b>: I wasn&#8217;t quite telling the truth when I said that <code>make_tuple<\/code> can capture a template parameter pack. We&#8217;ll come back to this issue later.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Concatenating tuples the hard way, and the easy way (or maybe it&#8217;s the lazy way).<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-103900","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Concatenating tuples the hard way, and the easy way (or maybe it&#8217;s the lazy way).<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/103900","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=103900"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/103900\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=103900"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=103900"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=103900"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}