{"id":407,"date":"2024-10-29T19:10:00","date_gmt":"2024-10-29T19:10:00","guid":{"rendered":"https:\/\/permutationcity.co.uk\/bp\/?p=407"},"modified":"2024-10-28T19:13:28","modified_gmt":"2024-10-28T19:13:28","slug":"defer-again","status":"publish","type":"post","link":"https:\/\/permutationcity.co.uk\/bp\/2024\/10\/29\/defer-again\/","title":{"rendered":"Defer again"},"content":{"rendered":"\n<p>I written about <a href=\"https:\/\/permutationcity.co.uk\/bp\/2024\/05\/09\/in-what-order\/\"><code>defer<\/code><\/a> before.\nThis is a keyword that delays execution of a statement until the end of the block.\nIt&#8217;s designed to allow you to perform setup and immediately specify the associated clean up.\nI thought it made control flow a bit more confusing but\ncould be a useful tool.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"simple-implementation\">Simple implementation<\/h1>\n\n\n\n<p>C++ doesn&#8217;t have this keyword but we can implement something similar.<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-c++src&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C++&quot;,&quot;language&quot;:&quot;C++&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;cpp&quot;}\">class Deferred {\npublic:\n    using Function = std::function&lt;void()&gt;;\n    \n    Deferred(const Function&amp; function) :\n        m_Function(function) {\n    }\n    \n    ~Deferred() {\n        m_Function();\n    }\n    \nprivate:\n    Function m_Function;\n};<\/pre><\/div>\n\n\n\n<p>Which can be used like this:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-c++src&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C++&quot;,&quot;language&quot;:&quot;C++&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;cpp&quot;}\">    FILE* file = fopen(filename, &quot;r&quot;);\n    Deferred deferred([&amp;file]() { fclose(file); });<\/pre><\/div>\n\n\n\n<p>You can add a bit more flexibility with another constructor:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-c++src&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C++&quot;,&quot;language&quot;:&quot;C++&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;cpp&quot;}\">    ...\n    template &lt;typename Function, typename Value&gt;\n    Deferred(const Function&amp; function, Value&amp; value) :\n        Deferred([&amp;function, &amp;value]() { function(value); }) {\n    }\n    ...<\/pre><\/div>\n\n\n\n<p>That gives you the option to pass a function and value rather then forcing you to use a closure:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-c++src&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C++&quot;,&quot;language&quot;:&quot;C++&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;cpp&quot;}\">    FILE* file = fopen(filename, &quot;r&quot;);\n    Deferred deferred(fclose, file);<\/pre><\/div>\n\n\n\n<p>You can even get it to work with function that takes an arbitrary number of values.\nI won&#8217;t go down a template rabbit hole here though.\nIn either case the file will be closed at the end of the scope.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"nested-blocks\">Nested blocks<\/h2>\n\n\n\n<p>Today I came across a more complicated situation.\nEffectively it was something like this:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-c++src&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C++&quot;,&quot;language&quot;:&quot;C++&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;cpp&quot;}\">    FILE* file = nullptr;\n    if (useFile) {\n        file = fopen(filename, &quot;r&quot;);\n    }\n    \/\/ Do other things.\n    ...\n    if (useFile) {\n        fclose(file);\n    }<\/pre><\/div>\n\n\n\n<p>It&#8217;s not complicated.\nWe <em>might<\/em> have opened a file but we still want to be sure that it&#8217;s closed.\nWe can&#8217;t use <code>Deferred<\/code> in the same way.\nIf we declare <code>deferred<\/code> inside the if-statement then it will close the file too early.\nIf we declare <code>deferred<\/code> outside the if-statement then the file might not have been opened.<\/p>\n\n\n\n<p>However we can extend our original class to cope. I&#8217;ll skip the templates for simplicity:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-c++src&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C++&quot;,&quot;language&quot;:&quot;C++&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;cpp&quot;}\">class Deferred {\npublic:\n    using Function = std::function&lt;void()&gt;;\n    \n    Deferred() = default;\n    \n    Deferred(const Function&amp; function) {\n        Add(function)\n    }\n    \n    ...\n    \n    ~Deferred() {\n        for (const auto&amp; function : std::ranges::reverse(m_Functions)) {\n            function();\n        }\n    }\n    \n    void Add(const Function&amp; function) {\n        m_Functions.push_back(function);\n    }\n    \n    ...\n    \nprivate:\n    std::vector&lt;Function&gt; m_Functions;\n};<\/pre><\/div>\n\n\n\n<p>This means we can easily cope with the nested blocks:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-c++src&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C++&quot;,&quot;language&quot;:&quot;C++&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;cpp&quot;}\">    Deferred deferred;\n    FILE* file = nullptr;\n    if (useFile) {\n        file = fopen(filename, &quot;r&quot;);\n        deferred.Add(fclose, file);\n    }\n    \/\/ Do other things.\n    ...\n<\/pre><\/div>\n\n\n\n<p>This means a single <code>Deferred<\/code> variable can clean up any number of things at the end of the scope.<\/p>\n\n\n\n<p>One thing to watch for is the lifetime of any variables you are cleaning up. Any variables declared after <code>deferred<\/code> will have their own destructor called first. That doesn&#8217;t matter in this instance, <code>file<\/code> doesn&#8217;t have a destructor. However it were <code>stream<\/code> instead then it <em>would<\/em> have a destructor.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"in-the-end\">In the end<\/h2>\n\n\n\n<p>This isn&#8217;t just limited to nested blocks. It&#8217;s suitable for any clean up you want to do later, as long as <code>Deferred<\/code> can have the appropriate lifetime. I suspect it&#8217;s possible to overuse this. If you can manage to have a simple constructor and destructor in your classes then that&#8217;s better, fewer layers of code to understand. This is probably most useful when you can&#8217;t make a simple destructor, such as interfacing with external systems.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I written about defer before. This is a keyword that delays execution of a statement until the end of the block. It&#8217;s designed to allow you to perform setup and immediately specify the associated clean up. I thought it made control flow a bit more confusing but could be a useful tool. Simple implementation C++ [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_import_markdown_pro_load_document_selector":0,"_import_markdown_pro_submit_text_textarea":"","footnotes":""},"categories":[1],"tags":[26],"class_list":["post-407","post","type-post","status-publish","format-standard","hentry","category-general","tag-languages"],"_links":{"self":[{"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/posts\/407","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/comments?post=407"}],"version-history":[{"count":1,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/posts\/407\/revisions"}],"predecessor-version":[{"id":408,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/posts\/407\/revisions\/408"}],"wp:attachment":[{"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/media?parent=407"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/categories?post=407"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/tags?post=407"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}