{"id":100565,"date":"2018-12-26T07:00:00","date_gmt":"2018-12-26T22:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=100565"},"modified":"2019-03-13T00:12:50","modified_gmt":"2019-03-13T07:12:50","slug":"20181226-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20181226-00\/?p=100565","title":{"rendered":"Don&#8217;t forget: std::pair does lexicographical ordering, so you don&#8217;t have to"},"content":{"rendered":"<p>A feature perhaps not as widely known as I thought is that the <code>std::pair<\/code> type performs lexicographical ordering, so you don&#8217;t have to. <\/p>\n<pre>\n\/\/ Suppose we record versions as std::pair&lt;int, int&gt;\n\/\/ where the first is the major version\n\/\/ and the second is the minor version.\n\nstd::map&lt;ComponentId, std::pair&lt;int, int&gt;&gt; requiredVersions;\n\nbool IsSupported(ComponentId id, std::pair&lt;int, int&gt; actualVersion)\n{\n auto item = requiredVersions.find(id);\n if (item == requiredVersions.end()) {\n  return true;\n }\n\n auto&amp; requiredVersion = item-&gt;second;\n\n if (actualVersion.first &gt; requiredVersion.first ||\n     (actualVersion.first == requiredVersion.first &amp;&amp;\n      actualVersion.second &gt;= requiredVersion.second)) {\n  return true;\n }\n\n return false;\n}\n<\/pre>\n<p>First, we try to find the component in our list of required versions. If it&#8217;s not found, then the component has no version requirements, and we say, &#8220;Sure, it&#8217;s supported!&#8221; (This is just an example. Maybe you want to say that if it&#8217;s not on the list, then it&#8217;s not supported at all.) <\/p>\n<p>Otherwise, we check the actual version number against the required version. If the major version is greater, or if the major version is equal but the minor version is greater or equal, then we decide that we have met the minimum requirements. <\/p>\n<p>Writing the comparison of major and minor versions is <a HREF=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20040213-00\/?p=40633\">easy to get wrong<\/a>, <\/p>\n<p>So don&#8217;t write the code that&#8217;s easy to get wrong. Let the standard library do it. <\/p>\n<pre>\nbool IsSupported(ComponentId id, std::pair&lt;int, int&gt; actualVersion)\n{\n  auto item = requiredVersions.find(id);\n if (item == requiredVersions.end()) {\n  return true;\n }\n\n auto&amp; requiredVersion = item-&gt;second;\n\n <font COLOR=\"blue\">return actualVersion &gt;= requiredVersion;<\/font>\n}\n<\/pre>\n<p><b>Bonus chatter<\/b>: I saw this mistake in some code that used the <code>std::pair<\/code> as the key in a map. <\/p>\n<pre>\nstd::map&lt;std::pair&lt;int, int&gt;, CoolThing&gt; sortedThings;\n<\/pre>\n<p>The idea is that the cool things would be sorted by a sort key that behaved like major\/minor. The code compared the keys manually, presumably because the author didn&#8217;t think that <code>std::pair<\/code> supported the relational operators. <\/p>\n<p>But of course <code>std::pair<\/code> supports the relational operators bcause that&#8217;s one of the prerequisites for being the key of a <code>std::map<\/code>. (Okay, technically, <code>std::map<\/code> requires only <code>operator&lt;<\/code>, but once you have <code>operator&lt;<\/code>, you can synthesize the rest.) <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Let it do the comparing.<\/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-100565","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Let it do the comparing.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/100565","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=100565"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/100565\/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=100565"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=100565"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=100565"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}