{"id":109959,"date":"2024-07-08T07:00:00","date_gmt":"2024-07-08T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=109959"},"modified":"2024-06-24T10:07:25","modified_gmt":"2024-06-24T17:07:25","slug":"20240708-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20240708-00\/?p=109959","title":{"rendered":"What&#8217;s the point of <CODE>std::<WBR>monostate<\/CODE>? You can&#8217;t do anything with it!"},"content":{"rendered":"<p>C++17 introduced <code>std::<wbr \/>monostate<\/code>, and I used it <a title=\"In C++\/WinRT, how can I await multiple coroutines and capture the results?, part 3\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20240112-00\/?p=109267\"> as a placeholder to represent the results of a coroutine that produces nothing<\/a>. In the comments, Neil Rashbrook asked <a href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20240112-00\/?p=109267#comment-141049\"> what you are expected to do with a <code>std::<wbr \/>monostate<\/code><\/a>, seeing as has no members and only trivial member functions.<\/p>\n<p>The answer is &#8220;nothing&#8221;.<\/p>\n<p>The purpose of <code>std::<wbr \/>monostate<\/code> is to be a dummy type that does nothing. All instances are considered equal to each other. It is basically this:<\/p>\n<pre>struct monostate {};\r\n\/\/ plus relational operators and a hash specialization\r\n<\/pre>\n<p>You can see it in <a href=\"https:\/\/github.com\/llvm\/llvm-project\/blob\/22f6e97d24f6e7190a447fd60e11e8ea03fd8356\/libcxx\/include\/__variant\/monostate.h#L26C42-L26C42\"> libcxx (LLVM\/clang)<\/a>, <a href=\"https:\/\/github.com\/gcc-mirror\/gcc\/blob\/5d2a360f0a541646abb11efdbabc33c6a04de7ee\/libstdc%2B%2B-v3\/include\/std\/variant#L1237\"> libstdc++ (gcc)<\/a>, and <a href=\"https:\/\/github.com\/microsoft\/STL\/blob\/3eac329d1f614ecf138d96c22a3b02f87076bc4a\/stl\/inc\/xutility#L7126\"> stl (msvc)<\/a>.<\/p>\n<p>But what&#8217;s the point of a class that does nothing, and which you can do nothing with?<\/p>\n<p>You don&#8217;t use <code>monostate<\/code> because you want to do something. You use <code>monostate<\/code> when you <i>don&#8217;t want to do anything<\/i>.<\/p>\n<p>Its original purpose was to be used as the initial type in a <code>std::<wbr \/>variant<\/code> to allow it to be default-constructed in an empty state.<\/p>\n<pre>struct Widget\r\n{\r\n    \/\/ no default constructor\r\n    Widget(std::string const&amp; id);\r\n\r\n    \u27e6 other members \u27e7\r\n};\r\n\r\nstruct PortListener\r\n{\r\n    \/\/ default constructor has unwanted side effects\r\n    PortListener(int port = 80);\r\n\r\n    \u27e6 other members \u27e7\r\n};\r\n\r\nstd::variant&lt;Widget, PortListener&gt; thingie; \/\/ can't do this\r\n<\/pre>\n<p>The <code>std::variant<\/code>&#8216;s default constructor default-constructs its first alternative. Since <code>Widget<\/code> doesn&#8217;t have a default constructor, you can&#8217;t put it first. And <code>Port\u00adListener<\/code>&#8216;s default constructor has unwanted side effects, so we don&#8217;t want to put it first.<\/p>\n<p>Enter <code>std::<wbr \/>monostate<\/code>. You can put that guy first.<\/p>\n<pre>std::variant&lt;std::monostate, Widget, PortListener&gt; thingie;\r\n<\/pre>\n<p>The <code>thingie<\/code> default-constructs into a <code>monostate<\/code>. What can you do with a <code>monostate<\/code>? Nothing! Its job is just to be a dummy type that you can use when you are forced to provide a default-constructible type but don&#8217;t want to.<\/p>\n<p>In the case of a <code>std::<wbr \/>variant<\/code>, you can think of inserting <code>std::<wbr \/>monostate<\/code> as a way to add an &#8220;empty&#8221; state to a <code>variant<\/code>,\u00b9 saving you the trouble of having to create a <code>std::<wbr \/>optional&lt;std::<wbr \/>variant&lt;...&gt;&gt;<\/code>. You can treat the <code>std::<wbr \/>monostate<\/code> as the &#8220;empty&#8221; state.<\/p>\n<p>In our usage of <code>std::<wbr \/>monostate<\/code>, we used it as just a dummy type that stands in for <code>void<\/code>.\u00b2<\/p>\n<p>\u00b9 More precisely, a way to add <i>another<\/i> &#8220;empty&#8221; state to a <code>variant<\/code>. There is already an &#8220;empty&#8221; state for a <code>std::<wbr \/>variant<\/code>, known as <code>valueless_<wbr \/>by_<wbr \/>exception<\/code>. This state is wacky, though, so you want to avoid it as much as possible. Another topic for another day.<\/p>\n<p>\u00b2 Bonus reading: <a href=\"https:\/\/wg21.link\/p0146r1\"> Regular Void<\/a>, which has stalled.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Not doing anything with it is exactly the point.<\/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-109959","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Not doing anything with it is exactly the point.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109959","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=109959"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109959\/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=109959"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=109959"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=109959"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}