<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>What Comes to Mind</title><link>https://sdowney.org/</link><description>Stuff, and more stuff</description><atom:link href="https://sdowney.org/rss.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>Contents © 2026 &lt;a href="mailto:sdowney@sdowney.dev"&gt;Steve Downey&lt;/a&gt; 
 &lt;a rel="license" href="https://creativecommons.org/licenses/by-nc-sa/4.0/"&gt;
 &lt;img alt="Creative Commons License BY-NC-SA"
 style="border-width:0; margin-bottom:12px;"
 src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png"&gt;&lt;/a&gt;</copyright><lastBuildDate>Sat, 09 May 2026 17:32:01 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Building vcpkg dependencies with project toolchain</title><link>https://sdowney.org/posts/building-vcpkg-dependencies-with-project-toolchain/</link><dc:creator>Steve Downey</dc:creator><description>&lt;div class="abstract" id="orga59575d"&gt;
&lt;p&gt;
Making sure vcpkg delivers packages built with your toolchain is not hard, but much of the advice on the internet is flat wrong. You need to specify your toolchain both in your project and in the the vcpkg &lt;code&gt;triplet&lt;/code&gt;. There's an airgap between your project and the dependency in &lt;code&gt;vcpkg install&lt;/code&gt;. The CMake settings can't just flow through.
&lt;/p&gt;

&lt;/div&gt;

&lt;!-- TEASER_END --&gt;
&lt;div id="outline-container-orge9389ae" class="outline-2"&gt;
&lt;h2 id="orge9389ae"&gt;&lt;span class="section-number-2"&gt;1.&lt;/span&gt; Toolchain is more than just the compiler&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-1"&gt;
&lt;p&gt;
Inside a link context everything needs to use the same definitions for everything or your program breaks. If you are lucky it will fail to link. If you are unlucky it will link and explode at runtime. Or you might have the worst kind of undefined behavior–working the way you expect it to. For now.
&lt;/p&gt;

&lt;p&gt;
The &lt;a href="https://eel.is/c++draft/basic#def.odr-16"&gt;&lt;code&gt;One Definition Rule&lt;/code&gt;&lt;/a&gt; tries to say that all of the definitions in a program must mean the same thing. Using different flags for different translation units is a simple way of giving different meanings to definitions. This can range from preprocessor defines in the flags, to conditional compilation based on the compiler, or standard version, to subtle changes in meaning based on the standard version or other flags, such as the literal encoding to render characters and string constants into.
&lt;/p&gt;

&lt;p&gt;
The toolchain should encompass all of the ABI affecting flags, and most flags affect ABI, or at least codegen, in some way. Differing codegen, while not as dangerous as an ABI break, can still be an unpleasant surprise.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgf112aff" class="outline-2"&gt;
&lt;h2 id="orgf112aff"&gt;&lt;span class="section-number-2"&gt;2.&lt;/span&gt; Using a toolchain with &lt;code&gt;vcpkg&lt;/code&gt; in-project&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-2"&gt;
&lt;p&gt;
There are several techniques for using vcpkg for dependency management and specifying a toolchain to use for compilation of the artifacts in a project. For an open source project, the problem is generally how to do so without locking everyone into &lt;code&gt;vcpkg&lt;/code&gt;. The current theory for CMake is to provide dependency provider hooks via CMAKE_PROJECT_TOP_LEVEL_INCLUDES, which are a list of files cmake will process before anything else, and in particular before the &lt;code&gt;project&lt;/code&gt; statement. The Beman Project has a primitive dependency provider, &lt;a href="https://github.com/bemanproject/infra/blob/main/cmake/use-fetch-content.cmake"&gt;use-fetch-content.cmake&lt;/a&gt;, that converts &lt;code&gt;find_package&lt;/code&gt; into &lt;code&gt;FetchContent&lt;/code&gt; and downloads and builds from Git URLs. This is an alternative to vendoring dependencies in-tree directly using git submodules or git subtrees.
&lt;/p&gt;

&lt;p&gt;
As an aside, git submodules are like vice-grips–the wrong tool for every job.
&lt;/p&gt;

&lt;p&gt;
For &lt;code&gt;vcpkg&lt;/code&gt;, you can integrate using the same mechanism, setting CMAKE_PROJECT_TOP_LEVEL_INCLUDES to $(VCPKG_ROOT)/scripts/buildsystems/vcpkg.cmake. This is entirely in place of setting the CMAKE_TOOLCHAIN_FILE to vcpkg.cmake, including vcpkg.cmake in a local toolchain file, or using VCPKG_CHAINLOAD_TOOLCHAIN_FILE to instruct vcpkg.cmake to load a toolchain after processing the &lt;code&gt;triple&lt;/code&gt; file.
&lt;/p&gt;

&lt;p&gt;
The initial configure will look something like:
&lt;/p&gt;
&lt;div class="org-src-container"&gt;
&lt;pre class="src src-shell"&gt;&lt;code&gt;cmake -DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=$(VCPKG_ROOT)/scripts/buildsystems/vcpkg.cmake &lt;span class="org-sh-escaped-newline"&gt;\&lt;/span&gt;
      -DCMAKE_TOOLCHAIN_FILE=./etc/gcc-16-toolchain.cmake &lt;span class="org-sh-escaped-newline"&gt;\&lt;/span&gt;
      -B .build -S .
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
With the gcc-16 toolchain file looking something like:
&lt;/p&gt;
&lt;div class="org-src-container"&gt;
&lt;pre class="src src-cmake"&gt;&lt;code&gt;include_guard(GLOBAL)

set(CMAKE_C_COMPILER gcc-16)
set(CMAKE_CXX_COMPILER g++-16)
set(GCOV_EXECUTABLE "gcov-16" CACHE STRING "GCOV executable" FORCE)

set(CMAKE_CXX_STANDARD 26)

set(CMAKE_CXX_FLAGS
    "-Wall -Wextra -std=gnu++26 -Wno-maybe-uninitialized"
    CACHE STRING
    "CXX_FLAGS"
    FORCE)

set(CMAKE_CXX_FLAGS_DEBUG
    "-O0 -fno-inline -g3"
    CACHE STRING
    "C++ DEBUG Flags"
    FORCE
)
set(CMAKE_CXX_FLAGS_RELEASE
    "-Ofast -g0 -DNDEBUG"
    CACHE STRING
    "C++ Release Flags"
    FORCE
)
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO
    "-O3 -g -DNDEBUG"
    CACHE STRING
    "C++ RelWithDebInfo Flags"
    FORCE
)
set(CMAKE_CXX_FLAGS_TSAN
    "-O3 -g -fsanitize=thread"
    CACHE STRING
    "C++ TSAN Flags"
    FORCE
)
set(CMAKE_CXX_FLAGS_ASAN
    "-O3 -g -fsanitize=address,undefined,leak"
    CACHE STRING
    "C++ ASAN Flags"
    FORCE
)

set(CMAKE_CXX_FLAGS_GCOV
    "-O0 -fno-default-inline -fno-inline -g --coverage -fprofile-abs-path"
    CACHE STRING
    "C++ GCOV Flags"
    FORCE
)

set(CMAKE_LINKER_FLAGS_GCOV "--coverage" CACHE STRING "Linker GCOV Flags" FORCE)

get_filename_component(RPATH "~/.local/lib64" ABSOLUTE)

set(CMAKE_EXE_LINKER_FLAGS
    "-Wl,-rpath,${RPATH}"
    CACHE STRING
    "CMAKE_EXE_LINKER_FLAGS"
    FORCE
)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
This provides CMake build types &lt;code&gt;DEBUG&lt;/code&gt;, &lt;code&gt;RELEASE&lt;/code&gt;, &lt;code&gt;RELWITHDEBINFO&lt;/code&gt;, &lt;code&gt;TSAN&lt;/code&gt;, &lt;code&gt;ASAN&lt;/code&gt;, and &lt;code&gt;GCOV&lt;/code&gt;, overriding the built-in default flags. It exports the coverage processor to use, picked up by my project, and adds rpath to the linked executable to where I have the gcc-16 libstdc++.so.6 installed. GCC recently bumped the &lt;code&gt;GLIBCXX&lt;/code&gt; version number to 35, so it is no longer compatible with the system &lt;code&gt;libstdc++.so.6&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
Note that it doesn't have any vcpkg variables or includes.
&lt;/p&gt;

&lt;p&gt;
Building with the &lt;code&gt;cmake&lt;/code&gt; command line flags above will end up calling vcpkg for any packages mentioned in the &lt;code&gt;vcpkg.json&lt;/code&gt; file and providing them to be found by &lt;code&gt;find_package&lt;/code&gt; calls. It's not quite how a cmake dependency provider works, but functions very much the same. However, &lt;code&gt;vcpkg&lt;/code&gt; will build dependencies the way the system &lt;code&gt;triple&lt;/code&gt; defines things, which will be with the system compiler and default flags, and may be entirely incompatible with your project.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgc2d4f1d" class="outline-2"&gt;
&lt;h2 id="orgc2d4f1d"&gt;&lt;span class="section-number-2"&gt;3.&lt;/span&gt; Building Dependencies with your Toolchain.&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-3"&gt;
&lt;p&gt;
The mechanism &lt;code&gt;vcpkg&lt;/code&gt; provides for injecting a toolchain into a dependency is a custom &lt;code&gt;triple&lt;/code&gt; that provides a VCPKG_CHAINLOAD_TOOLCHAIN_FILE. Because of the intermediate invocation of &lt;code&gt;vcpkg&lt;/code&gt;, setting VCPKG_CHAINLOAD_TOOLCHAIN_FILE in your project does not affect how &lt;code&gt;vcpkg&lt;/code&gt; builds or provides anything.
&lt;/p&gt;

&lt;p&gt;
We can, however, smuggle the variable we need through the environment.
&lt;/p&gt;

&lt;p&gt;
The custom &lt;code&gt;triple&lt;/code&gt; I'm using, &lt;code&gt;x64-linux-custom.cmake&lt;/code&gt;,  looks like:
&lt;/p&gt;
&lt;div class="org-src-container"&gt;
&lt;pre class="src src-cmake"&gt;&lt;code&gt;set(VCPKG_TARGET_ARCHITECTURE x64)
set(VCPKG_CRT_LINKAGE dynamic)
set(VCPKG_LIBRARY_LINKAGE static)

set(VCPKG_CMAKE_SYSTEM_NAME Linux)

set(VCPKG_CHAINLOAD_TOOLCHAIN_FILE "$ENV{PROJECT_VCPKG_TOOLCHAIN}")
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
And I make sure to export PROJECT_VCPKG_TOOLCHAIN into the environment as part of my build. I use a Makefile to drive my project workflow, so it's straightforward to set and export. Other workflow mechanisms are an exercise for the reader.
&lt;/p&gt;

&lt;p&gt;
The cmake invocation picks up flags and environment:
&lt;/p&gt;
&lt;div class="org-src-container"&gt;
&lt;pre class="src src-shell"&gt;&lt;code&gt;&lt;span class="org-builtin"&gt;export&lt;/span&gt; &lt;span class="org-variable-name"&gt;PROJECT_VCPKG_TOOLCHAIN&lt;/span&gt;=$(realpath ./etc/gcc-16-toolchain.cmake)
cmake -DCMAKE_TOOLCHAIN_FILE=$(PROJECT_VCPKG_TOOLCHAIN) &lt;span class="org-sh-escaped-newline"&gt;\&lt;/span&gt;
      -DVCPKG_OVERLAY_TRIPLETS=$(realpath ./cmake) &lt;span class="org-sh-escaped-newline"&gt;\&lt;/span&gt;
      -DVCPKG_TARGET_TRIPLET=x64-linux-custom &lt;span class="org-sh-escaped-newline"&gt;\&lt;/span&gt;
      -B .build -S .
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
With this, &lt;code&gt;vcpkg&lt;/code&gt; will use the toolchain I specify to build dependencies. It also treats the VCPKG_CHAINLOAD_TOOLCHAIN_FILE as ABI significant for its build caching. This means that if you include other files into your toolchain, the contents of those files do not count. A small issue if you are using layered toolchain files, sharing some flags between them such as for gcc-15 vs gcc-16 in e.g. a gcc-flags.cmake file. But I also know switching between many compilers is a very minority use case.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org356d02d" class="outline-2"&gt;
&lt;h2 id="org356d02d"&gt;&lt;span class="section-number-2"&gt;4.&lt;/span&gt; Someone is Wrong on the Internet&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-4"&gt;
&lt;p&gt;
This took far longer to work out than it should because there is much advice that is flat out wrong.
&lt;/p&gt;

&lt;p&gt;
In particular from AI generated summaries and articles.
&lt;/p&gt;

&lt;p&gt;
Setting VCPKG_CHAINLOAD_TOOLCHAIN_FILE in your project or on the &lt;code&gt;cmake&lt;/code&gt; command line &lt;b&gt;cannot&lt;/b&gt; affect how &lt;code&gt;vcpkg&lt;/code&gt; builds and retrieves dependencies.
&lt;/p&gt;

&lt;p&gt;
You must set a custom &lt;code&gt;triple&lt;/code&gt; file that sets VCPKG_CHAINLOAD_TOOLCHAIN_FILE in order to use that CMake toolchain with &lt;code&gt;vcpkg&lt;/code&gt;.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description><guid>https://sdowney.org/posts/building-vcpkg-dependencies-with-project-toolchain/</guid><pubDate>Sat, 27 Dec 2025 17:03:15 GMT</pubDate></item><item><title>Substitution is Sometimes a Failure</title><link>https://sdowney.org/posts/substitution-is-sometimes-a-failure/</link><dc:creator>Steve Downey</dc:creator><description>&lt;div class="abstract" id="orgcd9f9b3"&gt;
&lt;p&gt;
Why are optional::transform and optional::and_then not constrained by &lt;code&gt;invocable&lt;/code&gt;?
&lt;/p&gt;

&lt;/div&gt;

&lt;!-- TEASER_END --&gt;
&lt;div id="outline-container-org3671e46" class="outline-2"&gt;
&lt;h2 id="org3671e46"&gt;&lt;span class="section-number-2"&gt;1.&lt;/span&gt; Optional "Monadic" Interface&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-1"&gt;
&lt;p&gt;
&lt;a href="http://wg21.link/P0798"&gt;Monadic operations for std::optional&lt;/a&gt;
&lt;/p&gt;
&lt;ul class="org-ul"&gt;
&lt;li&gt;&lt;code&gt;transform&lt;/code&gt; is the c++ spelling for &lt;code&gt;map&lt;/code&gt; or &lt;code&gt;fmap&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;and_then&lt;/code&gt; is monadic &lt;code&gt;bind&lt;/code&gt; for optional&lt;/li&gt;
&lt;li&gt;&lt;code&gt;or_else&lt;/code&gt; is dual to &lt;code&gt;and_then&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
&lt;code&gt;or_else&lt;/code&gt; also has:
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;
Constraints: &lt;code&gt;F&lt;/code&gt; models &lt;code&gt;invocable&lt;/code&gt; and &lt;code&gt;T&lt;/code&gt; models &lt;code&gt;{move,copy}_constructible&lt;/code&gt;.
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
&lt;code&gt;transform&lt;/code&gt; and &lt;code&gt;and_then&lt;/code&gt; do not.
&lt;/p&gt;

&lt;p&gt;
They don't work if you don't give them invocables, and rely on &lt;code&gt;invoke_result_t&lt;/code&gt; to compute the result. So why not constrain them?
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgb43aa03" class="outline-2"&gt;
&lt;h2 id="orgb43aa03"&gt;&lt;span class="section-number-2"&gt;2.&lt;/span&gt; SFINAE is shallow&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-2"&gt;
&lt;p&gt;
The problem is if another template has to be instantiated in order to evaluate the template of interest, and that template has an error, you get an error, not a substitution failure. And, it turns out, lambdas are a common source of the problem and a common case in real use.
&lt;/p&gt;

&lt;p&gt;
Consider the code:
&lt;/p&gt;
&lt;div class="org-src-container"&gt;
&lt;pre class="src src-c++"&gt;&lt;code&gt;&lt;span class="org-type"&gt;void&lt;/span&gt; &lt;span class="org-function-name"&gt;f&lt;/span&gt;(&lt;span class="org-type"&gt;int&lt;/span&gt;&amp;amp;);

&lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;l&lt;/span&gt; = [](&lt;span class="org-keyword"&gt;auto&lt;/span&gt;&amp;amp; &lt;span class="org-variable-name"&gt;y&lt;/span&gt;) {
    f(y);
    &lt;span class="org-keyword"&gt;return&lt;/span&gt; 42;
};
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
The two important parts are the &lt;code&gt;auto&amp;amp;&lt;/code&gt; parameter and the implicit deduced return type.
&lt;/p&gt;

&lt;p&gt;
We can rewrite it, to make things possibly more obvious:
&lt;/p&gt;
&lt;div class="org-src-container"&gt;
&lt;pre class="src src-c++"&gt;&lt;code&gt;&lt;span class="org-keyword"&gt;struct&lt;/span&gt; &lt;span class="org-type"&gt;Func&lt;/span&gt; {
    &lt;span class="org-keyword"&gt;template&lt;/span&gt; &amp;lt;&lt;span class="org-keyword"&gt;typename&lt;/span&gt; &lt;span class="org-type"&gt;T&lt;/span&gt;&amp;gt;
    &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-keyword"&gt;operator&lt;/span&gt;&lt;span class="org-function-name"&gt;()&lt;/span&gt;(&lt;span class="org-type"&gt;T&lt;/span&gt;&amp;amp; &lt;span class="org-variable-name"&gt;t&lt;/span&gt;) {
        f(t);
        &lt;span class="org-keyword"&gt;return&lt;/span&gt; 42;
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
and to slightly spoil things, the problem code is effectively:
&lt;/p&gt;
&lt;div class="org-src-container"&gt;
&lt;pre class="src src-c++"&gt;&lt;code&gt;&lt;span class="org-keyword"&gt;static_assert&lt;/span&gt;(&lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-type"&gt;invocable&lt;/span&gt;&amp;lt;Func, &lt;span class="org-type"&gt;int&lt;/span&gt; &lt;span class="org-keyword"&gt;const&lt;/span&gt;&amp;amp;&amp;gt;);
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
which produces:
&lt;/p&gt;
&lt;div class="org-src-container"&gt;
&lt;pre class="src src-c++"&gt;&lt;code&gt;&amp;lt;source&amp;gt;: In instantiation of &lt;span class="org-warning"&gt;'&lt;/span&gt;&lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-constant"&gt;Func&lt;/span&gt;::&lt;span class="org-keyword"&gt;operator&lt;/span&gt;()(&lt;span class="org-type"&gt;T&lt;/span&gt;&amp;amp;) [with T = &lt;span class="org-keyword"&gt;const&lt;/span&gt; &lt;span class="org-type"&gt;int&lt;/span&gt;]&lt;span class="org-warning"&gt;'&lt;/span&gt;:
type_traits:2565:26:   required by substitution of &lt;span class="org-warning"&gt;'&lt;/span&gt;&lt;span class="org-keyword"&gt;template&lt;/span&gt;&amp;lt;&lt;span class="org-keyword"&gt;class&lt;/span&gt; &lt;span class="org-type"&gt;_Fn&lt;/span&gt;, &lt;span class="org-keyword"&gt;class&lt;/span&gt; ... &lt;span class="org-type"&gt;_Args&lt;/span&gt;&amp;gt; &lt;span class="org-keyword"&gt;static&lt;/span&gt; &lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-type"&gt;__result_of_success&lt;/span&gt;&amp;lt;&lt;span class="org-keyword"&gt;decltype&lt;/span&gt; (declval&amp;lt;&lt;span class="org-type"&gt;_Fn&lt;/span&gt;&amp;gt;()((&lt;span class="org-type"&gt;declval&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;_Args&lt;/span&gt;&amp;gt;)()...)), &lt;span class="org-constant"&gt;std&lt;/span&gt;::__invoke_other&amp;gt; &lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-constant"&gt;__result_of_other_impl&lt;/span&gt;::_S_test(&lt;span class="org-type"&gt;int&lt;/span&gt;) [with _Fn = Func; _Args = {&lt;span class="org-keyword"&gt;const&lt;/span&gt; &lt;span class="org-type"&gt;int&lt;/span&gt;&amp;amp;}]&lt;span class="org-warning"&gt;'&lt;/span&gt;
type_traits:2576:55:   required from &lt;span class="org-warning"&gt;'&lt;/span&gt;&lt;span class="org-keyword"&gt;struct&lt;/span&gt; &lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-type"&gt;__result_of_impl&lt;/span&gt;&amp;lt;&lt;span class="org-constant"&gt;false&lt;/span&gt;, &lt;span class="org-constant"&gt;false&lt;/span&gt;, Func, &lt;span class="org-keyword"&gt;const&lt;/span&gt; &lt;span class="org-type"&gt;int&lt;/span&gt;&amp;amp;&amp;gt;&lt;span class="org-warning"&gt;'&lt;/span&gt;
type_traits:3038:12:   recursively required by substitution of &lt;span class="org-warning"&gt;'&lt;/span&gt;&lt;span class="org-keyword"&gt;template&lt;/span&gt;&amp;lt;&lt;span class="org-keyword"&gt;class&lt;/span&gt; &lt;span class="org-type"&gt;_Result&lt;/span&gt;, &lt;span class="org-keyword"&gt;class&lt;/span&gt; &lt;span class="org-type"&gt;_Ret&lt;/span&gt;&amp;gt; &lt;span class="org-keyword"&gt;struct&lt;/span&gt; &lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-type"&gt;__is_invocable_impl&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;_Result&lt;/span&gt;, &lt;span class="org-type"&gt;_Ret&lt;/span&gt;, &lt;span class="org-constant"&gt;true&lt;/span&gt;, &lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-type"&gt;__void_t&lt;/span&gt;&amp;lt;&lt;span class="org-keyword"&gt;typename&lt;/span&gt; &lt;span class="org-constant"&gt;_CTp&lt;/span&gt;::&lt;span class="org-type"&gt;type&lt;/span&gt;&amp;gt; &amp;gt; [&lt;span class="org-constant"&gt;with&lt;/span&gt; _Result = &lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-type"&gt;__invoke_result&lt;/span&gt;&amp;lt;Func, &lt;span class="org-keyword"&gt;const&lt;/span&gt; &lt;span class="org-type"&gt;int&lt;/span&gt;&amp;amp;&amp;gt;; _Ret = &lt;span class="org-type"&gt;void&lt;/span&gt;]&lt;span class="org-warning"&gt;'&lt;/span&gt;
type_traits:3038:12:   required from &lt;span class="org-warning"&gt;'&lt;/span&gt;&lt;span class="org-keyword"&gt;struct&lt;/span&gt; &lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-type"&gt;is_invocable&lt;/span&gt;&amp;lt;Func, &lt;span class="org-keyword"&gt;const&lt;/span&gt; &lt;span class="org-type"&gt;int&lt;/span&gt;&amp;amp;&amp;gt;&lt;span class="org-warning"&gt;'&lt;/span&gt;
type_traits:3286:71:   required from &lt;span class="org-warning"&gt;'&lt;/span&gt;&lt;span class="org-keyword"&gt;constexpr&lt;/span&gt; &lt;span class="org-keyword"&gt;const&lt;/span&gt; &lt;span class="org-type"&gt;bool&lt;/span&gt; &lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-type"&gt;is_invocable_v&lt;/span&gt;&amp;lt;Func, &lt;span class="org-keyword"&gt;const&lt;/span&gt; &lt;span class="org-type"&gt;int&lt;/span&gt;&amp;amp;&amp;gt;&lt;span class="org-warning"&gt;'&lt;/span&gt;
concepts:336:25:   required from &lt;span class="org-type"&gt;here&lt;/span&gt;
&amp;lt;source&amp;gt;:12:10: error: binding reference of type &lt;span class="org-warning"&gt;'&lt;/span&gt;&lt;span class="org-type"&gt;int&lt;/span&gt;&amp;amp;&lt;span class="org-warning"&gt;'&lt;/span&gt; to &lt;span class="org-warning"&gt;'&lt;/span&gt;&lt;span class="org-keyword"&gt;const&lt;/span&gt; &lt;span class="org-type"&gt;int&lt;/span&gt;&lt;span class="org-warning"&gt;'&lt;/span&gt; discards qualifiers
   12 |         f(t);
      |         ~^~~
&amp;lt;source&amp;gt;:2:12: note:   initializing argument 1 of &lt;span class="org-warning"&gt;'&lt;/span&gt;&lt;span class="org-type"&gt;void&lt;/span&gt; f(&lt;span class="org-type"&gt;int&lt;/span&gt;&amp;amp;)&lt;span class="org-warning"&gt;'&lt;/span&gt;
    2 |     &lt;span class="org-type"&gt;void&lt;/span&gt; f(&lt;span class="org-type"&gt;int&lt;/span&gt;&amp;amp;);
      |            ^~~~
Compiler returned: 1
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;a href="https://compiler-explorer.com/z/W1jT6bxrf"&gt;Compiler Explorer&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
as the compiler is unhappy about trying to call the function &lt;code&gt;f&lt;/code&gt; with a &lt;code&gt;const int&amp;amp;&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
If the lambda or &lt;code&gt;Func&lt;/code&gt; is changed to have a non-deduced return type, the instantiation errors from the check to &lt;code&gt;invocable&lt;/code&gt; go away, although you still get an error calling either with a &lt;code&gt;const int&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
So why do we run into this with &lt;code&gt;transform&lt;/code&gt; if we were to constrain it with &lt;code&gt;invocable&lt;/code&gt; ?
&lt;/p&gt;

&lt;p&gt;
The compiler needs to figure out the overload set in order to resolve which one to use from the set. There are four of them two for the l- and r- value category and two for the const overloads.
&lt;/p&gt;

&lt;div class="org-src-container"&gt;
&lt;pre class="src src-c++"&gt;&lt;code&gt;&lt;span class="org-keyword"&gt;template&lt;/span&gt;&amp;lt;&lt;span class="org-keyword"&gt;class&lt;/span&gt; &lt;span class="org-type"&gt;F&lt;/span&gt;&amp;gt; &lt;span class="org-keyword"&gt;constexpr&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-function-name"&gt;transform&lt;/span&gt;(&lt;span class="org-type"&gt;F&lt;/span&gt;&amp;amp;&amp;amp; &lt;span class="org-variable-name"&gt;f&lt;/span&gt;) &amp;amp;;
&lt;span class="org-keyword"&gt;template&lt;/span&gt;&amp;lt;&lt;span class="org-keyword"&gt;class&lt;/span&gt; &lt;span class="org-type"&gt;F&lt;/span&gt;&amp;gt; &lt;span class="org-keyword"&gt;constexpr&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-function-name"&gt;transform&lt;/span&gt;(&lt;span class="org-type"&gt;F&lt;/span&gt;&amp;amp;&amp;amp; &lt;span class="org-variable-name"&gt;f&lt;/span&gt;) &lt;span class="org-keyword"&gt;const&lt;/span&gt; &amp;amp;;
&lt;span class="org-keyword"&gt;template&lt;/span&gt;&amp;lt;&lt;span class="org-keyword"&gt;class&lt;/span&gt; &lt;span class="org-type"&gt;F&lt;/span&gt;&amp;gt; &lt;span class="org-keyword"&gt;constexpr&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-function-name"&gt;transform&lt;/span&gt;(&lt;span class="org-type"&gt;F&lt;/span&gt;&amp;amp;&amp;amp; &lt;span class="org-variable-name"&gt;f&lt;/span&gt;) &amp;amp;&amp;amp;;
&lt;span class="org-keyword"&gt;template&lt;/span&gt;&amp;lt;&lt;span class="org-keyword"&gt;class&lt;/span&gt; &lt;span class="org-type"&gt;F&lt;/span&gt;&amp;gt; &lt;span class="org-keyword"&gt;constexpr&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-function-name"&gt;transform&lt;/span&gt;(&lt;span class="org-type"&gt;F&lt;/span&gt;&amp;amp;&amp;amp; &lt;span class="org-variable-name"&gt;f&lt;/span&gt;) &lt;span class="org-keyword"&gt;const&lt;/span&gt; &amp;amp;&amp;amp;;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
with differing computations of the resulting &lt;code&gt;optional&lt;/code&gt; being returned.
&lt;/p&gt;
&lt;div class="org-src-container"&gt;
&lt;pre class="src src-c++"&gt;&lt;code&gt;&lt;span class="org-keyword"&gt;using&lt;/span&gt; &lt;span class="org-type"&gt;U&lt;/span&gt; = &lt;span class="org-type"&gt;invoke_result_t&lt;/span&gt;&amp;lt;F, &lt;span class="org-keyword"&gt;decltype&lt;/span&gt;(&lt;span class="org-constant"&gt;std&lt;/span&gt;​::​move(*val))&amp;gt;;
&lt;span class="org-comment-delimiter"&gt;//&lt;/span&gt;&lt;span class="org-comment"&gt;or
&lt;/span&gt;&lt;span class="org-keyword"&gt;using&lt;/span&gt; &lt;span class="org-type"&gt;U&lt;/span&gt; = &lt;span class="org-type"&gt;remove_cv_t&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;invoke_result_t&lt;/span&gt;&amp;lt;F, &lt;span class="org-keyword"&gt;decltype&lt;/span&gt;(*val)&amp;gt;&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
So, in order to work out what the templated &lt;code&gt;transform&lt;/code&gt;'s signature really is, it has to compute what the invocable returns, and since the invocable has deduced return type, it needs to instantiate it, and instantiating with &lt;code&gt;const int&lt;/code&gt; causes an error.
&lt;/p&gt;

&lt;p&gt;
This is unfortunate.
&lt;/p&gt;

&lt;p&gt;
If we constrain &lt;code&gt;transform&lt;/code&gt; we get the same errors as above. &lt;a href="https://compiler-explorer.com/z/r1qbjx4zG"&gt;See here,&lt;/a&gt; with just enough of an &lt;code&gt;optional&lt;/code&gt; to compile.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org9860d9a" class="outline-2"&gt;
&lt;h2 id="org9860d9a"&gt;&lt;span class="section-number-2"&gt;3.&lt;/span&gt; Constraints, what are they good for&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-3"&gt;
&lt;p&gt;
Not absolutely nothing.
&lt;/p&gt;

&lt;p&gt;
Constraints in the library:
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;
Constraints: the conditions for the function's participation in overload resolution ([over.match]).
&lt;/p&gt;

&lt;p&gt;
[Note 1: Failure to meet such a condition results in the function's silent non-viability. — end note]
&lt;/p&gt;

&lt;p&gt;
[Example 1: An implementation can express such a condition via a constraint-expression ([temp.constr.decl]). — end example]
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
&lt;a href="https://eel.is/c++draft/description#structure.specifications-3.1"&gt;[structure.specifications] 3.1&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
Constraints are for making an overload not exist if the constraint isn't met. It's not a way of signaling an error. Those are &lt;code&gt;Mandates&lt;/code&gt;:
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;
Mandates: the conditions that, if not met, render the program ill-formed.
&lt;/p&gt;

&lt;p&gt;
[Example 2: An implementation can express such a condition via the constant-expression in a static_assert-declaration ([dcl.pre]). If the diagnostic is to be emitted only after the function has been selected by overload resolution, an implementation can express such a condition via a constraint-expression ([temp.constr.decl]) and also define the function as deleted. — end example]
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
&lt;a href="https://eel.is/c++draft/description#structure.specifications-3.2"&gt;[structure.specifications] 3.2&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
Asking to run &lt;code&gt;and_then&lt;/code&gt; on a non-invocable probably ought not to say there is no such function, but instead tell you it can't be invoked. I'm now not convinced that &lt;code&gt;or_else&lt;/code&gt; should be constrained this way. It's not significantly better for &lt;code&gt;o.or_else(5)&lt;/code&gt; to fail to resolve, mentioning &lt;code&gt;invocable&lt;/code&gt;, than produce an error that &lt;code&gt;invoke_result_t&lt;/code&gt; doesn't work, or that &lt;code&gt;f&lt;/code&gt; can't be invoked. The kind of error is a minor detail.
&lt;/p&gt;

&lt;p&gt;
Constraints that let you control the choice of alternatives are wonderful, and requires clauses are normal programmer accessible, unlike SFINAE, or even &lt;code&gt;enable_if&lt;/code&gt;. But without an overload set to constrain, there possibly should not be a constraint.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org491ffac" class="outline-2"&gt;
&lt;h2 id="org491ffac"&gt;&lt;span class="section-number-2"&gt;4.&lt;/span&gt; Can we do better?&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-4"&gt;
&lt;p&gt;
There are some notes in &lt;a href="https://wg21.link/P0798"&gt;P0798&lt;/a&gt; that suggest that Deducing This might help, &lt;a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0847r7.html"&gt;P0847&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
The idea would to be to NOT have all the value category overloads that need to be checked, but to just have a single one that deduces what &lt;code&gt;this&lt;/code&gt; is and provide it as a template parameter for further use. The contained parameter could be forwarded using &lt;code&gt;forward_like&amp;lt;Self&amp;gt;&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
P0847 has discussion about how deducing this might be applied to optional. There's also discussion of deducing this and the SFINAE-unfriendly auto at &lt;a href="https://devblogs.microsoft.com/cppblog/cpp23-deducing-this/"&gt;C++23’s Deducing this: what it is, why it is, how to use it&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
With the tools we have today, it looks possible, but still slightly messy. I managed to get my implementation of optional to compile and pass its own tests with.
&lt;/p&gt;
&lt;div class="org-src-container"&gt;
&lt;pre class="src src-c++"&gt;&lt;code&gt;&lt;span class="org-keyword"&gt;template&lt;/span&gt; &amp;lt;&lt;span class="org-keyword"&gt;class&lt;/span&gt; &lt;span class="org-type"&gt;F&lt;/span&gt;, &lt;span class="org-keyword"&gt;class&lt;/span&gt; &lt;span class="org-type"&gt;Self&lt;/span&gt;&amp;gt;
    &lt;span class="org-keyword"&gt;requires&lt;/span&gt;(
        &lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-type"&gt;invocable&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;F&lt;/span&gt;,
                       &lt;span class="org-keyword"&gt;decltype&lt;/span&gt;(&lt;span class="org-constant"&gt;std&lt;/span&gt;::forward_like&amp;lt;&lt;span class="org-type"&gt;Self&lt;/span&gt;&amp;gt;(&lt;span class="org-constant"&gt;std&lt;/span&gt;::declval&amp;lt;T&amp;gt;()))&amp;gt;)
&lt;span class="org-keyword"&gt;constexpr&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;transform&lt;/span&gt;(&lt;span class="org-keyword"&gt;this&lt;/span&gt; Self&amp;amp;&amp;amp; self, &lt;span class="org-type"&gt;F&lt;/span&gt;&amp;amp;&amp;amp; &lt;span class="org-variable-name"&gt;f&lt;/span&gt;)
    -&amp;gt; &lt;span class="org-type"&gt;optional&lt;/span&gt;&amp;lt;&lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-type"&gt;invoke_result_t&lt;/span&gt;&amp;lt;
        &lt;span class="org-type"&gt;F&lt;/span&gt;,
        &lt;span class="org-keyword"&gt;decltype&lt;/span&gt;(&lt;span class="org-constant"&gt;std&lt;/span&gt;::forward_like&amp;lt;&lt;span class="org-type"&gt;Self&lt;/span&gt;&amp;gt;(&lt;span class="org-constant"&gt;std&lt;/span&gt;::declval&amp;lt;T&amp;gt;()))&amp;gt;&amp;gt; {
    &lt;span class="org-keyword"&gt;using&lt;/span&gt; &lt;span class="org-type"&gt;U&lt;/span&gt; = &lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-type"&gt;invoke_result_t&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;F&lt;/span&gt;,
                                   &lt;span class="org-keyword"&gt;decltype&lt;/span&gt;(&lt;span class="org-constant"&gt;std&lt;/span&gt;::forward_like&amp;lt;&lt;span class="org-type"&gt;Self&lt;/span&gt;&amp;gt;(
                                       &lt;span class="org-constant"&gt;std&lt;/span&gt;::declval&amp;lt;T&amp;gt;()))&amp;gt;;
    &lt;span class="org-keyword"&gt;static_assert&lt;/span&gt;(&lt;span class="org-negation-char"&gt;!&lt;/span&gt;&lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-type"&gt;is_array_v&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;U&lt;/span&gt;&amp;gt;);
    &lt;span class="org-keyword"&gt;static_assert&lt;/span&gt;(&lt;span class="org-negation-char"&gt;!&lt;/span&gt;&lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-type"&gt;is_same_v&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;U&lt;/span&gt;, &lt;span class="org-type"&gt;in_place_t&lt;/span&gt;&amp;gt;);
    &lt;span class="org-keyword"&gt;static_assert&lt;/span&gt;(&lt;span class="org-negation-char"&gt;!&lt;/span&gt;&lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-type"&gt;is_same_v&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;U&lt;/span&gt;, &lt;span class="org-type"&gt;nullopt_t&lt;/span&gt;&amp;gt;);
    &lt;span class="org-keyword"&gt;static_assert&lt;/span&gt;(&lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-type"&gt;is_object_v&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;U&lt;/span&gt;&amp;gt; || &lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-type"&gt;is_reference_v&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;U&lt;/span&gt;&amp;gt;);
    &lt;span class="org-keyword"&gt;if&lt;/span&gt; (self.has_value()) {
        &lt;span class="org-keyword"&gt;return&lt;/span&gt; &lt;span class="org-type"&gt;optional&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;U&lt;/span&gt;&amp;gt;{&lt;span class="org-constant"&gt;detail&lt;/span&gt;::from_function,
                           &lt;span class="org-constant"&gt;std&lt;/span&gt;::forward&amp;lt;&lt;span class="org-type"&gt;F&lt;/span&gt;&amp;gt;(f),
                           &lt;span class="org-constant"&gt;std&lt;/span&gt;::forward_like&amp;lt;&lt;span class="org-type"&gt;Self&lt;/span&gt;&amp;gt;(self.value_)};
    }
    &lt;span class="org-keyword"&gt;return&lt;/span&gt; &lt;span class="org-type"&gt;optional&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;U&lt;/span&gt;&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
If there were a &lt;code&gt;std::forward_like_t&lt;/code&gt;, it might be possible to reduce some of the noise in computing the value category used for the &lt;code&gt;T&lt;/code&gt;. I also have not thought extensively about if the requires clause is truly needed in light of the &lt;code&gt;invoke_result_&lt;/code&gt; that can now be used in the trailing return type.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description><guid>https://sdowney.org/posts/substitution-is-sometimes-a-failure/</guid><pubDate>Fri, 28 Nov 2025 17:06:58 GMT</pubDate></item><item><title>Nikola Blog Infrastructure</title><link>https://sdowney.org/posts/nikola-blog-infrastructure/</link><dc:creator>Steve Downey</dc:creator><description>&lt;div class="abstract" id="orgfd08afb"&gt;
&lt;p&gt;
I've migrated from WordPress to a static blog generator–Nikola. This is how it works.
&lt;/p&gt;

&lt;/div&gt;

&lt;!-- TEASER_END --&gt;
&lt;div id="outline-container-orgf140dcd" class="outline-2"&gt;
&lt;h2 id="orgf140dcd"&gt;&lt;span class="section-number-2"&gt;1.&lt;/span&gt; Nikola&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-1"&gt;
&lt;p&gt;
Nikola is a static site generator written in python. It's mostly boring, which is a very good thing for software meant for use to be. Its home is &lt;a href="https://getnikola.org"&gt;https://getnikola.org&lt;/a&gt; and the source is on github at &lt;a href="https://github.com/getnikola/nikola"&gt;https://github.com/getnikola/nikola&lt;/a&gt;. It's many years old at this point, but not dead.
&lt;/p&gt;

&lt;p&gt;
The interesting part for me is that someone had already written a plugin that compiled org mode files, my preferred markup language, to the html that Nikola wants to publish. It wasn't quite to my tastes, but the changes were all on the org export side in elisp, and the python invocation of emacs to do the translation didn't need particular changes. That update is at &lt;a href="https://github.com/steve-downey/wctm/tree/src/plugins/orgmode"&gt;https://github.com/steve-downey/wctm/tree/src/plugins/orgmode&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
I've also set up staging at a github pages repo rendered at &lt;a href="https://steve-downey.github.io/"&gt;https://steve-downey.github.io/&lt;/a&gt; since it's a static site. The real version is at &lt;a href="https://sdowney.org"&gt;https://sdowney.org&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
Conversion was straightforward using the tools that Nikola provided and &lt;a href="https://getnikola.com/handbook.html#importing-your-wordpress-site-into-nikola"&gt;following the directions&lt;/a&gt; for importing a WordPress xml backup.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgca8a0a9" class="outline-2"&gt;
&lt;h2 id="orgca8a0a9"&gt;&lt;span class="section-number-2"&gt;2.&lt;/span&gt; Orgmode plugin&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-2"&gt;
&lt;p&gt;
Pulling a plugin into my working site was easy
&lt;/p&gt;
&lt;div class="org-src-container"&gt;
&lt;pre class="src src-zsh"&gt;&lt;code&gt;nikola plugin -i orgmode
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
copied the code from &lt;a href="https://github.com/getnikola/plugins/tree/master/v8/orgmode"&gt;https://github.com/getnikola/plugins/tree/master/v8/orgmode&lt;/a&gt; and I just had to update the main configuration file, &lt;code&gt;conf.py&lt;/code&gt;, to map org files to the orgmode compiler.
&lt;/p&gt;
&lt;div class="org-src-container"&gt;
&lt;pre class="src src-python"&gt;&lt;code&gt;&lt;span class="org-variable-name"&gt;COMPILERS&lt;/span&gt; &lt;span class="org-operator"&gt;=&lt;/span&gt; {
    &lt;span class="org-string"&gt;"rest"&lt;/span&gt;: [&lt;span class="org-string"&gt;'.txt'&lt;/span&gt;, &lt;span class="org-string"&gt;'.rst'&lt;/span&gt;],
    &lt;span class="org-string"&gt;"markdown"&lt;/span&gt;: [&lt;span class="org-string"&gt;'.md'&lt;/span&gt;, &lt;span class="org-string"&gt;'.mdown'&lt;/span&gt;, &lt;span class="org-string"&gt;'.markdown'&lt;/span&gt;],
    &lt;span class="org-string"&gt;"html"&lt;/span&gt;: [&lt;span class="org-string"&gt;'.html'&lt;/span&gt;, &lt;span class="org-string"&gt;'.htm'&lt;/span&gt;],
    &lt;span class="org-string"&gt;"orgmode"&lt;/span&gt;: [&lt;span class="org-string"&gt;'.org'&lt;/span&gt;],
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
I then updated the source code for the elisp html exporter using code from &lt;a href="https://github.com/steve-downey/wg21org/blob/main/emacs.d/init.el"&gt;https://github.com/steve-downey/wg21org/blob/main/emacs.d/init.el&lt;/a&gt; which installs org from upstream rather than using the built-in orgmode and configures my preferences. I may end up using more of &lt;a href="https://github.com/steve-downey/wg21org/blob/main/ox-wg21html.el"&gt;ox-wg21html.el&lt;/a&gt; as a framework for the exported HTML, only updating to use Bootstrap for css classes instead of my own or the org builtin.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orge9d3c0a" class="outline-2"&gt;
&lt;h2 id="orge9d3c0a"&gt;&lt;span class="section-number-2"&gt;3.&lt;/span&gt; LaTeX support via KaTeX&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-3"&gt;
&lt;p&gt;
I've configure Nikola to support LaTeX via KaTeX rather than MathJax. It is supposed to be a bit faster. This means &lt;b&gt;inline&lt;/b&gt; math like \(x^2\) or \(1 &amp;lt; 2\) or with breaks like:
  \[
  \int_0^\infty e^{-x^2} dx = {{\sqrt{\pi}} \over {2}}
  \]
Or in running text where I want to mention \[ \frac{-b \pm \sqrt{b^2 - 4 a c}}{2a} \] as the quadratic equation.
It does mean I don't have access to latex blocks like
&lt;/p&gt;
&lt;div class="org-src-container"&gt;
&lt;pre class="src src-latex"&gt;&lt;code&gt;&lt;span class="org-keyword"&gt;\begin&lt;/span&gt;{&lt;span class="org-function-name"&gt;equation&lt;/span&gt;}
  n_{i+1} = &lt;span class="org-keyword"&gt;\frac&lt;/span&gt;{n_{i} (d-i) (e-1)}{(i+1)}
&lt;span class="org-keyword"&gt;\end&lt;/span&gt;{&lt;span class="org-function-name"&gt;equation&lt;/span&gt;}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Maybe I won't miss it.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description><guid>https://sdowney.org/posts/nikola-blog-infrastructure/</guid><pubDate>Mon, 23 Dec 2024 18:15:27 GMT</pubDate></item><item><title>Concept Maps using C++23 Library Tech</title><link>https://sdowney.org/posts/index.php/2024/05/19/concept-maps-using-c23-library-tech/</link><dc:creator>Steve Downey</dc:creator><description>&lt;div id="outline-container-orga2bfebe" class="outline-2"&gt;
&lt;h3 id="orga2bfebe"&gt;Abstract&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-orga2bfebe"&gt;
&lt;p&gt; C++0x Concepts had a feature &lt;code&gt;Concept Maps&lt;/code&gt; that allowed a set of functions, types, and template definitions to be associated with a concept and the map to be specialized for types that meet the concept. &lt;/p&gt;

&lt;p&gt; This allowed open extension of a concept. &lt;/p&gt;

&lt;!-- TEASER_END --&gt;

&lt;p&gt; A definition could be provided that allows an algorithm to operate in terms of the API a concept presents and the map would define how those operations are implemented for a particular type. &lt;/p&gt;

&lt;ul class="org-ul"&gt;
&lt;li&gt;This is similar to how Haskell's &lt;code&gt;typeclass&lt;/code&gt; works.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="notes" id="orgfd6f34c"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org55a2fab" class="outline-3"&gt;
&lt;h4 id="org55a2fab"&gt;Lost with &lt;code&gt;Concepts-Lite&lt;/code&gt;&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-org55a2fab"&gt;
&lt;div class="notes" id="org7de7f73"&gt;
&lt;p&gt; The feature was very general, and lost as part of the &lt;code&gt;Concepts-Lite&lt;/code&gt; proposal that was eventually adopted. &lt;/p&gt;

&lt;p&gt; This loss of a level of indirection means that the APIs for a concept must be implemented by those names for a type, even when those names are not particularly good choices in the natural domain of a type rather than in the domain as a concept. &lt;/p&gt;

&lt;p&gt; The proliferation of &lt;code&gt;transform&lt;/code&gt; functions for functorial &lt;code&gt;map&lt;/code&gt; is such a problem. &lt;/p&gt;

&lt;p&gt; It is also a problem when adapting types that are closed for extension or do not permit member functions. &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org1170181" class="outline-2"&gt;
&lt;h3 id="org1170181"&gt;Why?&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org1170181"&gt;
&lt;ul class="org-ul"&gt;
&lt;li&gt;&lt;p&gt; Don't know if you should &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;Need to know if you could first&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="notes" id="org00d3ad4"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgec4f485" class="outline-3"&gt;
&lt;h4 id="orgec4f485"&gt;Alternatives&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-orgec4f485"&gt;
&lt;ul class="org-ul"&gt;
&lt;li&gt;&lt;p&gt; Virtual Interface &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt; Adapters &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;Collection of CPOs&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="notes" id="org1416f27"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org63dbb2f" class="outline-3"&gt;
&lt;h4 id="org63dbb2f"&gt;Hard to Support&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-org63dbb2f"&gt;
&lt;div class="notes" id="org0c07886"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orga340186" class="outline-2"&gt;
&lt;h3 id="orga340186"&gt;Example from C++0x Concepts&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-orga340186"&gt;
&lt;/div&gt;
&lt;div id="outline-container-org28ca89a" class="outline-3"&gt;
&lt;h4 id="org28ca89a"&gt;Student Record&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-org28ca89a"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-C++" id="nil"&gt;&lt;span class="org-keyword"&gt;class&lt;/span&gt; &lt;span class="org-type"&gt;student&lt;/span&gt; &lt;span class="org-type"&gt;record&lt;/span&gt; {
&lt;span class="org-keyword"&gt;public&lt;/span&gt;:
  &lt;span class="org-type"&gt;string&lt;/span&gt; &lt;span class="org-variable-name"&gt;id&lt;/span&gt;;
  &lt;span class="org-type"&gt;string&lt;/span&gt; &lt;span class="org-variable-name"&gt;name&lt;/span&gt;;
  &lt;span class="org-type"&gt;string&lt;/span&gt; &lt;span class="org-variable-name"&gt;address&lt;/span&gt;;
  &lt;span class="org-type"&gt;bool&lt;/span&gt;   &lt;span class="org-function-name"&gt;id_equal&lt;/span&gt;(&lt;span class="org-keyword"&gt;const&lt;/span&gt; &lt;span class="org-type"&gt;student&lt;/span&gt; &lt;span class="org-type"&gt;record&lt;/span&gt;&amp;amp;);
  &lt;span class="org-type"&gt;bool&lt;/span&gt;   &lt;span class="org-function-name"&gt;name_equal&lt;/span&gt;(&lt;span class="org-keyword"&gt;const&lt;/span&gt; &lt;span class="org-type"&gt;student&lt;/span&gt; &lt;span class="org-type"&gt;record&lt;/span&gt;&amp;amp;);
  &lt;span class="org-type"&gt;bool&lt;/span&gt;   &lt;span class="org-function-name"&gt;address_equal&lt;/span&gt;(&lt;span class="org-keyword"&gt;const&lt;/span&gt; &lt;span class="org-type"&gt;student&lt;/span&gt; &lt;span class="org-type"&gt;record&lt;/span&gt;&amp;amp;);
};
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="notes" id="org3e8c3d9"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgaaad96e" class="outline-3"&gt;
&lt;h4 id="orgaaad96e"&gt;Equality Comparable&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-orgaaad96e"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;&lt;span class="org-type"&gt;concept_map&lt;/span&gt; &lt;span class="org-type"&gt;EqualityComparable&lt;/span&gt;&lt;span class="org-variable-name"&gt;&amp;lt;student record&amp;gt;&lt;/span&gt;{
    &lt;span class="org-type"&gt;bool&lt;/span&gt; &lt;span class="org-keyword"&gt;operator&lt;/span&gt;&lt;span class="org-variable-name"&gt;==&lt;/span&gt;(&lt;span class="org-keyword"&gt;const&lt;/span&gt; &lt;span class="org-type"&gt;student&lt;/span&gt; &lt;span class="org-type"&gt;record&lt;/span&gt;&amp;amp; &lt;span class="org-variable-name"&gt;a&lt;/span&gt;,
                    &lt;span class="org-keyword"&gt;const&lt;/span&gt; &lt;span class="org-type"&gt;student&lt;/span&gt; &lt;span class="org-type"&gt;record&lt;/span&gt;&amp;amp; &lt;span class="org-variable-name"&gt;b&lt;/span&gt;){
        &lt;span class="org-keyword"&gt;return&lt;/span&gt; a.id_equal(b);
}
};
&lt;/pre&gt;
&lt;/div&gt;

&lt;div class="notes" id="orgc2f233f"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgd6557c8" class="outline-3"&gt;
&lt;h4 id="orgd6557c8"&gt;Allow associated types&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-orgd6557c8"&gt;
&lt;p&gt; Very useful for pointers &lt;/p&gt;

&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;&lt;span class="org-type"&gt;concept_map&lt;/span&gt; &lt;span class="org-type"&gt;BinaryFunction&lt;/span&gt;&lt;span class="org-variable-name"&gt;&amp;lt;int (*)(int, int), int, int&amp;gt;&lt;/span&gt;
{
    &lt;span class="org-keyword"&gt;typedef&lt;/span&gt; &lt;span class="org-type"&gt;int&lt;/span&gt; &lt;span class="org-type"&gt;result_type&lt;/span&gt;;
};
&lt;/pre&gt;
&lt;/div&gt;


&lt;div class="notes" id="orgac26af1"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org5b19f13" class="outline-3"&gt;
&lt;h4 id="org5b19f13"&gt;Why Didn't We Get Them?&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-org5b19f13"&gt;
&lt;p&gt; Let's not go there right now. &lt;/p&gt;

&lt;div class="notes" id="orgcd8e7be"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org5455e39" class="outline-2"&gt;
&lt;h3 id="org5455e39"&gt;State of the Art&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org5455e39"&gt;
&lt;/div&gt;
&lt;div id="outline-container-org2126bdf" class="outline-3"&gt;
&lt;h4 id="org2126bdf"&gt;Rust Traits&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-org2126bdf"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-rust" id="nil"&gt;&lt;span class="org-keyword"&gt;trait&lt;/span&gt; &lt;span class="org-type"&gt;PartialEq&lt;/span&gt; {
    &lt;span class="org-keyword"&gt;fn&lt;/span&gt; &lt;span class="org-function-name"&gt;eq&lt;/span&gt;(&lt;span class="org-rust-ampersand"&gt;&amp;amp;&lt;/span&gt;&lt;span class="org-keyword"&gt;self&lt;/span&gt;, &lt;span class="org-variable-name"&gt;rhs&lt;/span&gt;: &lt;span class="org-rust-ampersand"&gt;&amp;amp;&lt;/span&gt;&lt;span class="org-type"&gt;Self&lt;/span&gt;) -&amp;gt; &lt;span class="org-type"&gt;bool&lt;/span&gt;;

    &lt;span class="org-keyword"&gt;fn&lt;/span&gt; &lt;span class="org-function-name"&gt;ne&lt;/span&gt;(&lt;span class="org-rust-ampersand"&gt;&amp;amp;&lt;/span&gt;&lt;span class="org-keyword"&gt;self&lt;/span&gt;, &lt;span class="org-variable-name"&gt;rhs&lt;/span&gt;: &lt;span class="org-rust-ampersand"&gt;&amp;amp;&lt;/span&gt;&lt;span class="org-type"&gt;Self&lt;/span&gt;) -&amp;gt; &lt;span class="org-type"&gt;bool&lt;/span&gt; {
        !&lt;span class="org-keyword"&gt;self&lt;/span&gt;.eq(rhs)
    }
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;div class="notes" id="org84edbf7"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org0372946" class="outline-3"&gt;
&lt;h4 id="org0372946"&gt;C++ CPOs&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-org0372946"&gt;
&lt;/div&gt;
&lt;div id="outline-container-org38d8aac" class="outline-4"&gt;
&lt;h5 id="org38d8aac"&gt;Some Concepts and Types&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-org38d8aac"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-C++" id="nil"&gt;&lt;span class="org-keyword"&gt;namespace&lt;/span&gt; &lt;span class="org-constant"&gt;N&lt;/span&gt;::&lt;span class="org-constant"&gt;hidden&lt;/span&gt; {
&lt;span class="org-keyword"&gt;template&lt;/span&gt; &amp;lt;&lt;span class="org-keyword"&gt;typename&lt;/span&gt; &lt;span class="org-type"&gt;T&lt;/span&gt;&amp;gt;
&lt;span class="org-keyword"&gt;concept&lt;/span&gt; &lt;span class="org-type"&gt;has_eq&lt;/span&gt; = &lt;span class="org-keyword"&gt;requires&lt;/span&gt;(&lt;span class="org-type"&gt;T&lt;/span&gt; &lt;span class="org-keyword"&gt;const&lt;/span&gt;&amp;amp; &lt;span class="org-variable-name"&gt;v&lt;/span&gt;) {
  { eq(v, v) } -&amp;gt; &lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-type"&gt;same_as&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;bool&lt;/span&gt;&amp;gt;;
};

&lt;span class="org-keyword"&gt;struct&lt;/span&gt; &lt;span class="org-type"&gt;eq_fn&lt;/span&gt; {
  &lt;span class="org-keyword"&gt;template&lt;/span&gt; &amp;lt;&lt;span class="org-type"&gt;has_eq&lt;/span&gt; &lt;span class="org-type"&gt;T&lt;/span&gt;&amp;gt;
  &lt;span class="org-keyword"&gt;constexpr&lt;/span&gt; &lt;span class="org-type"&gt;bool&lt;/span&gt; &lt;span class="org-keyword"&gt;operator&lt;/span&gt;&lt;span class="org-function-name"&gt;()&lt;/span&gt;(&lt;span class="org-type"&gt;T&lt;/span&gt; &lt;span class="org-keyword"&gt;const&lt;/span&gt;&amp;amp; &lt;span class="org-variable-name"&gt;x&lt;/span&gt;,
                            &lt;span class="org-type"&gt;T&lt;/span&gt; &lt;span class="org-keyword"&gt;const&lt;/span&gt;&amp;amp; &lt;span class="org-variable-name"&gt;y&lt;/span&gt;) &lt;span class="org-keyword"&gt;const&lt;/span&gt; {
    &lt;span class="org-keyword"&gt;return&lt;/span&gt; eq(x, y);
  }
};

&lt;span class="org-keyword"&gt;template&lt;/span&gt; &amp;lt;&lt;span class="org-type"&gt;has_eq&lt;/span&gt; &lt;span class="org-type"&gt;T&lt;/span&gt;&amp;gt;
&lt;span class="org-keyword"&gt;constexpr&lt;/span&gt; &lt;span class="org-type"&gt;bool&lt;/span&gt; &lt;span class="org-function-name"&gt;ne&lt;/span&gt;(&lt;span class="org-type"&gt;T&lt;/span&gt; &lt;span class="org-keyword"&gt;const&lt;/span&gt;&amp;amp; &lt;span class="org-variable-name"&gt;x&lt;/span&gt;, &lt;span class="org-type"&gt;T&lt;/span&gt; &lt;span class="org-keyword"&gt;const&lt;/span&gt;&amp;amp; &lt;span class="org-variable-name"&gt;y&lt;/span&gt;) {
  &lt;span class="org-keyword"&gt;return&lt;/span&gt; &lt;span class="org-keyword"&gt;not&lt;/span&gt; eq(x, y);
}

&lt;span class="org-keyword"&gt;template&lt;/span&gt; &amp;lt;&lt;span class="org-keyword"&gt;typename&lt;/span&gt; &lt;span class="org-type"&gt;T&lt;/span&gt;&amp;gt;
&lt;span class="org-keyword"&gt;concept&lt;/span&gt; &lt;span class="org-type"&gt;has_ne&lt;/span&gt; = &lt;span class="org-keyword"&gt;requires&lt;/span&gt;(&lt;span class="org-type"&gt;T&lt;/span&gt; &lt;span class="org-keyword"&gt;const&lt;/span&gt;&amp;amp; &lt;span class="org-variable-name"&gt;v&lt;/span&gt;) {
  { ne(v, v) } -&amp;gt; &lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-type"&gt;same_as&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;bool&lt;/span&gt;&amp;gt;;
};

&lt;span class="org-keyword"&gt;struct&lt;/span&gt; &lt;span class="org-type"&gt;ne_fn&lt;/span&gt; {
  &lt;span class="org-keyword"&gt;template&lt;/span&gt; &amp;lt;&lt;span class="org-type"&gt;has_ne&lt;/span&gt; &lt;span class="org-type"&gt;T&lt;/span&gt;&amp;gt;
  &lt;span class="org-keyword"&gt;constexpr&lt;/span&gt; &lt;span class="org-type"&gt;bool&lt;/span&gt; &lt;span class="org-keyword"&gt;operator&lt;/span&gt;&lt;span class="org-function-name"&gt;()&lt;/span&gt;(&lt;span class="org-type"&gt;T&lt;/span&gt; &lt;span class="org-keyword"&gt;const&lt;/span&gt;&amp;amp; &lt;span class="org-variable-name"&gt;x&lt;/span&gt;,
                            &lt;span class="org-type"&gt;T&lt;/span&gt; &lt;span class="org-keyword"&gt;const&lt;/span&gt;&amp;amp; &lt;span class="org-variable-name"&gt;y&lt;/span&gt;) &lt;span class="org-keyword"&gt;const&lt;/span&gt; {
    &lt;span class="org-keyword"&gt;return&lt;/span&gt; ne(x, y);
  }
};
} &lt;span class="org-comment-delimiter"&gt;// &lt;/span&gt;&lt;span class="org-comment"&gt;namespace N::hidden&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt; See &lt;u&gt;Why tag_invoke is not the solution I want&lt;/u&gt; by Barry Revzin &lt;a href="https://brevzin.github.io/c++/2020/12/01/tag-invoke/"&gt;https://brevzin.github.io/c++/2020/12/01/tag-invoke/&lt;/a&gt; &lt;/p&gt;

&lt;div class="notes" id="org4ec3d03"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgd9440f0" class="outline-4"&gt;
&lt;h5 id="orgd9440f0"&gt;C++ partial_equality&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-orgd9440f0"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-C++" id="nil"&gt;&lt;span class="org-keyword"&gt;namespace&lt;/span&gt; &lt;span class="org-constant"&gt;N&lt;/span&gt; {
&lt;span class="org-keyword"&gt;inline&lt;/span&gt; &lt;span class="org-keyword"&gt;namespace&lt;/span&gt; &lt;span class="org-constant"&gt;function_objects&lt;/span&gt; {
&lt;span class="org-keyword"&gt;inline&lt;/span&gt; &lt;span class="org-keyword"&gt;constexpr&lt;/span&gt; &lt;span class="org-constant"&gt;hidden&lt;/span&gt;::&lt;span class="org-type"&gt;eq_fn&lt;/span&gt; &lt;span class="org-variable-name"&gt;eq&lt;/span&gt;{};
&lt;span class="org-keyword"&gt;inline&lt;/span&gt; &lt;span class="org-keyword"&gt;constexpr&lt;/span&gt; &lt;span class="org-constant"&gt;hidden&lt;/span&gt;::&lt;span class="org-type"&gt;ne_fn&lt;/span&gt; &lt;span class="org-variable-name"&gt;ne&lt;/span&gt;{};
} &lt;span class="org-comment-delimiter"&gt;// &lt;/span&gt;&lt;span class="org-comment"&gt;namespace function_objects&lt;/span&gt;

&lt;span class="org-keyword"&gt;template&lt;/span&gt; &amp;lt;&lt;span class="org-keyword"&gt;typename&lt;/span&gt; &lt;span class="org-type"&gt;T&lt;/span&gt;&amp;gt;
&lt;span class="org-keyword"&gt;concept&lt;/span&gt; partial_equality
  &lt;span class="org-keyword"&gt;requires&lt;/span&gt;(&lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-type"&gt;remove_reference_t&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;T&lt;/span&gt;&amp;gt; &lt;span class="org-keyword"&gt;const&lt;/span&gt;&amp;amp; &lt;span class="org-variable-name"&gt;t&lt;/span&gt;)
{
  eq(t, t);
  ne(t, t);
};
} &lt;span class="org-comment-delimiter"&gt;// &lt;/span&gt;&lt;span class="org-comment"&gt;namespace N&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt; See &lt;u&gt;Why tag_invoke is not the solution I want&lt;/u&gt; by Barry Revzin &lt;a href="https://brevzin.github.io/c++/2020/12/01/tag-invoke/"&gt;https://brevzin.github.io/c++/2020/12/01/tag-invoke/&lt;/a&gt; &lt;/p&gt;

&lt;div class="notes" id="orgdecd5c0"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org5396b8f" class="outline-2"&gt;
&lt;h3 id="org5396b8f"&gt;Requirements for Solution&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org5396b8f"&gt;
&lt;ul class="org-ul"&gt;
&lt;li&gt;&lt;p&gt; Tied to the type system &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt; Automatable &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;"zero" overhead

&lt;ul class="org-ul"&gt;
&lt;li&gt;&lt;p&gt; no virtual calls &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;no type erasure&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="notes" id="orgc4034ba"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgad4da33" class="outline-2"&gt;
&lt;h3 id="orgad4da33"&gt;What does typeclass do?&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-orgad4da33"&gt;
&lt;p&gt; Adds a record to the function that defines the operations for the type. &lt;/p&gt;

&lt;p&gt; Can we do that? &lt;/p&gt;

&lt;div class="notes" id="org585f6ee"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org3f6e803" class="outline-2"&gt;
&lt;h3 id="org3f6e803"&gt;Type-based lookup&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org3f6e803"&gt;
&lt;p&gt; Templates! &lt;/p&gt;

&lt;div class="notes" id="org887d83a"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgcf837b9" class="outline-2"&gt;
&lt;h3 id="orgcf837b9"&gt;Additional Requirements&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-orgcf837b9"&gt;
&lt;p&gt; Avoid ADL &lt;/p&gt;

&lt;p&gt; Object Lookup rather than Overload Lookup &lt;/p&gt;

&lt;div class="notes" id="orgc8f05ae"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org43e91b6" class="outline-2"&gt;
&lt;h3 id="org43e91b6"&gt;Variable templates&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org43e91b6"&gt;
&lt;p&gt; Variable templates have become more powerful &lt;/p&gt;

&lt;p&gt; We can have entirely distinct specializations &lt;/p&gt;

&lt;div class="notes" id="org9184e90"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org9b64424" class="outline-3"&gt;
&lt;h4 id="org9b64424"&gt;A Step Towards Implementation&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-org9b64424"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-C++" id="nil"&gt;&lt;span class="org-keyword"&gt;template&lt;/span&gt; &amp;lt;&lt;span class="org-keyword"&gt;class&lt;/span&gt; &lt;span class="org-type"&gt;T&lt;/span&gt;&amp;gt;
&lt;span class="org-keyword"&gt;concept&lt;/span&gt; &lt;span class="org-type"&gt;partial_equality&lt;/span&gt; = &lt;span class="org-keyword"&gt;requires&lt;/span&gt;(
    &lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-type"&gt;remove_reference_t&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;T&lt;/span&gt;&amp;gt; &lt;span class="org-keyword"&gt;const&lt;/span&gt;&amp;amp; &lt;span class="org-variable-name"&gt;t&lt;/span&gt;) {
  {
    &lt;span class="org-type"&gt;partial_eq&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;T&lt;/span&gt;&amp;gt;.eq(t, t)
  } -&amp;gt; &lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-type"&gt;same_as&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;bool&lt;/span&gt;&amp;gt;;
  {
    &lt;span class="org-type"&gt;partial_eq&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;T&lt;/span&gt;&amp;gt;.ne(t, t)
  } -&amp;gt; &lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-type"&gt;same_as&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;bool&lt;/span&gt;&amp;gt;;
};
&lt;/pre&gt;
&lt;/div&gt;

&lt;div class="notes" id="org679feb5"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgf24cbc4" class="outline-3"&gt;
&lt;h4 id="orgf24cbc4"&gt;&lt;code&gt;partial_eq&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-orgf24cbc4"&gt;
&lt;/div&gt;
&lt;div id="outline-container-orga7f035c" class="outline-4"&gt;
&lt;h5 id="orga7f035c"&gt;An inline variable object&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-orga7f035c"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;&lt;span class="org-keyword"&gt;template&lt;/span&gt;&amp;lt;&lt;span class="org-keyword"&gt;class&lt;/span&gt; &lt;span class="org-type"&gt;T&lt;/span&gt;&amp;gt;
&lt;span class="org-keyword"&gt;constexpr&lt;/span&gt; &lt;span class="org-keyword"&gt;inline&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;partial_eq&lt;/span&gt; = &lt;span class="org-constant"&gt;hidden&lt;/span&gt;::partial_eq_default;
&lt;/pre&gt;
&lt;/div&gt;

&lt;div class="notes" id="org7617290"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgd69f366" class="outline-4"&gt;
&lt;h5 id="orgd69f366"&gt;A default implementation&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-orgd69f366"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-C++" id="nil"&gt;&lt;span class="org-keyword"&gt;constexpr&lt;/span&gt; &lt;span class="org-keyword"&gt;inline&lt;/span&gt; &lt;span class="org-keyword"&gt;struct&lt;/span&gt; &lt;span class="org-type"&gt;partial_eq_default_t&lt;/span&gt; {
  &lt;span class="org-keyword"&gt;constexpr&lt;/span&gt; &lt;span class="org-type"&gt;bool&lt;/span&gt;
  &lt;span class="org-function-name"&gt;eq&lt;/span&gt;(&lt;span class="org-type"&gt;has_eq&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-keyword"&gt;const&lt;/span&gt;&amp;amp; &lt;span class="org-variable-name"&gt;rhs&lt;/span&gt;,
     &lt;span class="org-type"&gt;has_eq&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-keyword"&gt;const&lt;/span&gt;&amp;amp; &lt;span class="org-variable-name"&gt;lhs&lt;/span&gt;) &lt;span class="org-keyword"&gt;const&lt;/span&gt; {
    &lt;span class="org-keyword"&gt;return&lt;/span&gt; (rhs == lhs);
  }
  &lt;span class="org-keyword"&gt;constexpr&lt;/span&gt; &lt;span class="org-type"&gt;bool&lt;/span&gt;
  &lt;span class="org-function-name"&gt;ne&lt;/span&gt;(&lt;span class="org-type"&gt;has_eq&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-keyword"&gt;const&lt;/span&gt;&amp;amp; &lt;span class="org-variable-name"&gt;rhs&lt;/span&gt;,
     &lt;span class="org-type"&gt;has_eq&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-keyword"&gt;const&lt;/span&gt;&amp;amp; &lt;span class="org-variable-name"&gt;lhs&lt;/span&gt;) &lt;span class="org-keyword"&gt;const&lt;/span&gt; {
    &lt;span class="org-keyword"&gt;return&lt;/span&gt; (lhs != rhs);
  }
} &lt;span class="org-variable-name"&gt;partial_eq_default&lt;/span&gt;;
&lt;/pre&gt;
&lt;/div&gt;

&lt;div class="notes" id="org73e4b81"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org07152f2" class="outline-4"&gt;
&lt;h5 id="org07152f2"&gt;New &lt;code&gt;has_eq&lt;/code&gt;&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-org07152f2"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;&lt;span class="org-keyword"&gt;template&lt;/span&gt; &amp;lt;&lt;span class="org-keyword"&gt;typename&lt;/span&gt; &lt;span class="org-type"&gt;T&lt;/span&gt;&amp;gt;
&lt;span class="org-keyword"&gt;concept&lt;/span&gt; &lt;span class="org-type"&gt;has_eq&lt;/span&gt; = &lt;span class="org-keyword"&gt;requires&lt;/span&gt;(&lt;span class="org-type"&gt;T&lt;/span&gt; &lt;span class="org-keyword"&gt;const&lt;/span&gt;&amp;amp; &lt;span class="org-variable-name"&gt;v&lt;/span&gt;) {
  { &lt;span class="org-keyword"&gt;operator&lt;/span&gt;==(v, v) } -&amp;gt; &lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-type"&gt;same_as&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;bool&lt;/span&gt;&amp;gt;;
};
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="notes" id="org40519d3"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org33fa324" class="outline-3"&gt;
&lt;h4 id="org33fa324"&gt;Will do better&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-org33fa324"&gt;
&lt;p&gt; In a bit &lt;/p&gt;

&lt;div class="notes" id="orgd6431cd"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org8851fb9" class="outline-2"&gt;
&lt;h3 id="org8851fb9"&gt;Monoid&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org8851fb9"&gt;
&lt;p&gt; A little more than you think. &lt;/p&gt;

&lt;ul class="org-ul"&gt;
&lt;li&gt;A type&lt;/li&gt;
&lt;li&gt;With an associative binary operation&lt;/li&gt;
&lt;li&gt;Which is closed&lt;/li&gt;
&lt;li&gt;And has an identity element&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgb51a0c4" class="outline-3"&gt;
&lt;h4 id="orgb51a0c4"&gt;Maybe not a lot more&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-orgb51a0c4"&gt;
&lt;div class="notes" id="org0c44627"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org38e75f7" class="outline-3"&gt;
&lt;h4 id="org38e75f7"&gt;Math&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-org38e75f7"&gt;
&lt;ul class="org-ul"&gt;
&lt;li&gt;\(\oplus: M \times M \rightarrow M\)&lt;/li&gt;
&lt;li&gt;\(x \oplus (y \oplus z) = (x \oplus y) \oplus z\)&lt;/li&gt;
&lt;li&gt;\(1_M \in M\) such that \(\forall m \in M : (1_M \oplus m) = m = (m \oplus 1_M)\)&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="notes" id="org17705e7"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org38a2fc2" class="outline-3"&gt;
&lt;h4 id="org38a2fc2"&gt;Function form&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-org38a2fc2"&gt;
&lt;ul class="org-ul"&gt;
&lt;li&gt;\(f : M \times M \rightarrow M\)&lt;/li&gt;
&lt;li&gt;\(f(x, f(y, z)) = f(f(x, y), z)\)&lt;/li&gt;
&lt;li&gt;\(1_M \in M\) such that \(\forall m \in M : f(1_M, m) = m = f(m, 1_M)\)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; The similarity to left and right fold is &lt;b&gt;NOT&lt;/b&gt; an accident &lt;/p&gt;

&lt;div class="notes" id="org87b2c28"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orge87a585" class="outline-3"&gt;
&lt;h4 id="orge87a585"&gt;Core Functions&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-orge87a585"&gt;
&lt;dl class="org-dl"&gt;
&lt;dt&gt;\(empty : m\)&lt;/dt&gt;&lt;dd&gt;\(empty = concat \, []\)&lt;/dd&gt;
&lt;dt&gt;\(concat : [m] \rightarrow m\)&lt;/dt&gt;&lt;dd&gt;\(fold \, append \, empty\)&lt;/dd&gt;
&lt;dt&gt;\(append : m \rightarrow m \rightarrow m\)&lt;/dt&gt;&lt;dd&gt;\(op\)&lt;/dd&gt;
&lt;/dl&gt;


&lt;p&gt; Note that it's self-referential &lt;/p&gt;

&lt;p&gt; This is common &lt;/p&gt;

&lt;div class="notes" id="orgbae6f76"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org8204644" class="outline-4"&gt;
&lt;h5 id="org8204644"&gt;From Haskell Prelude&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-org8204644"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-haskell" id="nil"&gt;&lt;span class="org-haskell-keyword"&gt;class&lt;/span&gt; &lt;span class="org-haskell-type"&gt;Semigroup&lt;/span&gt; a &lt;span class="org-haskell-operator"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="org-haskell-type"&gt;Monoid&lt;/span&gt; a &lt;span class="org-haskell-keyword"&gt;where&lt;/span&gt;
  mempty &lt;span class="org-haskell-operator"&gt;::&lt;/span&gt; a
  mempty &lt;span class="org-haskell-operator"&gt;=&lt;/span&gt; mconcat &lt;span class="org-haskell-constructor"&gt;[]&lt;/span&gt;

  mappend &lt;span class="org-haskell-operator"&gt;::&lt;/span&gt; a &lt;span class="org-haskell-operator"&gt;-&amp;gt;&lt;/span&gt; a &lt;span class="org-haskell-operator"&gt;-&amp;gt;&lt;/span&gt; a
  mappend &lt;span class="org-haskell-operator"&gt;=&lt;/span&gt; (&lt;span class="org-haskell-operator"&gt;&amp;lt;&amp;gt;&lt;/span&gt;)

  mconcat &lt;span class="org-haskell-operator"&gt;::&lt;/span&gt; [a] &lt;span class="org-haskell-operator"&gt;-&amp;gt;&lt;/span&gt; a
  mconcat &lt;span class="org-haskell-operator"&gt;=&lt;/span&gt; foldr mappend mempty
&lt;/pre&gt;
&lt;/div&gt;

&lt;div class="notes" id="org27faaae"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org58ba1f2" class="outline-3"&gt;
&lt;h4 id="org58ba1f2"&gt;Minimum Set&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-org58ba1f2"&gt;
&lt;p&gt; \(empty \, | \, concat\) &lt;/p&gt;

&lt;div class="notes" id="orgc143f8b"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org7fab3d4" class="outline-3"&gt;
&lt;h4 id="org7fab3d4"&gt;In C++&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-org7fab3d4"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-C++" id="nil"&gt;&lt;span class="org-keyword"&gt;template&lt;/span&gt; &amp;lt;&lt;span class="org-keyword"&gt;typename&lt;/span&gt; &lt;span class="org-type"&gt;T&lt;/span&gt;, &lt;span class="org-keyword"&gt;typename&lt;/span&gt; &lt;span class="org-type"&gt;M&lt;/span&gt;&amp;gt;
&lt;span class="org-keyword"&gt;concept&lt;/span&gt; &lt;span class="org-type"&gt;MonoidRequirements&lt;/span&gt; =
    &lt;span class="org-keyword"&gt;requires&lt;/span&gt;(&lt;span class="org-type"&gt;T&lt;/span&gt; &lt;span class="org-variable-name"&gt;i&lt;/span&gt;) {
      { i.identity() } -&amp;gt; &lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-type"&gt;same_as&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;M&lt;/span&gt;&amp;gt;;
    }
    ||
    &lt;span class="org-keyword"&gt;requires&lt;/span&gt;(&lt;span class="org-type"&gt;T&lt;/span&gt; &lt;span class="org-variable-name"&gt;i&lt;/span&gt;, &lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-constant"&gt;ranges&lt;/span&gt;::&lt;span class="org-type"&gt;empty_view&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;M&lt;/span&gt;&amp;gt; &lt;span class="org-variable-name"&gt;r1&lt;/span&gt;) {
      { i.concat(r1) } -&amp;gt; &lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-type"&gt;same_as&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;M&lt;/span&gt;&amp;gt;;
    };
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="notes" id="org2c61343"&gt;
&lt;p&gt; I am ignoring all sorts of const volatile reference issues here. &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org55db03e" class="outline-2"&gt;
&lt;h3 id="org55db03e"&gt;Implementing the other side&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org55db03e"&gt;
&lt;/div&gt;
&lt;div id="outline-container-org94ca958" class="outline-3"&gt;
&lt;h4 id="org94ca958"&gt;The Map for a Monoid&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-org94ca958"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;&lt;span class="org-keyword"&gt;template&lt;/span&gt; &amp;lt;&lt;span class="org-keyword"&gt;class&lt;/span&gt; &lt;span class="org-type"&gt;Impl&lt;/span&gt;&amp;gt;
  &lt;span class="org-keyword"&gt;requires&lt;/span&gt; &lt;span class="org-type"&gt;MonoidRequirements&lt;/span&gt;&amp;lt;
      &lt;span class="org-type"&gt;Impl&lt;/span&gt;,
      &lt;span class="org-keyword"&gt;typename&lt;/span&gt; &lt;span class="org-constant"&gt;Impl&lt;/span&gt;::&lt;span class="org-type"&gt;value_type&lt;/span&gt;&amp;gt;
&lt;span class="org-keyword"&gt;struct&lt;/span&gt; &lt;span class="org-type"&gt;Monoid&lt;/span&gt; : &lt;span class="org-keyword"&gt;protected&lt;/span&gt; &lt;span class="org-type"&gt;Impl&lt;/span&gt; {
  &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;identity&lt;/span&gt;(&lt;span class="org-keyword"&gt;this&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; self);

  &lt;span class="org-keyword"&gt;template&lt;/span&gt; &amp;lt;&lt;span class="org-keyword"&gt;typename&lt;/span&gt; &lt;span class="org-type"&gt;Range&lt;/span&gt;&amp;gt;
  &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;concat&lt;/span&gt;(&lt;span class="org-keyword"&gt;this&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; self, &lt;span class="org-type"&gt;Range&lt;/span&gt; &lt;span class="org-variable-name"&gt;r&lt;/span&gt;);

  &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;op&lt;/span&gt;(&lt;span class="org-keyword"&gt;this&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; self, &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;a1&lt;/span&gt;, &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;a2&lt;/span&gt;);
};
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="notes" id="org2cb36b8"&gt;
&lt;p&gt; empty is a terrible name, concat only a little better. empty becomes identity &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgf2e4e66" class="outline-4"&gt;
&lt;h5 id="orgf2e4e66"&gt;&lt;code&gt;identity&lt;/code&gt;&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-orgf2e4e66"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;    &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;identity&lt;/span&gt;(&lt;span class="org-keyword"&gt;this&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &amp;amp;&amp;amp; self) {
        &lt;span class="org-constant"&gt;std&lt;/span&gt;::puts(&lt;span class="org-string"&gt;"Monoid::identity()"&lt;/span&gt;);
        &lt;span class="org-keyword"&gt;return&lt;/span&gt; self.concat(&lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-constant"&gt;ranges&lt;/span&gt;::&lt;span class="org-type"&gt;empty_view&lt;/span&gt;&amp;lt;&lt;span class="org-keyword"&gt;typename&lt;/span&gt; &lt;span class="org-constant"&gt;Impl&lt;/span&gt;::&lt;span class="org-type"&gt;value_type&lt;/span&gt;&amp;gt;{});
    }

&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org4544cc8" class="outline-4"&gt;
&lt;h5 id="org4544cc8"&gt;&lt;code&gt;concat&lt;/code&gt;&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-org4544cc8"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;   &lt;span class="org-keyword"&gt;template&lt;/span&gt;&amp;lt;&lt;span class="org-keyword"&gt;typename&lt;/span&gt; &lt;span class="org-type"&gt;Range&lt;/span&gt;&amp;gt;
   &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;concat&lt;/span&gt;(&lt;span class="org-keyword"&gt;this&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; self, &lt;span class="org-type"&gt;Range&lt;/span&gt; &lt;span class="org-variable-name"&gt;r&lt;/span&gt;) {
        &lt;span class="org-constant"&gt;std&lt;/span&gt;::puts(&lt;span class="org-string"&gt;"Monoid::concat()"&lt;/span&gt;);
        &lt;span class="org-keyword"&gt;return&lt;/span&gt; &lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-constant"&gt;ranges&lt;/span&gt;::fold_right(r,
                    self.identity(),
                    [&amp;amp;](&lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;m1&lt;/span&gt;, &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;m2&lt;/span&gt;){&lt;span class="org-keyword"&gt;return&lt;/span&gt; self.op(m1, m2);});
    }

&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org7fb7987" class="outline-4"&gt;
&lt;h5 id="org7fb7987"&gt;&lt;code&gt;op&lt;/code&gt;&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-org7fb7987"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;   &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;op&lt;/span&gt;(&lt;span class="org-keyword"&gt;this&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; self, &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;a1&lt;/span&gt;, &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;a2&lt;/span&gt;) {
        &lt;span class="org-constant"&gt;std&lt;/span&gt;::puts(&lt;span class="org-string"&gt;"Monoid::op"&lt;/span&gt;);
        &lt;span class="org-keyword"&gt;return&lt;/span&gt; self.op(a1, a2);
    }
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org433bfeb" class="outline-3"&gt;
&lt;h4 id="org433bfeb"&gt;Deducing &lt;code&gt;this&lt;/code&gt; &lt;b&gt;and&lt;/b&gt; CRTP&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-org433bfeb"&gt;
&lt;p&gt; We'll see in a moment, but it's because we want to constraint the required implementation. &lt;/p&gt;

&lt;p&gt; We want to use the derived version which has all of the operations. &lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgd365e33" class="outline-3"&gt;
&lt;h4 id="orgd365e33"&gt;&lt;code&gt;Plus&lt;/code&gt;&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-orgd365e33"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-C++" id="nil"&gt;&lt;span class="org-keyword"&gt;template&lt;/span&gt; &amp;lt;&lt;span class="org-keyword"&gt;typename&lt;/span&gt; &lt;span class="org-type"&gt;M&lt;/span&gt;&amp;gt;
&lt;span class="org-keyword"&gt;class&lt;/span&gt; &lt;span class="org-type"&gt;Plus&lt;/span&gt; {
&lt;span class="org-keyword"&gt;public&lt;/span&gt;:
  &lt;span class="org-keyword"&gt;using&lt;/span&gt; &lt;span class="org-type"&gt;value_type&lt;/span&gt; = M;
  &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;identity&lt;/span&gt;(&lt;span class="org-keyword"&gt;this&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; self) -&amp;gt; &lt;span class="org-type"&gt;M&lt;/span&gt; {
    &lt;span class="org-constant"&gt;std&lt;/span&gt;::puts(&lt;span class="org-string"&gt;"Plus::identity()"&lt;/span&gt;);
    &lt;span class="org-keyword"&gt;return&lt;/span&gt; M{0};
  }

  &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;op&lt;/span&gt;(&lt;span class="org-keyword"&gt;this&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; self, &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;s1&lt;/span&gt;, &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;s2&lt;/span&gt;) -&amp;gt; &lt;span class="org-type"&gt;M&lt;/span&gt; {
    &lt;span class="org-constant"&gt;std&lt;/span&gt;::puts(&lt;span class="org-string"&gt;"Plus::op()"&lt;/span&gt;);
    &lt;span class="org-keyword"&gt;return&lt;/span&gt; s1 + s2;
  }
};
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org0a4f2c7" class="outline-3"&gt;
&lt;h4 id="org0a4f2c7"&gt;&lt;code&gt;PlusMonoidMap&lt;/code&gt;&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-org0a4f2c7"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;&lt;span class="org-keyword"&gt;template&lt;/span&gt;&amp;lt;&lt;span class="org-keyword"&gt;typename&lt;/span&gt; &lt;span class="org-type"&gt;M&lt;/span&gt;&amp;gt;
&lt;span class="org-keyword"&gt;struct&lt;/span&gt; &lt;span class="org-type"&gt;PlusMonoidMap&lt;/span&gt; : &lt;span class="org-keyword"&gt;public&lt;/span&gt; &lt;span class="org-type"&gt;Monoid&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;Plus&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;M&lt;/span&gt;&amp;gt;&amp;gt; {
    &lt;span class="org-keyword"&gt;using&lt;/span&gt; &lt;span class="org-constant"&gt;Plus&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;M&lt;/span&gt;&amp;gt;::identity;
    &lt;span class="org-keyword"&gt;using&lt;/span&gt; &lt;span class="org-constant"&gt;Plus&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;M&lt;/span&gt;&amp;gt;::op;
};
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="notes" id="orga6a3f61"&gt;
&lt;p&gt; Need to pull the operations from the Monoid instance into the Map, so we get the right ones being used by concat. &lt;/p&gt;

&lt;p&gt; This might be simpler if we didn't allow choice of the basis operations, but that's also overly restrictive. &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgc757316" class="outline-3"&gt;
&lt;h4 id="orgc757316"&gt;The map instances&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-orgc757316"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;&lt;span class="org-keyword"&gt;template&lt;/span&gt;&amp;lt;&lt;span class="org-keyword"&gt;class&lt;/span&gt; &lt;span class="org-type"&gt;T&lt;/span&gt;&amp;gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;monoid_concept_map&lt;/span&gt; = &lt;span class="org-constant"&gt;std&lt;/span&gt;::false_type{};

&lt;span class="org-keyword"&gt;template&lt;/span&gt;&amp;lt;&amp;gt;
&lt;span class="org-keyword"&gt;constexpr&lt;/span&gt; &lt;span class="org-keyword"&gt;inline&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-type"&gt;monoid_concept_map&lt;/span&gt;&lt;span class="org-variable-name"&gt;&amp;lt;int&amp;gt;&lt;/span&gt; = &lt;span class="org-type"&gt;PlusMonoidMap&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;int&lt;/span&gt;&amp;gt;{};

&lt;span class="org-keyword"&gt;template&lt;/span&gt;&amp;lt;&amp;gt;
&lt;span class="org-keyword"&gt;constexpr&lt;/span&gt; &lt;span class="org-keyword"&gt;inline&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-type"&gt;monoid_concept_map&lt;/span&gt;&lt;span class="org-variable-name"&gt;&amp;lt;long&amp;gt;&lt;/span&gt; = &lt;span class="org-type"&gt;PlusMonoidMap&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;long&lt;/span&gt;&amp;gt;{};

&lt;span class="org-keyword"&gt;template&lt;/span&gt;&amp;lt;&amp;gt;
&lt;span class="org-keyword"&gt;constexpr&lt;/span&gt; &lt;span class="org-keyword"&gt;inline&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-type"&gt;monoid_concept_map&lt;/span&gt;&lt;span class="org-variable-name"&gt;&amp;lt;char&amp;gt;&lt;/span&gt; = &lt;span class="org-type"&gt;PlusMonoidMap&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;char&lt;/span&gt;&amp;gt;{};
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org4a87cf1" class="outline-3"&gt;
&lt;h4 id="org4a87cf1"&gt;Can we &lt;code&gt;concat&lt;/code&gt; instead?&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-org4a87cf1"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;&lt;span class="org-keyword"&gt;class&lt;/span&gt; &lt;span class="org-type"&gt;StringMonoid&lt;/span&gt; {
&lt;span class="org-keyword"&gt;public&lt;/span&gt;:
  &lt;span class="org-keyword"&gt;using&lt;/span&gt; &lt;span class="org-type"&gt;value_type&lt;/span&gt; = &lt;span class="org-constant"&gt;std&lt;/span&gt;::string;

  &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;op&lt;/span&gt;(&lt;span class="org-keyword"&gt;this&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt;&amp;amp;&amp;amp;, &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;s1&lt;/span&gt;, &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;s2&lt;/span&gt;) {
    &lt;span class="org-constant"&gt;std&lt;/span&gt;::puts(&lt;span class="org-string"&gt;"StringMonoid::op()"&lt;/span&gt;);
    &lt;span class="org-keyword"&gt;return&lt;/span&gt; s1 + s2;
  }

  &lt;span class="org-keyword"&gt;template&lt;/span&gt; &amp;lt;&lt;span class="org-keyword"&gt;typename&lt;/span&gt; &lt;span class="org-type"&gt;Range&lt;/span&gt;&amp;gt;
  &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;concat&lt;/span&gt;(&lt;span class="org-keyword"&gt;this&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; self, &lt;span class="org-type"&gt;Range&lt;/span&gt; &lt;span class="org-variable-name"&gt;r&lt;/span&gt;) {
    &lt;span class="org-constant"&gt;std&lt;/span&gt;::puts(&lt;span class="org-string"&gt;"StringMonoid::concat()"&lt;/span&gt;);
    &lt;span class="org-keyword"&gt;return&lt;/span&gt; &lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-constant"&gt;ranges&lt;/span&gt;::fold_right(
        r, &lt;span class="org-constant"&gt;std&lt;/span&gt;::string{}, [&amp;amp;](&lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;m1&lt;/span&gt;, &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;m2&lt;/span&gt;) {
          &lt;span class="org-keyword"&gt;return&lt;/span&gt; self.op(m1, m2);
        });
  }
};
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="notes" id="org1421b14"&gt;
&lt;p&gt; No, I'm not properly constraining Range here. No, I'm not actually recommending this as an implementation. &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org3c488f3" class="outline-3"&gt;
&lt;h4 id="org3c488f3"&gt;The Map and instance&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-org3c488f3"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;&lt;span class="org-keyword"&gt;struct&lt;/span&gt; &lt;span class="org-type"&gt;StringMonoidMap&lt;/span&gt; : &lt;span class="org-keyword"&gt;public&lt;/span&gt; &lt;span class="org-type"&gt;Monoid&lt;/span&gt;&amp;lt;StringMonoid&amp;gt; {
    &lt;span class="org-keyword"&gt;using&lt;/span&gt; &lt;span class="org-constant"&gt;StringMonoid&lt;/span&gt;::op;
    &lt;span class="org-keyword"&gt;using&lt;/span&gt; &lt;span class="org-constant"&gt;StringMonoid&lt;/span&gt;::concat;
};

&lt;span class="org-keyword"&gt;template&lt;/span&gt;&amp;lt;&amp;gt;
&lt;span class="org-keyword"&gt;constexpr&lt;/span&gt; &lt;span class="org-keyword"&gt;inline&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-type"&gt;monoid_concept_map&lt;/span&gt;&amp;lt;&lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-variable-name"&gt;string&amp;gt;&lt;/span&gt; = StringMonoidMap{};

&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org3a12eef" class="outline-2"&gt;
&lt;h3 id="org3a12eef"&gt;Some simple use&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org3a12eef"&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgd1b5091" class="outline-3"&gt;
&lt;h4 id="orgd1b5091"&gt;Exercise the functions&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-orgd1b5091"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-C++" id="nil"&gt;&lt;span class="org-keyword"&gt;template&lt;/span&gt;&amp;lt;&lt;span class="org-keyword"&gt;typename&lt;/span&gt; &lt;span class="org-type"&gt;P&lt;/span&gt;&amp;gt;
&lt;span class="org-type"&gt;void&lt;/span&gt; &lt;span class="org-function-name"&gt;testP&lt;/span&gt;()
{
    &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;d1&lt;/span&gt; = &lt;span class="org-type"&gt;monoid_concept_map&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;P&lt;/span&gt;&amp;gt;;

    &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;x&lt;/span&gt; = d1.identity();
    assert(P{} == x);

    &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;sum&lt;/span&gt; = d1.op(x, P{1});
    assert(P{1} == sum);

    &lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-type"&gt;vector&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;P&lt;/span&gt;&amp;gt; &lt;span class="org-variable-name"&gt;v&lt;/span&gt; = {1,2,3,4};
    &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;k&lt;/span&gt; = d1.concat(v);
    assert(k == 10);
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgd13d04e" class="outline-3"&gt;
&lt;h4 id="orgd13d04e"&gt;Some simple cases&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-orgd13d04e"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;    &lt;span class="org-constant"&gt;std&lt;/span&gt;::cout &amp;lt;&amp;lt; &lt;span class="org-string"&gt;"\ntest int\n"&lt;/span&gt;;
    testP&amp;lt;&lt;span class="org-type"&gt;int&lt;/span&gt;&amp;gt;();

    &lt;span class="org-constant"&gt;std&lt;/span&gt;::cout &amp;lt;&amp;lt; &lt;span class="org-string"&gt;"\ntest long\n"&lt;/span&gt;;
    testP&amp;lt;&lt;span class="org-type"&gt;long&lt;/span&gt;&amp;gt;();

   &lt;span class="org-constant"&gt;std&lt;/span&gt;::cout &amp;lt;&amp;lt; &lt;span class="org-string"&gt;"\ntest char\n"&lt;/span&gt;;
    testP&amp;lt;&lt;span class="org-type"&gt;char&lt;/span&gt;&amp;gt;();

&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orga5b5669" class="outline-3"&gt;
&lt;h4 id="orga5b5669"&gt;On &lt;code&gt;std::string&lt;/code&gt;&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-orga5b5669"&gt;
&lt;p&gt; This will use the StringMonoid we defined a few moments ago. &lt;/p&gt;

&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-C++" id="nil"&gt;    &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;d2&lt;/span&gt; = &lt;span class="org-type"&gt;monoid_concept_map&lt;/span&gt;&amp;lt;&lt;span class="org-constant"&gt;std&lt;/span&gt;::string&amp;gt;;

    &lt;span class="org-constant"&gt;std&lt;/span&gt;::cout &amp;lt;&amp;lt; &lt;span class="org-string"&gt;"\ntest string\n"&lt;/span&gt;;
    &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;x2&lt;/span&gt; = d2.identity();
    assert(&lt;span class="org-constant"&gt;std&lt;/span&gt;::string{} == x2);

    &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;sum2&lt;/span&gt; = d2.op(x2, &lt;span class="org-string"&gt;"1"&lt;/span&gt;);
    assert(&lt;span class="org-constant"&gt;std&lt;/span&gt;::string{&lt;span class="org-string"&gt;"1"&lt;/span&gt;} == sum2);

    &lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-type"&gt;vector&lt;/span&gt;&amp;lt;&lt;span class="org-constant"&gt;std&lt;/span&gt;::string&amp;gt; &lt;span class="org-variable-name"&gt;vs&lt;/span&gt; = {&lt;span class="org-string"&gt;"1"&lt;/span&gt;,&lt;span class="org-string"&gt;"2"&lt;/span&gt;,&lt;span class="org-string"&gt;"3"&lt;/span&gt;,&lt;span class="org-string"&gt;"4"&lt;/span&gt;};
    &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;k2&lt;/span&gt; = d2.concat(vs);
    assert(k2 == &lt;span class="org-constant"&gt;std&lt;/span&gt;::string{&lt;span class="org-string"&gt;"1234"&lt;/span&gt;});
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt; Note that the map type is mostly invisible. &lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgb719e3f" class="outline-3"&gt;
&lt;h4 id="orgb719e3f"&gt;Results&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-orgb719e3f"&gt;
&lt;/div&gt;
&lt;div id="outline-container-org24e555f" class="outline-4"&gt;
&lt;h5 id="org24e555f"&gt;test int&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-org24e555f"&gt;
&lt;em&gt;&lt;/em&gt;
&lt;pre class="example" id="nil"&gt;
Plus::identity()
Plus::op()
Monoid::concat()
Plus::identity()
Plus::op()
Plus::op()
Plus::op()
Plus::op()
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orge66a8b5" class="outline-4"&gt;
&lt;h5 id="orge66a8b5"&gt;test long&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-orge66a8b5"&gt;
&lt;em&gt;&lt;/em&gt;
&lt;pre class="example" id="nil"&gt;
Plus::identity()
Plus::op()
Monoid::concat()
Plus::identity()
Plus::op()
Plus::op()
Plus::op()
Plus::op()
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgf7ae047" class="outline-4"&gt;
&lt;h5 id="orgf7ae047"&gt;test char&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-orgf7ae047"&gt;
&lt;em&gt;&lt;/em&gt;
&lt;pre class="example" id="nil"&gt;
Plus::identity()
Plus::op()
Monoid::concat()
Plus::identity()
Plus::op()
Plus::op()
Plus::op()
Plus::op()
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org7390f2c" class="outline-4"&gt;
&lt;h5 id="org7390f2c"&gt;test string&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-org7390f2c"&gt;
&lt;em&gt;&lt;/em&gt;
&lt;pre class="example" id="nil"&gt;
Monoid::identity()
StringMonoid::concat()
StringMonoid::op()
StringMonoid::concat()
StringMonoid::op()
StringMonoid::op()
StringMonoid::op()
StringMonoid::op()
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orga5cfe90" class="outline-2"&gt;
&lt;h3 id="orga5cfe90"&gt;Monoid in Trees&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-orga5cfe90"&gt;
&lt;/div&gt;
&lt;div id="outline-container-org8d2fc90" class="outline-3"&gt;
&lt;h4 id="org8d2fc90"&gt;Foldable generalizes&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-org8d2fc90"&gt;
&lt;p&gt; Folding is very much tied to Range like things. &lt;/p&gt;

&lt;p&gt; It can, and has, been generalized to things that can be traversed. &lt;/p&gt;

&lt;p&gt; &lt;code&gt;monoids&lt;/code&gt; are still critical for Traversables. &lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org5737e19" class="outline-3"&gt;
&lt;h4 id="org5737e19"&gt;Summarizing Data in a tree&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-org5737e19"&gt;
&lt;p&gt; If the summary type is monoidal, nodes can hold summaries of all the data below them. &lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org20d51eb" class="outline-3"&gt;
&lt;h4 id="org20d51eb"&gt;&lt;code&gt;fingertrees&lt;/code&gt;&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-org20d51eb"&gt;
&lt;p&gt; Much of the flexibility of &lt;code&gt;fingertrees&lt;/code&gt; comes from the monoidal tags. &lt;/p&gt;

&lt;p&gt; They are also fairly complicated. &lt;/p&gt;

&lt;p&gt; Technique can be applied to other, simpler trees. &lt;/p&gt;

&lt;p&gt; P3200 (eventually) ((C++29)) &lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgeea587e" class="outline-3"&gt;
&lt;h4 id="orgeea587e"&gt;fringe-tree&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-orgeea587e"&gt;
&lt;p&gt; Simplified tree with data at the edges &lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgacbba9a" class="outline-3"&gt;
&lt;h4 id="orgacbba9a"&gt;Code&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-orgacbba9a"&gt;
&lt;p&gt; Show the monoid-map branch of &lt;/p&gt;

&lt;p&gt; &lt;a href="https://github.com/steve-downey/fringetree"&gt;steve-downey/fringetree.git&lt;/a&gt; &lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgab7d8a2" class="outline-2"&gt;
&lt;h3 id="orgab7d8a2"&gt;Summary for Concept Maps&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-orgab7d8a2"&gt;
&lt;p&gt; Tell you what I told you &lt;/p&gt;

&lt;ul class="org-ul"&gt;
&lt;li&gt;Variable templates for map lookup&lt;/li&gt;
&lt;li&gt;Named operations on the map object&lt;/li&gt;
&lt;li&gt;Open for extension&lt;/li&gt;
&lt;li&gt;Concept checkable implementations&lt;/li&gt;
&lt;li&gt;Decoupled map use and implementation&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org8395959" class="outline-2"&gt;
&lt;h3 id="org8395959"&gt;Questions?&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org8395959"&gt;
&lt;p&gt; Or comments &lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org3983c15" class="outline-2"&gt;
&lt;h3 id="org3983c15"&gt;Thank You&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org3983c15"&gt;
&lt;div class="notes" id="org4db291f"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description><guid>https://sdowney.org/posts/index.php/2024/05/19/concept-maps-using-c23-library-tech/</guid><pubDate>Sun, 19 May 2024 15:51:00 GMT</pubDate></item><item><title>Slides from C++Now 2023 Async Control Flow</title><link>https://sdowney.org/posts/index.php/2024/05/18/slides-from-cnow-2023-async-control-flow/</link><dc:creator>Steve Downey</dc:creator><description>&lt;div id="outline-container-org8b3a3c0" class="outline-2"&gt;
&lt;h3 id="org8b3a3c0"&gt;Using Sender/Receiver for Async Control Flow&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org8b3a3c0"&gt;
&lt;p&gt; Steve Downey &lt;/p&gt;

&lt;p&gt; These are the slides, slightly rerendered, from my presentation at C++Now 2023. &lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orga88bc52" class="outline-2"&gt;
&lt;h3 id="orga88bc52"&gt;Abstract&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-orga88bc52"&gt;
&lt;p&gt; How can P2300 Senders be composed using sender adapters and sender factories to provide arbitrary program control flow? &lt;/p&gt;

&lt;ul class="org-ul"&gt;
&lt;li&gt;How do I use these things?&lt;/li&gt;
&lt;/ul&gt;
&lt;ul class="org-ul"&gt;
&lt;li&gt;Where can I steal from?&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- TEASER_END --&gt;

&lt;div class="notes" id="org36cf365"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org236dff5" class="outline-2"&gt;
&lt;h3 id="org236dff5"&gt;&lt;code&gt;std::execution&lt;/code&gt;&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org236dff5"&gt;
&lt;p&gt; &lt;a href="https://wg21.link/P2300"&gt;P2300&lt;/a&gt; &lt;/p&gt;

&lt;p&gt; Recent version at &lt;a href="https://isocpp.org/files/papers/P2300R7.html"&gt;https://isocpp.org/files/papers/P2300R7.html&lt;/a&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt; A self-contained design for a Standard C++ framework for managing asynchronous execution on generic execution resources. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="notes" id="org8339640"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgc5b1e38" class="outline-3"&gt;
&lt;h4 id="orgc5b1e38"&gt;Three Key Abstractions&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-orgc5b1e38"&gt;
&lt;ol class="org-ol"&gt;
&lt;li&gt;&lt;p&gt; Schedulers &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt; Senders &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;Receivers&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div id="outline-container-org6ffab16" class="outline-4"&gt;
&lt;h5 id="org6ffab16"&gt;Schedulers&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-org6ffab16"&gt;
&lt;p&gt; Responsible for scheduling work on execution resources. &lt;/p&gt;

&lt;p&gt; Execution resources are things like threads, GPUs, and so on. &lt;/p&gt;

&lt;p&gt; Sends work to be done in a place. &lt;/p&gt;

&lt;div class="notes" id="orga800408"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgf878c5c" class="outline-4"&gt;
&lt;h5 id="orgf878c5c"&gt;Senders&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-orgf878c5c"&gt;
&lt;p&gt; Senders describe work. &lt;/p&gt;

&lt;div class="notes" id="org3d29294"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgf5c2ed9" class="outline-4"&gt;
&lt;h5 id="orgf5c2ed9"&gt;Receivers&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-orgf5c2ed9"&gt;
&lt;p&gt; Receivers are where work terminates. &lt;/p&gt;

&lt;ul class="org-ul"&gt;
&lt;li&gt;&lt;p&gt; Value channel &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt; Error channel &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;Stopped channel&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="notes" id="org5d9d478"&gt;
&lt;p&gt; Work can terminate in three different ways. &lt;/p&gt;

&lt;ul class="org-ul"&gt;
&lt;li&gt;Return a value.&lt;/li&gt;
&lt;li&gt;Throw an exception&lt;/li&gt;
&lt;li&gt;Be canceled&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; It's been a few minutes. Lets see some simple code. &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgd098f7f" class="outline-4"&gt;
&lt;h5 id="orgd098f7f"&gt;Hello Async World&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-orgd098f7f"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-C++" id="nil"&gt;&lt;span class="linenr"&gt; 1: &lt;/span&gt;
&lt;span class="linenr"&gt; 2: &lt;/span&gt;&lt;span class="org-preprocessor"&gt;#include&lt;/span&gt; &lt;span class="org-string"&gt;&amp;lt;stdexec/execution.hpp&amp;gt;&lt;/span&gt;
&lt;span class="linenr"&gt; 3: &lt;/span&gt;&lt;span class="org-preprocessor"&gt;#include&lt;/span&gt; &lt;span class="org-string"&gt;&amp;lt;exec/static_thread_pool.hpp&amp;gt;&lt;/span&gt;
&lt;span class="linenr"&gt; 4: &lt;/span&gt;&lt;span class="org-preprocessor"&gt;#include&lt;/span&gt; &lt;span class="org-string"&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;
&lt;span class="linenr"&gt; 5: &lt;/span&gt;
&lt;span class="linenr"&gt; 6: &lt;/span&gt;&lt;span class="org-type"&gt;int&lt;/span&gt; &lt;span class="org-function-name"&gt;main&lt;/span&gt;() {
&lt;span class="linenr"&gt; 7: &lt;/span&gt;  &lt;span class="org-constant"&gt;exec&lt;/span&gt;::&lt;span class="org-type"&gt;static_thread_pool&lt;/span&gt; &lt;span class="org-variable-name"&gt;pool&lt;/span&gt;(8);
&lt;span class="linenr"&gt; 8: &lt;/span&gt;
&lt;span class="linenr"&gt; 9: &lt;/span&gt;  &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::&lt;span class="org-type"&gt;scheduler&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;sch&lt;/span&gt; = pool.get_scheduler();
&lt;span class="linenr"&gt;10: &lt;/span&gt;
&lt;span class="linenr"&gt;11: &lt;/span&gt;  &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::&lt;span class="org-type"&gt;sender&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;begin&lt;/span&gt; = &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::schedule(sch);
&lt;span class="linenr"&gt;12: &lt;/span&gt;  &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::&lt;span class="org-type"&gt;sender&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;hi&lt;/span&gt;    = &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::then(begin, [] {
&lt;span class="linenr"&gt;13: &lt;/span&gt;    &lt;span class="org-constant"&gt;std&lt;/span&gt;::cout &amp;lt;&amp;lt; &lt;span class="org-string"&gt;"Hello world! Have an int.\n"&lt;/span&gt;;
&lt;span class="linenr"&gt;14: &lt;/span&gt;    &lt;span class="org-keyword"&gt;return&lt;/span&gt; 13;
&lt;span class="linenr"&gt;15: &lt;/span&gt;  });
&lt;span class="linenr"&gt;16: &lt;/span&gt;
&lt;span class="linenr"&gt;17: &lt;/span&gt;  &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;add_42&lt;/span&gt; = &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::then(hi, [](&lt;span class="org-type"&gt;int&lt;/span&gt; &lt;span class="org-variable-name"&gt;arg&lt;/span&gt;) { &lt;span class="org-keyword"&gt;return&lt;/span&gt; arg + 42; });
&lt;span class="linenr"&gt;18: &lt;/span&gt;
&lt;span class="linenr"&gt;19: &lt;/span&gt;  &lt;span class="org-keyword"&gt;auto&lt;/span&gt; [i] = &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::sync_wait(add_42).value();
&lt;span class="linenr"&gt;20: &lt;/span&gt;
&lt;span class="linenr"&gt;21: &lt;/span&gt;  &lt;span class="org-constant"&gt;std&lt;/span&gt;::cout &amp;lt;&amp;lt; &lt;span class="org-string"&gt;"The int is "&lt;/span&gt; &amp;lt;&amp;lt; i &amp;lt;&amp;lt; &lt;span class="org-string"&gt;'\n'&lt;/span&gt;;
&lt;span class="linenr"&gt;22: &lt;/span&gt;
&lt;span class="linenr"&gt;23: &lt;/span&gt;  &lt;span class="org-keyword"&gt;return&lt;/span&gt; 0;
&lt;span class="linenr"&gt;24: &lt;/span&gt;}
&lt;span class="linenr"&gt;25: &lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt; &lt;a href="https://godbolt.org/z/1M5enroaE"&gt;Compiler Explorer&lt;/a&gt; &lt;/p&gt;

&lt;div class="notes" id="org2eb3f3f"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgf7d68f0" class="outline-4"&gt;
&lt;h5 id="orgf7d68f0"&gt;Hello Async World Results&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-orgf7d68f0"&gt;
&lt;em&gt;&lt;/em&gt;
&lt;pre class="example" id="nil"&gt;
Hello world! Have an int.
The int is 55
&lt;/pre&gt;

&lt;div class="notes" id="orgbf13cfb"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgd5015b3" class="outline-4"&gt;
&lt;h5 id="orgd5015b3"&gt;When All - Concurent Async&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-orgd5015b3"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;&lt;span class="linenr"&gt; 1: &lt;/span&gt;&lt;span class="org-constant"&gt;exec&lt;/span&gt;::&lt;span class="org-type"&gt;static_thread_pool&lt;/span&gt; &lt;span class="org-variable-name"&gt;pool&lt;/span&gt;(3);
&lt;span class="linenr"&gt; 2: &lt;/span&gt;
&lt;span class="linenr"&gt; 3: &lt;/span&gt;&lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;sched&lt;/span&gt; = pool.get_scheduler();
&lt;span class="linenr"&gt; 4: &lt;/span&gt;
&lt;span class="linenr"&gt; 5: &lt;/span&gt;&lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;fun&lt;/span&gt; = [](&lt;span class="org-type"&gt;int&lt;/span&gt; &lt;span class="org-variable-name"&gt;i&lt;/span&gt;) { &lt;span class="org-keyword"&gt;return&lt;/span&gt; i * i; };
&lt;span class="linenr"&gt; 6: &lt;/span&gt;
&lt;span class="linenr"&gt; 7: &lt;/span&gt;&lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;work&lt;/span&gt; = &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::when_all(
&lt;span class="linenr"&gt; 8: &lt;/span&gt;    &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::on(sched, &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::just(0) | &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::then(fun)),
&lt;span class="linenr"&gt; 9: &lt;/span&gt;    &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::on(sched, &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::just(1) | &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::then(fun)),
&lt;span class="linenr"&gt;10: &lt;/span&gt;    &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::on(sched, &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::just(2) | &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::then(fun)));
&lt;span class="linenr"&gt;11: &lt;/span&gt;
&lt;span class="linenr"&gt;12: &lt;/span&gt;&lt;span class="org-keyword"&gt;auto&lt;/span&gt; [i, j, k] = &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::sync_wait(&lt;span class="org-constant"&gt;std&lt;/span&gt;::move(work)).value();
&lt;span class="linenr"&gt;13: &lt;/span&gt;
&lt;span class="linenr"&gt;14: &lt;/span&gt;&lt;span class="org-constant"&gt;std&lt;/span&gt;::printf(&lt;span class="org-string"&gt;"%d %d %d\n"&lt;/span&gt;, i, j, k);
&lt;/pre&gt;
&lt;/div&gt;

&lt;div class="notes" id="org5b2f4f0"&gt;
&lt;p&gt; Describe some work: &lt;/p&gt;

&lt;p&gt; Creates 3 sender pipelines that are executed concurrently by passing to `when_all` &lt;/p&gt;

&lt;p&gt; Each sender is scheduled on `sched` using `on` and starts with `just(n)` that creates a Sender that just forwards `n` to the next sender. &lt;/p&gt;

&lt;p&gt; After `just(n)`, we chain `then(fun)` which invokes `fun` using the value provided from `just()` &lt;/p&gt;

&lt;p&gt; Note: No work actually happens here. Everything is lazy and `work` is just an object that statically represents the work to later be executed &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org8c3d7d7" class="outline-4"&gt;
&lt;h5 id="org8c3d7d7"&gt;When All - Concurent Async - Results&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-org8c3d7d7"&gt;
&lt;em&gt;&lt;/em&gt;
&lt;pre class="example" id="nil"&gt;
0 1 4
&lt;/pre&gt;

&lt;div class="notes" id="orgebda57b"&gt;
&lt;p&gt; Order of execution is by chance, order of results is determined. &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgb1730fb" class="outline-4"&gt;
&lt;h5 id="orgb1730fb"&gt;Dynamic Choice of Sender&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-orgb1730fb"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;&lt;span class="linenr"&gt; 1: &lt;/span&gt;&lt;span class="org-constant"&gt;exec&lt;/span&gt;::&lt;span class="org-type"&gt;static_thread_pool&lt;/span&gt; &lt;span class="org-variable-name"&gt;pool&lt;/span&gt;(3);
&lt;span class="linenr"&gt; 2: &lt;/span&gt;
&lt;span class="linenr"&gt; 3: &lt;/span&gt;&lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;sched&lt;/span&gt; = pool.get_scheduler();
&lt;span class="linenr"&gt; 4: &lt;/span&gt;
&lt;span class="linenr"&gt; 5: &lt;/span&gt;&lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;fun&lt;/span&gt; = [](&lt;span class="org-type"&gt;int&lt;/span&gt; &lt;span class="org-variable-name"&gt;i&lt;/span&gt;) -&amp;gt; &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::sender &lt;span class="org-keyword"&gt;auto&lt;/span&gt; {
&lt;span class="linenr"&gt; 6: &lt;/span&gt;  &lt;span class="org-keyword"&gt;using&lt;/span&gt; &lt;span class="org-keyword"&gt;namespace&lt;/span&gt; &lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-constant"&gt;string_literals&lt;/span&gt;;
&lt;span class="linenr"&gt; 7: &lt;/span&gt;  &lt;span class="org-keyword"&gt;if&lt;/span&gt; ((i % 2) == 0) {
&lt;span class="linenr"&gt; 8: &lt;/span&gt;    &lt;span class="org-keyword"&gt;return&lt;/span&gt; &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::just(&lt;span class="org-string"&gt;"even"&lt;/span&gt;s);
&lt;span class="linenr"&gt; 9: &lt;/span&gt;  } &lt;span class="org-keyword"&gt;else&lt;/span&gt; {
&lt;span class="linenr"&gt;10: &lt;/span&gt;    &lt;span class="org-keyword"&gt;return&lt;/span&gt; &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::just(&lt;span class="org-string"&gt;"odd"&lt;/span&gt;s);
&lt;span class="linenr"&gt;11: &lt;/span&gt;  }
&lt;span class="linenr"&gt;12: &lt;/span&gt;};
&lt;span class="linenr"&gt;13: &lt;/span&gt;
&lt;span class="linenr"&gt;14: &lt;/span&gt;&lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;work&lt;/span&gt; = &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::when_all(
&lt;span class="linenr"&gt;15: &lt;/span&gt;    &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::on(sched, &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::just(0) | &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::let_value(fun)),
&lt;span class="linenr"&gt;16: &lt;/span&gt;    &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::on(sched, &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::just(1) | &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::let_value(fun)),
&lt;span class="linenr"&gt;17: &lt;/span&gt;    &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::on(sched, &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::just(2) | &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::let_value(fun)));
&lt;span class="linenr"&gt;18: &lt;/span&gt;
&lt;span class="linenr"&gt;19: &lt;/span&gt;&lt;span class="org-keyword"&gt;auto&lt;/span&gt; [i, j, k] = &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::sync_wait(&lt;span class="org-constant"&gt;std&lt;/span&gt;::move(work)).value();
&lt;span class="linenr"&gt;20: &lt;/span&gt;
&lt;span class="linenr"&gt;21: &lt;/span&gt;&lt;span class="org-constant"&gt;std&lt;/span&gt;::printf(&lt;span class="org-string"&gt;"%s %s %s"&lt;/span&gt;, i.c_str(), j.c_str(), k.c_str());
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt; &lt;a href="https://godbolt.org/z/7vx69cMj9"&gt;Compiler Explorer&lt;/a&gt; &lt;/p&gt;

&lt;div class="notes" id="org8b2f9b4"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgb681eb0" class="outline-4"&gt;
&lt;h5 id="orgb681eb0"&gt;Enough API to talk about control flow&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-orgb681eb0"&gt;
&lt;p&gt; The minimal set being: &lt;/p&gt;

&lt;ul class="org-ul"&gt;
&lt;li&gt;stdexec::on&lt;/li&gt;
&lt;li&gt;stdexec::just&lt;/li&gt;
&lt;li&gt;stdexec::then&lt;/li&gt;
&lt;li&gt;stdexec::let_value&lt;/li&gt;
&lt;li&gt;stdexec::sync_wait&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt; I will mostly ignore the error and stop channels &lt;/p&gt;

&lt;div class="notes" id="orgd3933b4"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org294db44" class="outline-2"&gt;
&lt;h3 id="org294db44"&gt;Vigorous Handwaving&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org294db44"&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgaa994df" class="outline-3"&gt;
&lt;h4 id="orgaa994df"&gt;Some Theory&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-orgaa994df"&gt;
&lt;p&gt; Continuation Passing Style &lt;/p&gt;

&lt;div class="notes" id="orgfcb288c"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgd5b64c5" class="outline-4"&gt;
&lt;h5 id="orgd5b64c5"&gt;Not At All New&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-orgd5b64c5"&gt;
&lt;p&gt; Sussman and Steele in 1975 &lt;/p&gt;

&lt;p&gt; &lt;a href="https://dspace.mit.edu/bitstream/handle/1721.1/5794/AIM-349.pdf"&gt;AI Memo 349: "Scheme: An Interpreter for Extended Lambda Calculus"&lt;/a&gt; &lt;/p&gt;

&lt;div class="notes" id="org4fc8969"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org0871c6c" class="outline-4"&gt;
&lt;h5 id="org0871c6c"&gt;Pass a "Continuation"&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-org0871c6c"&gt;
&lt;p&gt; Where to go next rather than return the value. &lt;/p&gt;

&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-haskell" id="nil"&gt;&lt;span class="org-haskell-definition"&gt;add&lt;/span&gt; &lt;span class="org-haskell-operator"&gt;::&lt;/span&gt; &lt;span class="org-haskell-type"&gt;Float&lt;/span&gt; &lt;span class="org-haskell-operator"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="org-haskell-type"&gt;Float&lt;/span&gt; &lt;span class="org-haskell-operator"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="org-haskell-type"&gt;Float&lt;/span&gt;
&lt;span class="org-haskell-definition"&gt;add&lt;/span&gt; a b &lt;span class="org-haskell-operator"&gt;=&lt;/span&gt; a &lt;span class="org-haskell-operator"&gt;+&lt;/span&gt; b

&lt;span class="org-haskell-definition"&gt;add_cps&lt;/span&gt; &lt;span class="org-haskell-operator"&gt;::&lt;/span&gt; &lt;span class="org-haskell-type"&gt;Float&lt;/span&gt; &lt;span class="org-haskell-operator"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="org-haskell-type"&gt;Float&lt;/span&gt; &lt;span class="org-haskell-operator"&gt;-&amp;gt;&lt;/span&gt; (&lt;span class="org-haskell-type"&gt;Float&lt;/span&gt; &lt;span class="org-haskell-operator"&gt;-&amp;gt;&lt;/span&gt; a) &lt;span class="org-haskell-operator"&gt;-&amp;gt;&lt;/span&gt; a
&lt;span class="org-haskell-definition"&gt;add_cps&lt;/span&gt; a b cont &lt;span class="org-haskell-operator"&gt;=&lt;/span&gt; cont (a &lt;span class="org-haskell-operator"&gt;+&lt;/span&gt; b)
&lt;/pre&gt;
&lt;/div&gt;

&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;&lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-function-name"&gt;add&lt;/span&gt;(&lt;span class="org-type"&gt;float&lt;/span&gt; &lt;span class="org-variable-name"&gt;a&lt;/span&gt;, &lt;span class="org-type"&gt;float&lt;/span&gt; &lt;span class="org-variable-name"&gt;b&lt;/span&gt;) -&amp;gt; &lt;span class="org-type"&gt;float&lt;/span&gt; {
    &lt;span class="org-keyword"&gt;return&lt;/span&gt; a + b;
}

&lt;span class="org-keyword"&gt;template&lt;/span&gt;&amp;lt;&lt;span class="org-keyword"&gt;typename&lt;/span&gt; &lt;span class="org-type"&gt;Cont&lt;/span&gt;&amp;gt;
&lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-function-name"&gt;add_cps&lt;/span&gt;(&lt;span class="org-type"&gt;float&lt;/span&gt; &lt;span class="org-variable-name"&gt;a&lt;/span&gt;, &lt;span class="org-type"&gt;float&lt;/span&gt; &lt;span class="org-variable-name"&gt;b&lt;/span&gt;, &lt;span class="org-type"&gt;Cont&lt;/span&gt; &lt;span class="org-variable-name"&gt;k&lt;/span&gt;) {
    &lt;span class="org-keyword"&gt;return&lt;/span&gt; k(a+b);
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;div class="notes" id="org83586c7"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org0559af1" class="outline-4"&gt;
&lt;h5 id="org0559af1"&gt;Inherently a tail call&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-org0559af1"&gt;
&lt;p&gt; In continuation passing style we never return. &lt;/p&gt;

&lt;p&gt; We send a value to the rest of the program. &lt;/p&gt;

&lt;p&gt; Hard to express in C++. &lt;/p&gt;

&lt;p&gt; Extra machinery necessary to do the plumbing. &lt;/p&gt;

&lt;p&gt; Also, some risk, so we don't always do TCO. &lt;/p&gt;

&lt;p&gt; We keep the sender "thunks" live so we don't dangle references. &lt;/p&gt;

&lt;div class="notes" id="org7ce856a"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org1e75715" class="outline-4"&gt;
&lt;h5 id="org1e75715"&gt;Intermittently Popular as a Compiler Technique&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-org1e75715"&gt;
&lt;p&gt; The transformations of direct functions to CPS are mechanical. &lt;/p&gt;

&lt;p&gt; The result is easier to optimize and mechanically reason about. &lt;/p&gt;

&lt;p&gt; Equivalent to Single Static Assignment. &lt;/p&gt;

&lt;p&gt; Structured Programming can be converted to CPS. &lt;/p&gt;

&lt;div class="notes" id="org6493700"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org9562d05" class="outline-4"&gt;
&lt;h5 id="org9562d05"&gt;Delimted Continuations&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-org9562d05"&gt;
&lt;p&gt; General continuations reified as a function. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt; Everyone knows that when a process executes a system call like ‘read’, it gets suspended. When the disk delivers the data, the process is resumed. That suspension of a process is its continuation. It is delimited: it is not the check-point of the whole OS, it is the check-point of a process only, from the invocation of main() up to the point main() returns. Normally these suspensions are resumed only once, but can be zero times (exit) or twice (fork). &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt; Oleg Kiselyov &lt;a href="https://okmij.org/ftp/continuations/Fest2008-talk-notes.pdf"&gt;Fest2008-talk-notes.pdf&lt;/a&gt; &lt;/p&gt;

&lt;div class="notes" id="orgf6e78f9"&gt;
&lt;p&gt; If this qoute reminds you of coroutines, you are paying attention. &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org9068f85" class="outline-4"&gt;
&lt;h5 id="org9068f85"&gt;Haskell's Cont Type&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-org9068f85"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-haskell" id="nil"&gt;&lt;span class="org-haskell-keyword"&gt;newtype&lt;/span&gt; &lt;span class="org-haskell-type"&gt;Cont&lt;/span&gt; r a &lt;span class="org-haskell-operator"&gt;=&lt;/span&gt; &lt;span class="org-haskell-constructor"&gt;Cont&lt;/span&gt; { runCont &lt;span class="org-haskell-operator"&gt;::&lt;/span&gt; (a &lt;span class="org-haskell-operator"&gt;-&amp;gt;&lt;/span&gt; r) &lt;span class="org-haskell-operator"&gt;-&amp;gt;&lt;/span&gt; r }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt; This is &lt;u&gt;roughly&lt;/u&gt; equivalent to the sender value channel. A Cont takes a reciever, a function that consumes the value being sent, and produces an r, the result type. &lt;/p&gt;

&lt;p&gt; The &lt;code&gt;identity&lt;/code&gt; function is often used. &lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org172f559" class="outline-4"&gt;
&lt;h5 id="org172f559"&gt;Underlies &lt;code&gt;std::execution&lt;/code&gt;&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-org172f559"&gt;
&lt;p&gt; The plumbing is hidden. &lt;/p&gt;

&lt;p&gt; Senders "send" to their continuations, delimted by the Reciever. &lt;/p&gt;

&lt;div class="notes" id="orgd311a42"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgf9763ec" class="outline-3"&gt;
&lt;h4 id="orgf9763ec"&gt;Another Level of Indirection&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-orgf9763ec"&gt;
&lt;/div&gt;
&lt;div id="outline-container-org68f9649" class="outline-4"&gt;
&lt;h5 id="org68f9649"&gt;Solves all problems&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-org68f9649"&gt;
&lt;p&gt; Adds two more. &lt;/p&gt;

&lt;p&gt; At least &lt;/p&gt;

&lt;div class="notes" id="orgb13c3fd"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orga29d66f" class="outline-4"&gt;
&lt;h5 id="orga29d66f"&gt;CPS Indirects Function Return&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-orga29d66f"&gt;
&lt;p&gt; Transform a function &lt;/p&gt;

&lt;p style="text-align:center"&gt; $latex   A  \rightarrow B   $ &lt;/p&gt;


&lt;p&gt; to &lt;/p&gt;

&lt;p style="text-align:center"&gt; $latex   A  \rightarrow B  \rightarrow ( B \rightarrow R ) \rightarrow R   $ &lt;/p&gt;


&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-haskell" id="nil"&gt;&lt;span class="org-haskell-definition"&gt;add&lt;/span&gt; &lt;span class="org-haskell-operator"&gt;::&lt;/span&gt; &lt;span class="org-haskell-type"&gt;Float&lt;/span&gt; &lt;span class="org-haskell-operator"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="org-haskell-type"&gt;Float&lt;/span&gt; &lt;span class="org-haskell-operator"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="org-haskell-type"&gt;Float&lt;/span&gt;
&lt;span class="org-haskell-definition"&gt;add&lt;/span&gt; a b &lt;span class="org-haskell-operator"&gt;=&lt;/span&gt; a &lt;span class="org-haskell-operator"&gt;+&lt;/span&gt; b

&lt;span class="org-haskell-definition"&gt;add_cps&lt;/span&gt; &lt;span class="org-haskell-operator"&gt;::&lt;/span&gt; &lt;span class="org-haskell-type"&gt;Float&lt;/span&gt; &lt;span class="org-haskell-operator"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="org-haskell-type"&gt;Float&lt;/span&gt; &lt;span class="org-haskell-operator"&gt;-&amp;gt;&lt;/span&gt; (&lt;span class="org-haskell-type"&gt;Float&lt;/span&gt; &lt;span class="org-haskell-operator"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="org-haskell-type"&gt;A&lt;/span&gt;) &lt;span class="org-haskell-operator"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="org-haskell-type"&gt;A&lt;/span&gt;
&lt;span class="org-haskell-definition"&gt;add_cps&lt;/span&gt; a b cont &lt;span class="org-haskell-operator"&gt;=&lt;/span&gt; cont (a &lt;span class="org-haskell-operator"&gt;+&lt;/span&gt; b)
&lt;/pre&gt;
&lt;/div&gt;


&lt;div class="notes" id="orgde3c0e9"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgaf9b3e1" class="outline-4"&gt;
&lt;h5 id="orgaf9b3e1"&gt;Sender Closes Over A&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-orgaf9b3e1"&gt;
&lt;p style="text-align:center"&gt; $latex   B  \rightarrow ( B \rightarrow R ) \rightarrow R   $ &lt;/p&gt;

&lt;p&gt; The $LATEX A$ is (mostly) erased from the Sender. &lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org2621484" class="outline-4"&gt;
&lt;h5 id="org2621484"&gt;Reciever Is The Transform to Result&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-org2621484"&gt;
&lt;p style="text-align:center"&gt; $latex   ( B \rightarrow R ) \rightarrow R   $ &lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org4c55ea0" class="outline-3"&gt;
&lt;h4 id="org4c55ea0"&gt;Some Pictures&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-org4c55ea0"&gt;
&lt;/div&gt;
&lt;div id="outline-container-org5e7ea49" class="outline-5"&gt;
&lt;h6 id="org5e7ea49"&gt;Sender&lt;/h6&gt;
&lt;div class="outline-text-5" id="text-org5e7ea49"&gt;
&lt;div id="org2d613b7" class="figure"&gt; &lt;p&gt;&lt;img src="https://sdowney.org/wp-content/uploads/2024/05/sender.png" alt="sender.png"&gt; &lt;/p&gt; &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgb5de8b8" class="outline-5"&gt;
&lt;h6 id="orgb5de8b8"&gt;&lt;code&gt;just&lt;/code&gt;&lt;/h6&gt;
&lt;div class="outline-text-5" id="text-orgb5de8b8"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;&lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::just(0)
&lt;/pre&gt;
&lt;/div&gt;

&lt;div id="org23c38c7" class="figure"&gt; &lt;p&gt;&lt;img src="https://sdowney.org/wp-content/uploads/2024/05/just.png" alt="just.png"&gt; &lt;/p&gt; &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org533dd2e" class="outline-5"&gt;
&lt;h6 id="org533dd2e"&gt;&lt;code&gt;then&lt;/code&gt;&lt;/h6&gt;
&lt;div class="outline-text-5" id="text-org533dd2e"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;&lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-function-name"&gt;f&lt;/span&gt;(&lt;span class="org-type"&gt;A&lt;/span&gt; &lt;span class="org-variable-name"&gt;a&lt;/span&gt;) -&amp;gt; &lt;span class="org-type"&gt;B&lt;/span&gt;;
&lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;s&lt;/span&gt; = &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::just(a) | &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::then(f);
&lt;/pre&gt;
&lt;/div&gt;

&lt;div id="org7400c8c" class="figure"&gt; &lt;p&gt;&lt;img src="https://sdowney.org/wp-content/uploads/2024/05/then.png" alt="then.png"&gt; &lt;/p&gt; &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgf0c5b3f" class="outline-5"&gt;
&lt;h6 id="orgf0c5b3f"&gt;&lt;code&gt;let_value&lt;/code&gt;&lt;/h6&gt;
&lt;div class="outline-text-5" id="text-orgf0c5b3f"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;&lt;span class="org-type"&gt;sender_of&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;set_value_t&lt;/span&gt;(&lt;span class="org-variable-name"&gt;B&lt;/span&gt;)&amp;gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-function-name"&gt;snd&lt;/span&gt;(&lt;span class="org-type"&gt;A&lt;/span&gt; &lt;span class="org-variable-name"&gt;a&lt;/span&gt;);
&lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;s&lt;/span&gt; = &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::just(a) | &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::let_value(snd);
&lt;/pre&gt;
&lt;/div&gt;

&lt;div id="org8f34211" class="figure"&gt; &lt;p&gt;&lt;img src="https://sdowney.org/wp-content/uploads/2024/05/let_value.png" alt="let_value.png"&gt; &lt;/p&gt; &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org5ac08ab" class="outline-3"&gt;
&lt;h4 id="org5ac08ab"&gt;In which we use the M word&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-org5ac08ab"&gt;
&lt;/div&gt;
&lt;div id="outline-container-org134a392" class="outline-4"&gt;
&lt;h5 id="org134a392"&gt;Sender is a Monad&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-org134a392"&gt;
&lt;p&gt; (surprise) &lt;/p&gt;

&lt;p&gt; (shock, dismay) &lt;/p&gt;

&lt;div class="notes" id="orgdbe487b"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org8b69996" class="outline-4"&gt;
&lt;h5 id="org8b69996"&gt;Function Composition is the hint&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-org8b69996"&gt;
&lt;p&gt; Functions are units of work. &lt;/p&gt;

&lt;p&gt; We compose them into programs. &lt;/p&gt;

&lt;p&gt; The question is if the rules apply. &lt;/p&gt;

&lt;div class="notes" id="org981c41e"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orge30880f" class="outline-4"&gt;
&lt;h5 id="orge30880f"&gt;Monadic Interface&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-orge30880f"&gt;
&lt;dl class="org-dl"&gt;
&lt;dt&gt;bind or and_then&lt;/dt&gt;&lt;dd&gt;&lt;p style="text-align:center"&gt; $latex   M \langle a \rangle \rightarrow (a \rightarrow M \langle b \rangle ) \rightarrow M \langle b \rangle   $ &lt;/p&gt;&lt;/dd&gt;

&lt;dt&gt;fish or kleisli arrow &lt;/dt&gt;&lt;dd&gt;&lt;p style="text-align:center"&gt; $latex   (a \rightarrow M \langle b \rangle ) \rightarrow (b \rightarrow M \langle c \rangle ) \rightarrow (a \rightarrow M \langle c \rangle )   $ &lt;/p&gt;&lt;/dd&gt;

&lt;dt&gt;join or flatten or mconcat&lt;/dt&gt;&lt;dd&gt;&lt;p style="text-align:center"&gt; $latex   M \langle M \langle a \rangle \rangle \rightarrow  M \langle a \rangle   $ &lt;/p&gt;&lt;/dd&gt;
&lt;/dl&gt;

&lt;div class="notes" id="orgb4e34d8"&gt;
&lt;p&gt; Monad Interface &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgadd7e17" class="outline-4"&gt;
&lt;h5 id="orgadd7e17"&gt;Applicative and Functor parts&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-orgadd7e17"&gt;
&lt;dl class="org-dl"&gt;
&lt;dt&gt;make or pure or return&lt;/dt&gt;&lt;dd&gt;&lt;p style="text-align:center"&gt; $latex   a  \rightarrow  M \langle a \rangle   $ &lt;/p&gt;&lt;/dd&gt;

&lt;dt&gt;fmap or transform&lt;/dt&gt;&lt;dd&gt;&lt;p style="text-align:center"&gt; $latex     (a \rightarrow b) \rightarrow M \langle a \rangle \rightarrow M \langle b \rangle    $ &lt;/p&gt;&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt; Any one of the first three and one of the second two can define the other three &lt;/p&gt;

&lt;div class="notes" id="org1ea8d66"&gt;
&lt;p&gt; Monad Interface &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org8809cf7" class="outline-4"&gt;
&lt;h5 id="org8809cf7"&gt;Monad Laws&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-org8809cf7"&gt;
&lt;dl class="org-dl"&gt;
&lt;dt&gt;left identity&lt;/dt&gt;&lt;dd&gt;bind(pure(a), h) == h(a)&lt;/dd&gt;
&lt;dt&gt;right identity&lt;/dt&gt;&lt;dd&gt;bind(m, pure) == m&lt;/dd&gt;
&lt;dt&gt;associativity&lt;/dt&gt;&lt;dd&gt;bind(bind(m, g), h) == bind(m, bind((\x -&amp;gt; g(x), h))&lt;/dd&gt;
&lt;/dl&gt;

&lt;div class="notes" id="orgdeee1f4"&gt;
&lt;p&gt; Monad Laws &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org4a2ed42" class="outline-4"&gt;
&lt;h5 id="org4a2ed42"&gt;Sender is Three Monads in a Trench-coat&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-org4a2ed42"&gt;
&lt;p&gt; Stacked up. &lt;/p&gt;

&lt;ul class="org-ul"&gt;
&lt;li&gt;Value&lt;/li&gt;
&lt;li&gt;Error&lt;/li&gt;
&lt;li&gt;Stopped&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="notes" id="orge90651e"&gt;
&lt;p&gt; The three channels can be crossed, mixed, and remixed. Focus on the value channel for simplicity. &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgd26dd21" class="outline-3"&gt;
&lt;h4 id="orgd26dd21"&gt;The Three Monadic Parts&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-orgd26dd21"&gt;
&lt;div class="notes" id="org2736585"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgec26678" class="outline-4"&gt;
&lt;h5 id="orgec26678"&gt;&lt;code&gt;just&lt;/code&gt;&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-orgec26678"&gt;
&lt;p&gt; Send a value. &lt;/p&gt;

&lt;p&gt; &lt;code&gt;pure&lt;/code&gt; &lt;/p&gt;

&lt;div class="notes" id="orga22f135"&gt;
&lt;p&gt; just lifts a value into the monad &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgfe3008d" class="outline-4"&gt;
&lt;h5 id="orgfe3008d"&gt;&lt;code&gt;then&lt;/code&gt;&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-orgfe3008d"&gt;
&lt;p&gt; Send a value returned from a function that takes its argument from a Sender. &lt;/p&gt;

&lt;p&gt; &lt;code&gt;fmap&lt;/code&gt; or &lt;code&gt;transform&lt;/code&gt; &lt;/p&gt;

&lt;div class="notes" id="org4ce6d5a"&gt;
&lt;p&gt; then is the functor fmap &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org19ddb5d" class="outline-4"&gt;
&lt;h5 id="org19ddb5d"&gt;&lt;code&gt;let_value&lt;/code&gt;&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-org19ddb5d"&gt;
&lt;p&gt; Send what is returned by a Sender returned from a function that takes its argument from a Sender. &lt;/p&gt;

&lt;p&gt; &lt;code&gt;bind&lt;/code&gt; &lt;/p&gt;

&lt;div class="notes" id="orga0ab095"&gt;
&lt;p&gt; let value is the monadic bind &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org65d75e4" class="outline-4"&gt;
&lt;h5 id="org65d75e4"&gt;Necessary and Sufficient&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-org65d75e4"&gt;
&lt;p&gt; The monadic bind gives us the runtime choices we need. &lt;/p&gt;

&lt;div class="notes" id="org3710183"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org9a8af39" class="outline-3"&gt;
&lt;h4 id="org9a8af39"&gt;Basis of Control&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-org9a8af39"&gt;
&lt;ul class="org-ul"&gt;
&lt;li&gt;Sequence&lt;/li&gt;
&lt;li&gt;Decision&lt;/li&gt;
&lt;li&gt;Recursion&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="notes" id="org24383ab"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org9ba54a2" class="outline-4"&gt;
&lt;h5 id="org9ba54a2"&gt;Sequence&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-org9ba54a2"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;&lt;span class="linenr"&gt; 1: &lt;/span&gt;  &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::&lt;span class="org-type"&gt;sender&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;work&lt;/span&gt; =
&lt;span class="linenr"&gt; 2: &lt;/span&gt;      &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::schedule(sch)
&lt;span class="linenr"&gt; 3: &lt;/span&gt;      | &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::then([] {
&lt;span class="linenr"&gt; 4: &lt;/span&gt;          &lt;span class="org-constant"&gt;std&lt;/span&gt;::cout &amp;lt;&amp;lt; &lt;span class="org-string"&gt;"Hello world! Have an int."&lt;/span&gt;;
&lt;span class="linenr"&gt; 5: &lt;/span&gt;          &lt;span class="org-keyword"&gt;return&lt;/span&gt; 13;
&lt;span class="linenr"&gt; 6: &lt;/span&gt;      })
&lt;span class="linenr"&gt; 7: &lt;/span&gt;      | &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::then([](&lt;span class="org-type"&gt;int&lt;/span&gt; &lt;span class="org-variable-name"&gt;arg&lt;/span&gt;) { &lt;span class="org-keyword"&gt;return&lt;/span&gt; arg + 42; });
&lt;span class="linenr"&gt; 8: &lt;/span&gt;
&lt;span class="linenr"&gt; 9: &lt;/span&gt;  &lt;span class="org-keyword"&gt;auto&lt;/span&gt; [i] = &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::sync_wait(work).value();
&lt;span class="linenr"&gt;10: &lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;div class="notes" id="org27c1c32"&gt;
&lt;p&gt; One thing after another. &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org72e7b8d" class="outline-4"&gt;
&lt;h5 id="org72e7b8d"&gt;Decision&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-org72e7b8d"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;&lt;span class="linenr"&gt; 1: &lt;/span&gt;&lt;span class="org-constant"&gt;exec&lt;/span&gt;::&lt;span class="org-type"&gt;static_thread_pool&lt;/span&gt; &lt;span class="org-variable-name"&gt;pool&lt;/span&gt;(8);
&lt;span class="linenr"&gt; 2: &lt;/span&gt;
&lt;span class="linenr"&gt; 3: &lt;/span&gt;&lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::&lt;span class="org-type"&gt;scheduler&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;sch&lt;/span&gt; = pool.get_scheduler();
&lt;span class="linenr"&gt; 4: &lt;/span&gt;
&lt;span class="linenr"&gt; 5: &lt;/span&gt;&lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::&lt;span class="org-type"&gt;sender&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;begin&lt;/span&gt;  = &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::schedule(sch);
&lt;span class="linenr"&gt; 6: &lt;/span&gt;&lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::&lt;span class="org-type"&gt;sender&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;seven&lt;/span&gt;  = &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::just(7);
&lt;span class="linenr"&gt; 7: &lt;/span&gt;&lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::&lt;span class="org-type"&gt;sender&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;eleven&lt;/span&gt; = &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::just(11);
&lt;span class="linenr"&gt; 8: &lt;/span&gt;
&lt;span class="linenr"&gt; 9: &lt;/span&gt;&lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::&lt;span class="org-type"&gt;sender&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;branch&lt;/span&gt; =
&lt;span class="linenr"&gt;10: &lt;/span&gt;    begin
&lt;span class="linenr"&gt;11: &lt;/span&gt;    | &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::then([]() { &lt;span class="org-keyword"&gt;return&lt;/span&gt; &lt;span class="org-constant"&gt;std&lt;/span&gt;::make_tuple(5, 4); })
&lt;span class="linenr"&gt;12: &lt;/span&gt;    | &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::let_value(
&lt;span class="linenr"&gt;13: &lt;/span&gt;        [=](&lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;tpl&lt;/span&gt;) {
&lt;span class="linenr"&gt;14: &lt;/span&gt;        &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-keyword"&gt;const&lt;/span&gt;&amp;amp; [&lt;span class="org-constant"&gt;i&lt;/span&gt;, &lt;span class="org-constant"&gt;j&lt;/span&gt;] = tpl;
&lt;span class="linenr"&gt;15: &lt;/span&gt;
&lt;span class="linenr"&gt;16: &lt;/span&gt;        &lt;span class="org-keyword"&gt;return&lt;/span&gt; tst((i &amp;gt; j),
&lt;span class="linenr"&gt;17: &lt;/span&gt;                   seven | &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::then([&amp;amp;](&lt;span class="org-type"&gt;int&lt;/span&gt; &lt;span class="org-variable-name"&gt;k&lt;/span&gt;) &lt;span class="org-keyword"&gt;noexcept&lt;/span&gt; {
&lt;span class="linenr"&gt;18: &lt;/span&gt;                       &lt;span class="org-constant"&gt;std&lt;/span&gt;::cout &amp;lt;&amp;lt; &lt;span class="org-string"&gt;"true branch "&lt;/span&gt; &amp;lt;&amp;lt; k &amp;lt;&amp;lt; &lt;span class="org-string"&gt;'\n'&lt;/span&gt;;
&lt;span class="linenr"&gt;19: &lt;/span&gt;                   }),
&lt;span class="linenr"&gt;20: &lt;/span&gt;                   eleven | &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::then([&amp;amp;](&lt;span class="org-type"&gt;int&lt;/span&gt; &lt;span class="org-variable-name"&gt;k&lt;/span&gt;) &lt;span class="org-keyword"&gt;noexcept&lt;/span&gt; {
&lt;span class="linenr"&gt;21: &lt;/span&gt;                       &lt;span class="org-constant"&gt;std&lt;/span&gt;::cout &amp;lt;&amp;lt; &lt;span class="org-string"&gt;"false branch "&lt;/span&gt; &amp;lt;&amp;lt; k &amp;lt;&amp;lt; &lt;span class="org-string"&gt;'\n'&lt;/span&gt;;
&lt;span class="linenr"&gt;22: &lt;/span&gt;                   }));
&lt;span class="linenr"&gt;23: &lt;/span&gt;    });
&lt;span class="linenr"&gt;24: &lt;/span&gt;
&lt;span class="linenr"&gt;25: &lt;/span&gt;&lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::sync_wait(&lt;span class="org-constant"&gt;std&lt;/span&gt;::move(branch));
&lt;/pre&gt;
&lt;/div&gt;

&lt;em&gt;&lt;/em&gt;
&lt;pre class="example" id="nil"&gt;
true branch 7
&lt;/pre&gt;

&lt;div class="notes" id="org6433988"&gt;
&lt;p&gt; Control what sender is sent at rentime depending on the state of the program when the work is executing rather than in the structure of the senders. &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgbaa8db1" class="outline-5"&gt;
&lt;h6 id="orgbaa8db1"&gt;&lt;code&gt;tst&lt;/code&gt; function&lt;/h6&gt;
&lt;div class="outline-text-5" id="text-orgbaa8db1"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;&lt;span class="linenr"&gt; 1: &lt;/span&gt;&lt;span class="org-keyword"&gt;inline&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;tst&lt;/span&gt; = [](&lt;span class="org-type"&gt;bool&lt;/span&gt;                 &lt;span class="org-variable-name"&gt;cond&lt;/span&gt;,
&lt;span class="linenr"&gt; 2: &lt;/span&gt;                     &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::&lt;span class="org-type"&gt;sender&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;left&lt;/span&gt;,
&lt;span class="linenr"&gt; 3: &lt;/span&gt;                     &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::&lt;span class="org-type"&gt;sender&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;right&lt;/span&gt;)
&lt;span class="linenr"&gt; 4: &lt;/span&gt;    -&amp;gt; &lt;span class="org-constant"&gt;exec&lt;/span&gt;::&lt;span class="org-type"&gt;variant_sender&lt;/span&gt;&amp;lt;&lt;span class="org-keyword"&gt;decltype&lt;/span&gt;(left),
&lt;span class="linenr"&gt; 5: &lt;/span&gt;                            &lt;span class="org-keyword"&gt;decltype&lt;/span&gt;(right)&amp;gt; {
&lt;span class="linenr"&gt; 6: &lt;/span&gt;  &lt;span class="org-keyword"&gt;if&lt;/span&gt; (cond)
&lt;span class="linenr"&gt; 7: &lt;/span&gt;    &lt;span class="org-keyword"&gt;return&lt;/span&gt; left;
&lt;span class="linenr"&gt; 8: &lt;/span&gt;  &lt;span class="org-keyword"&gt;else&lt;/span&gt;
&lt;span class="linenr"&gt; 9: &lt;/span&gt;    &lt;span class="org-keyword"&gt;return&lt;/span&gt; right;
&lt;span class="linenr"&gt;10: &lt;/span&gt;};
&lt;span class="linenr"&gt;11: &lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org84e1bd6" class="outline-4"&gt;
&lt;h5 id="org84e1bd6"&gt;Recursion&lt;/h5&gt;
&lt;div class="outline-text-4" id="text-org84e1bd6"&gt;
&lt;div class="notes" id="org5757047"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org64da46e" class="outline-5"&gt;
&lt;h6 id="org64da46e"&gt;Simple Recursion&lt;/h6&gt;
&lt;div class="outline-text-5" id="text-org64da46e"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;&lt;span class="linenr"&gt; 1: &lt;/span&gt;
&lt;span class="linenr"&gt; 2: &lt;/span&gt;&lt;span class="org-keyword"&gt;using&lt;/span&gt; &lt;span class="org-type"&gt;any_int_sender&lt;/span&gt; =
&lt;span class="linenr"&gt; 3: &lt;/span&gt;    &lt;span class="org-type"&gt;any_sender_of&lt;/span&gt;&amp;lt;&lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::set_value_t(&lt;span class="org-type"&gt;int&lt;/span&gt;),
&lt;span class="linenr"&gt; 4: &lt;/span&gt;                  &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::set_stopped_t(),
&lt;span class="linenr"&gt; 5: &lt;/span&gt;                  &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::set_error_t(&lt;span class="org-constant"&gt;std&lt;/span&gt;::exception_ptr)&amp;gt;;
&lt;span class="linenr"&gt; 6: &lt;/span&gt;
&lt;span class="linenr"&gt; 7: &lt;/span&gt;&lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-function-name"&gt;fac&lt;/span&gt;(&lt;span class="org-type"&gt;int&lt;/span&gt; &lt;span class="org-variable-name"&gt;n&lt;/span&gt;) -&amp;gt; &lt;span class="org-type"&gt;any_int_sender&lt;/span&gt; {
&lt;span class="linenr"&gt; 8: &lt;/span&gt;    &lt;span class="org-constant"&gt;std&lt;/span&gt;::cout &amp;lt;&amp;lt; &lt;span class="org-string"&gt;"factorial of "&lt;/span&gt; &amp;lt;&amp;lt; n &amp;lt;&amp;lt; &lt;span class="org-string"&gt;"\n"&lt;/span&gt;;
&lt;span class="linenr"&gt; 9: &lt;/span&gt;    &lt;span class="org-keyword"&gt;if&lt;/span&gt; (n == 0)
&lt;span class="linenr"&gt;10: &lt;/span&gt;        &lt;span class="org-keyword"&gt;return&lt;/span&gt; &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::just(1);
&lt;span class="linenr"&gt;11: &lt;/span&gt;
&lt;span class="linenr"&gt;12: &lt;/span&gt;    &lt;span class="org-keyword"&gt;return&lt;/span&gt; &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::just(n - 1)
&lt;span class="linenr"&gt;13: &lt;/span&gt;        | &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::let_value([](&lt;span class="org-type"&gt;int&lt;/span&gt; &lt;span class="org-variable-name"&gt;k&lt;/span&gt;) { &lt;span class="org-keyword"&gt;return&lt;/span&gt; fac(k); })
&lt;span class="linenr"&gt;14: &lt;/span&gt;        | &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::then([&lt;span class="org-constant"&gt;n&lt;/span&gt;](&lt;span class="org-type"&gt;int&lt;/span&gt; &lt;span class="org-variable-name"&gt;k&lt;/span&gt;) { &lt;span class="org-keyword"&gt;return&lt;/span&gt; k * n; });
&lt;span class="linenr"&gt;15: &lt;/span&gt;}
&lt;span class="linenr"&gt;16: &lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;&lt;span class="linenr"&gt; 1: &lt;/span&gt;
&lt;span class="linenr"&gt; 2: &lt;/span&gt;    &lt;span class="org-type"&gt;int&lt;/span&gt;                  &lt;span class="org-variable-name"&gt;k&lt;/span&gt; = 10;
&lt;span class="linenr"&gt; 3: &lt;/span&gt;    &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::&lt;span class="org-type"&gt;sender&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;factorial&lt;/span&gt; =
&lt;span class="linenr"&gt; 4: &lt;/span&gt;        begin
&lt;span class="linenr"&gt; 5: &lt;/span&gt;        | &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::then([=]() { &lt;span class="org-keyword"&gt;return&lt;/span&gt; k; })
&lt;span class="linenr"&gt; 6: &lt;/span&gt;        | &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::let_value([](&lt;span class="org-type"&gt;int&lt;/span&gt; &lt;span class="org-variable-name"&gt;k&lt;/span&gt;) { &lt;span class="org-keyword"&gt;return&lt;/span&gt; fac(k); });
&lt;span class="linenr"&gt; 7: &lt;/span&gt;
&lt;span class="linenr"&gt; 8: &lt;/span&gt;    &lt;span class="org-constant"&gt;std&lt;/span&gt;::cout &amp;lt;&amp;lt; &lt;span class="org-string"&gt;"factorial built\n\n"&lt;/span&gt;;
&lt;span class="linenr"&gt; 9: &lt;/span&gt;
&lt;span class="linenr"&gt;10: &lt;/span&gt;    &lt;span class="org-keyword"&gt;auto&lt;/span&gt; [i] = &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::sync_wait(&lt;span class="org-constant"&gt;std&lt;/span&gt;::move(factorial)).value();
&lt;span class="linenr"&gt;11: &lt;/span&gt;    &lt;span class="org-constant"&gt;std&lt;/span&gt;::cout &amp;lt;&amp;lt; &lt;span class="org-string"&gt;"factorial "&lt;/span&gt; &amp;lt;&amp;lt; k &amp;lt;&amp;lt; &lt;span class="org-string"&gt;" = "&lt;/span&gt; &amp;lt;&amp;lt; i &amp;lt;&amp;lt; &lt;span class="org-string"&gt;'\n'&lt;/span&gt;;
&lt;span class="linenr"&gt;12: &lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;em&gt;&lt;/em&gt;
&lt;pre class="example" id="nil"&gt;
factorial built

factorial of 10
factorial of 9
factorial of 8
factorial of 7
factorial of 6
factorial of 5
factorial of 4
factorial of 3
factorial of 2
factorial of 1
factorial of 0
factorial 10 = 3628800
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgfc40dd9" class="outline-5"&gt;
&lt;h6 id="orgfc40dd9"&gt;General Recursion&lt;/h6&gt;
&lt;div class="outline-text-5" id="text-orgfc40dd9"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;&lt;span class="linenr"&gt; 1: &lt;/span&gt;&lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-function-name"&gt;fib&lt;/span&gt;(&lt;span class="org-type"&gt;int&lt;/span&gt; &lt;span class="org-variable-name"&gt;n&lt;/span&gt;) -&amp;gt; &lt;span class="org-type"&gt;any_int_sender&lt;/span&gt; {
&lt;span class="linenr"&gt; 2: &lt;/span&gt;    &lt;span class="org-keyword"&gt;if&lt;/span&gt; (n == 0)
&lt;span class="linenr"&gt; 3: &lt;/span&gt;        &lt;span class="org-keyword"&gt;return&lt;/span&gt; &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::on(getDefaultScheduler(),  &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::just(0));
&lt;span class="linenr"&gt; 4: &lt;/span&gt;
&lt;span class="linenr"&gt; 5: &lt;/span&gt;    &lt;span class="org-keyword"&gt;if&lt;/span&gt; (n == 1)
&lt;span class="linenr"&gt; 6: &lt;/span&gt;        &lt;span class="org-keyword"&gt;return&lt;/span&gt; &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::on(getDefaultScheduler(), &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::just(1));
&lt;span class="linenr"&gt; 7: &lt;/span&gt;
&lt;span class="linenr"&gt; 8: &lt;/span&gt;    &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;work&lt;/span&gt; = &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::when_all(
&lt;span class="linenr"&gt; 9: &lt;/span&gt;                    &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::on(getDefaultScheduler(), &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::just(n - 1)) |
&lt;span class="linenr"&gt;10: &lt;/span&gt;                        &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::let_value([](&lt;span class="org-type"&gt;int&lt;/span&gt; &lt;span class="org-variable-name"&gt;k&lt;/span&gt;) { &lt;span class="org-keyword"&gt;return&lt;/span&gt; fib(k); }),
&lt;span class="linenr"&gt;11: &lt;/span&gt;                    &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::on(getDefaultScheduler(), &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::just(n - 2)) |
&lt;span class="linenr"&gt;12: &lt;/span&gt;                        &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::let_value([](&lt;span class="org-type"&gt;int&lt;/span&gt; &lt;span class="org-variable-name"&gt;k&lt;/span&gt;) { &lt;span class="org-keyword"&gt;return&lt;/span&gt; fib(k); })) |
&lt;span class="linenr"&gt;13: &lt;/span&gt;                &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::then([](&lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;i&lt;/span&gt;, &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;j&lt;/span&gt;) { &lt;span class="org-keyword"&gt;return&lt;/span&gt; i + j; });
&lt;span class="linenr"&gt;14: &lt;/span&gt;
&lt;span class="linenr"&gt;15: &lt;/span&gt;    &lt;span class="org-keyword"&gt;return&lt;/span&gt; work;
&lt;span class="linenr"&gt;16: &lt;/span&gt;}
&lt;span class="linenr"&gt;17: &lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;&lt;span class="linenr"&gt; 1: &lt;/span&gt;
&lt;span class="linenr"&gt; 2: &lt;/span&gt;&lt;span class="org-type"&gt;int&lt;/span&gt;                  &lt;span class="org-variable-name"&gt;k&lt;/span&gt; = 30;
&lt;span class="linenr"&gt; 3: &lt;/span&gt;    &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::&lt;span class="org-type"&gt;sender&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;fibonacci&lt;/span&gt; =
&lt;span class="linenr"&gt; 4: &lt;/span&gt;        begin | &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::then([=]() { &lt;span class="org-keyword"&gt;return&lt;/span&gt; k; }) |
&lt;span class="linenr"&gt; 5: &lt;/span&gt;        &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::let_value([](&lt;span class="org-type"&gt;int&lt;/span&gt; &lt;span class="org-variable-name"&gt;k&lt;/span&gt;) { &lt;span class="org-keyword"&gt;return&lt;/span&gt; fib(k); });
&lt;span class="linenr"&gt; 6: &lt;/span&gt;
&lt;span class="linenr"&gt; 7: &lt;/span&gt;    &lt;span class="org-constant"&gt;std&lt;/span&gt;::cout &amp;lt;&amp;lt; &lt;span class="org-string"&gt;"fibonacci built\n"&lt;/span&gt;;
&lt;span class="linenr"&gt; 8: &lt;/span&gt;
&lt;span class="linenr"&gt; 9: &lt;/span&gt;    &lt;span class="org-keyword"&gt;auto&lt;/span&gt; [i] = &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::sync_wait(&lt;span class="org-constant"&gt;std&lt;/span&gt;::move(fibonacci)).value();
&lt;span class="linenr"&gt;10: &lt;/span&gt;    &lt;span class="org-constant"&gt;std&lt;/span&gt;::cout &amp;lt;&amp;lt; &lt;span class="org-string"&gt;"fibonacci "&lt;/span&gt; &amp;lt;&amp;lt; k &amp;lt;&amp;lt; &lt;span class="org-string"&gt;" = "&lt;/span&gt; &amp;lt;&amp;lt; i &amp;lt;&amp;lt; &lt;span class="org-string"&gt;'\n'&lt;/span&gt;;
&lt;/pre&gt;
&lt;/div&gt;

&lt;em&gt;&lt;/em&gt;
&lt;pre class="example" id="nil"&gt;
fibonacci built
fibonacci 30 = 832040
fibonacci 30 = 832040
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org5fd882c" class="outline-5"&gt;
&lt;h6 id="org5fd882c"&gt;Fold&lt;/h6&gt;
&lt;div class="outline-text-5" id="text-org5fd882c"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;&lt;span class="linenr"&gt; 1: &lt;/span&gt;
&lt;span class="linenr"&gt; 2: &lt;/span&gt;        &lt;span class="org-keyword"&gt;if&lt;/span&gt; (first == last) {
&lt;span class="linenr"&gt; 3: &lt;/span&gt;            &lt;span class="org-keyword"&gt;return&lt;/span&gt; &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::just(U{&lt;span class="org-constant"&gt;std&lt;/span&gt;::move(init)});
&lt;span class="linenr"&gt; 4: &lt;/span&gt;        }
&lt;span class="linenr"&gt; 5: &lt;/span&gt;
&lt;span class="linenr"&gt; 6: &lt;/span&gt;        &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;nxt&lt;/span&gt; =
&lt;span class="linenr"&gt; 7: &lt;/span&gt;            &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::just(&lt;span class="org-constant"&gt;std&lt;/span&gt;::invoke(f, &lt;span class="org-constant"&gt;std&lt;/span&gt;::move(init), *first)) |
&lt;span class="linenr"&gt; 8: &lt;/span&gt;            &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::let_value([&lt;span class="org-keyword"&gt;this&lt;/span&gt;,
&lt;span class="linenr"&gt; 9: &lt;/span&gt;                                &lt;span class="org-variable-name"&gt;first&lt;/span&gt; = first,
&lt;span class="linenr"&gt;10: &lt;/span&gt;                                &lt;span class="org-variable-name"&gt;last&lt;/span&gt; = last,
&lt;span class="linenr"&gt;11: &lt;/span&gt;                                &lt;span class="org-variable-name"&gt;f&lt;/span&gt; = f
&lt;span class="linenr"&gt;12: &lt;/span&gt;                                ](&lt;span class="org-type"&gt;U&lt;/span&gt; &lt;span class="org-variable-name"&gt;u&lt;/span&gt;) {
&lt;span class="linenr"&gt;13: &lt;/span&gt;                &lt;span class="org-type"&gt;I&lt;/span&gt; &lt;span class="org-variable-name"&gt;i&lt;/span&gt; = first;
&lt;span class="linenr"&gt;14: &lt;/span&gt;                &lt;span class="org-keyword"&gt;return&lt;/span&gt; (*&lt;span class="org-keyword"&gt;this&lt;/span&gt;)(++i, last, u, f);
&lt;span class="linenr"&gt;15: &lt;/span&gt;            });
&lt;span class="linenr"&gt;16: &lt;/span&gt;        &lt;span class="org-keyword"&gt;return&lt;/span&gt; &lt;span class="org-constant"&gt;std&lt;/span&gt;::move(nxt);
&lt;/pre&gt;
&lt;/div&gt;

&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;&lt;span class="linenr"&gt; 1: &lt;/span&gt;
&lt;span class="linenr"&gt; 2: &lt;/span&gt;    &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;v&lt;/span&gt; = &lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-constant"&gt;ranges&lt;/span&gt;::iota_view{1, 10'000};
&lt;span class="linenr"&gt; 3: &lt;/span&gt;
&lt;span class="linenr"&gt; 4: &lt;/span&gt;    &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::&lt;span class="org-type"&gt;sender&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;work&lt;/span&gt; =
&lt;span class="linenr"&gt; 5: &lt;/span&gt;        begin
&lt;span class="linenr"&gt; 6: &lt;/span&gt;        | &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::let_value([&lt;span class="org-variable-name"&gt;i&lt;/span&gt; = &lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-constant"&gt;ranges&lt;/span&gt;::begin(v),
&lt;span class="linenr"&gt; 7: &lt;/span&gt;                              &lt;span class="org-variable-name"&gt;s&lt;/span&gt; = &lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-constant"&gt;ranges&lt;/span&gt;::end(v)]() {
&lt;span class="linenr"&gt; 8: &lt;/span&gt;            &lt;span class="org-keyword"&gt;return&lt;/span&gt; fold_left(i, s, 0, [](&lt;span class="org-type"&gt;int&lt;/span&gt; &lt;span class="org-variable-name"&gt;i&lt;/span&gt;, &lt;span class="org-type"&gt;int&lt;/span&gt; &lt;span class="org-variable-name"&gt;j&lt;/span&gt;) { &lt;span class="org-keyword"&gt;return&lt;/span&gt; i + j; });
&lt;span class="linenr"&gt; 9: &lt;/span&gt;        });
&lt;span class="linenr"&gt;10: &lt;/span&gt;
&lt;span class="linenr"&gt;11: &lt;/span&gt;    &lt;span class="org-keyword"&gt;auto&lt;/span&gt; [i] = &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::sync_wait(&lt;span class="org-constant"&gt;std&lt;/span&gt;::move(work)).value();
&lt;span class="linenr"&gt;12: &lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;em&gt;&lt;/em&gt;
&lt;pre class="example" id="nil"&gt;
work  = 49995000
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgcb782a7" class="outline-5"&gt;
&lt;h6 id="orgcb782a7"&gt;Backtrack&lt;/h6&gt;
&lt;div class="outline-text-5" id="text-orgcb782a7"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;&lt;span class="org-keyword"&gt;using&lt;/span&gt; &lt;span class="org-type"&gt;any_node_sender&lt;/span&gt; =
    &lt;span class="org-type"&gt;any_sender_of&lt;/span&gt;&amp;lt;&lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::set_value_t(&lt;span class="org-constant"&gt;tree&lt;/span&gt;::&lt;span class="org-type"&gt;NodePtr&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;int&lt;/span&gt;&amp;gt;),
                  &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::set_stopped_t(),
                  &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::set_error_t(&lt;span class="org-constant"&gt;std&lt;/span&gt;::exception_ptr)&amp;gt;;

&lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-function-name"&gt;search_tree&lt;/span&gt;(&lt;span class="org-keyword"&gt;auto&lt;/span&gt;                    &lt;span class="org-variable-name"&gt;test&lt;/span&gt;,
                 &lt;span class="org-constant"&gt;tree&lt;/span&gt;::&lt;span class="org-type"&gt;NodePtr&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;int&lt;/span&gt;&amp;gt;      &lt;span class="org-variable-name"&gt;tree&lt;/span&gt;,
                 &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::&lt;span class="org-type"&gt;scheduler&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;sch&lt;/span&gt;,
                 &lt;span class="org-type"&gt;any_node_sender&lt;/span&gt;&amp;amp;&amp;amp;       &lt;span class="org-variable-name"&gt;fail&lt;/span&gt;) -&amp;gt; &lt;span class="org-type"&gt;any_node_sender&lt;/span&gt; {
    &lt;span class="org-keyword"&gt;if&lt;/span&gt; (tree == &lt;span class="org-constant"&gt;nullptr&lt;/span&gt;) {
        &lt;span class="org-keyword"&gt;return&lt;/span&gt; &lt;span class="org-constant"&gt;std&lt;/span&gt;::move(fail);
    }
    &lt;span class="org-keyword"&gt;if&lt;/span&gt; (test(tree)) {
        &lt;span class="org-keyword"&gt;return&lt;/span&gt; &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::just(tree);
    }
    &lt;span class="org-keyword"&gt;return&lt;/span&gt; &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::on(sch, &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::just()) |
           &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::let_value([=, &lt;span class="org-variable-name"&gt;fail&lt;/span&gt; = &lt;span class="org-constant"&gt;std&lt;/span&gt;::move(fail)]() &lt;span class="org-keyword"&gt;mutable&lt;/span&gt; {
               &lt;span class="org-keyword"&gt;return&lt;/span&gt; search_tree(
                   test,
                   tree-&amp;gt;left(),
                   sch,
                   &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::on(sch, &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::just()) |
                       &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::let_value(
                           [=, &lt;span class="org-variable-name"&gt;fail&lt;/span&gt; = &lt;span class="org-constant"&gt;std&lt;/span&gt;::move(fail)]() &lt;span class="org-keyword"&gt;mutable&lt;/span&gt; {
                               &lt;span class="org-keyword"&gt;return&lt;/span&gt; search_tree(
                                   test, tree-&amp;gt;right(), sch, &lt;span class="org-constant"&gt;std&lt;/span&gt;::move(fail));
                           }));
           });
    &lt;span class="org-keyword"&gt;return&lt;/span&gt; fail;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;    &lt;span class="org-constant"&gt;tree&lt;/span&gt;::&lt;span class="org-type"&gt;NodePtr&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;int&lt;/span&gt;&amp;gt; &lt;span class="org-variable-name"&gt;t&lt;/span&gt;;
    &lt;span class="org-keyword"&gt;for&lt;/span&gt; (&lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;i&lt;/span&gt; : &lt;span class="org-constant"&gt;std&lt;/span&gt;::&lt;span class="org-constant"&gt;ranges&lt;/span&gt;::&lt;span class="org-constant"&gt;views&lt;/span&gt;::iota(1, 10'000)) {
        &lt;span class="org-constant"&gt;tree&lt;/span&gt;::&lt;span class="org-constant"&gt;Tree&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;int&lt;/span&gt;&amp;gt;::insert(i, t);
    }

    &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;test&lt;/span&gt; = [](&lt;span class="org-constant"&gt;tree&lt;/span&gt;::&lt;span class="org-type"&gt;NodePtr&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;int&lt;/span&gt;&amp;gt; &lt;span class="org-variable-name"&gt;t&lt;/span&gt;) -&amp;gt; &lt;span class="org-type"&gt;bool&lt;/span&gt; {
        &lt;span class="org-keyword"&gt;return&lt;/span&gt; t ? t-&amp;gt;data() == 500 : &lt;span class="org-constant"&gt;false&lt;/span&gt;;
    };

    &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;fail&lt;/span&gt; = begin | &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::then([]() { &lt;span class="org-keyword"&gt;return&lt;/span&gt; &lt;span class="org-constant"&gt;tree&lt;/span&gt;::&lt;span class="org-type"&gt;NodePtr&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;int&lt;/span&gt;&amp;gt;{}; });

    &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::&lt;span class="org-type"&gt;sender&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;work&lt;/span&gt; =
        begin | &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::let_value([=]() {
            &lt;span class="org-keyword"&gt;return&lt;/span&gt; search_tree(test, t, sch, &lt;span class="org-constant"&gt;std&lt;/span&gt;::move(fail));
        });

    &lt;span class="org-keyword"&gt;auto&lt;/span&gt; [n] = &lt;span class="org-constant"&gt;stdexec&lt;/span&gt;::sync_wait(&lt;span class="org-constant"&gt;std&lt;/span&gt;::move(work)).value();

    &lt;span class="org-constant"&gt;std&lt;/span&gt;::cout &amp;lt;&amp;lt; &lt;span class="org-string"&gt;"work "&lt;/span&gt;
              &amp;lt;&amp;lt; &lt;span class="org-string"&gt;" = "&lt;/span&gt; &amp;lt;&amp;lt; n-&amp;gt;data() &amp;lt;&amp;lt; &lt;span class="org-string"&gt;'\n'&lt;/span&gt;;
&lt;/pre&gt;
&lt;/div&gt;

&lt;em&gt;&lt;/em&gt;
&lt;pre class="example" id="nil"&gt;
work  = 500
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org91abfba" class="outline-2"&gt;
&lt;h3 id="org91abfba"&gt;Don't Do That&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org91abfba"&gt;
&lt;/div&gt;
&lt;div id="outline-container-org1aa4228" class="outline-3"&gt;
&lt;h4 id="org1aa4228"&gt;Can is not Should&lt;/h4&gt;
&lt;/div&gt;
&lt;div id="outline-container-orga3f48a3" class="outline-3"&gt;
&lt;h4 id="orga3f48a3"&gt;Write an Algorithm&lt;/h4&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgbea3c89" class="outline-3"&gt;
&lt;h4 id="orgbea3c89"&gt;Why You Might&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-orgbea3c89"&gt;
&lt;ul class="org-ul"&gt;
&lt;li&gt;Throughput&lt;/li&gt;
&lt;li&gt;Interruptable&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="notes" id="orgd77b1a9"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org03d3e92" class="outline-2"&gt;
&lt;h3 id="org03d3e92"&gt;Thank You&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org03d3e92"&gt;
&lt;div class="notes" id="org76ec745"&gt;
&lt;p&gt;  &lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description><guid>https://sdowney.org/posts/index.php/2024/05/18/slides-from-cnow-2023-async-control-flow/</guid><pubDate>Sat, 18 May 2024 22:27:00 GMT</pubDate></item><item><title>Some Informal Remarks Towards a New Theory of Trait Customization</title><link>https://sdowney.org/posts/index.php/2023/12/24/some-informal-remarks-towards-a-new-theory-of-trait-customization/</link><dc:creator>Steve Downey</dc:creator><description>&lt;div id="outline-container-org0a7dcc5" class="outline-2"&gt;
&lt;h3 id="org0a7dcc5"&gt;A Possible Technique&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org0a7dcc5"&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;&lt;span class="org-keyword"&gt;constexpr&lt;/span&gt; &lt;span class="org-type"&gt;bool&lt;/span&gt; &lt;span class="org-function-name"&gt;g&lt;/span&gt;(&lt;span class="org-type"&gt;int&lt;/span&gt; &lt;span class="org-variable-name"&gt;lhs&lt;/span&gt;, &lt;span class="org-type"&gt;int&lt;/span&gt; &lt;span class="org-variable-name"&gt;rhs&lt;/span&gt;) {
    &lt;span class="org-keyword"&gt;auto&lt;/span&gt;&amp;amp; &lt;span class="org-variable-name"&gt;op&lt;/span&gt; = &lt;span class="org-type"&gt;partial_eq&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;int&lt;/span&gt;&amp;gt;;
    &lt;span class="org-keyword"&gt;return&lt;/span&gt; op.ne(lhs, rhs);
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;a href="https://godbolt.org/z/Ge43cWfn8"&gt;Compiler Explorer with Supporting Code&lt;/a&gt;

A trait is defined as a template variable that implements the required operations. Implementation of those operations is possible via a variety of techniques, but existence is concept checkable. It might prove useful to explicitly opt in to a sufficiently generic trait.

The technique satisfies the openness requirement, that the trait can be created independently of the type that models the trait. There can still only be one definition, but this enables opting std:: types into new traits, for example.

It also doesn't universally grab an operation name. The trait variable is namespaceable.

Syntax isn't really awesome, but not utterly unworkable.

&lt;/div&gt;
&lt;/div&gt;

&lt;!-- TEASER_END --&gt;

&lt;div id="outline-container-org5ad6709" class="outline-2"&gt;
&lt;h3 id="org5ad6709"&gt;Background&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org5ad6709"&gt;

 Several years ago, Barry Revzin in "&lt;a href="https://brevzin.github.io/c++/2020/12/01/tag-invoke/"&gt;Why tag_invoke is not the solution I want"&lt;/a&gt; outlined the characteristics that a good customization interface would have. Quoting
&lt;blockquote&gt;
&lt;ol class="org-ol"&gt;
    &lt;li&gt;The ability to see clearly, in code, what the interface is that can (or needs to) be customized.&lt;/li&gt;
    &lt;li&gt;The ability to provide default implementations that can be overridden, not just non-defaulted functions.&lt;/li&gt;
    &lt;li&gt;The ability to opt in explicitly to the interface.&lt;/li&gt;
    &lt;li&gt;The inability to incorrectly opt in to the interface (for instance, if the interface has a function that takes an int, you cannot opt in by accidentally taking an unsigned int).&lt;/li&gt;
    &lt;li&gt;The ability to easily invoke the customized implementation. Alternatively, the inability to accidentally invoke the base implementation.&lt;/li&gt;
    &lt;li&gt;The ability to easily verify that a type implements an interface.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
I believe that with some support on the implementation side, and some &lt;code&gt;concept&lt;/code&gt; definitions to assert correct usage, having an explicit object that implements the required traits for a concept can satisfy more of the requirements than &lt;code&gt;tag_invoke&lt;/code&gt; or &lt;code&gt;std::&lt;/code&gt; customization points. The trade-off is that usage of the trait is explicit and not dependent on arguments to the trait, which means that it is more verbose and possible to get wrong in both subtle and gross ways.

&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org87d886f" class="outline-2"&gt;
&lt;h3 id="org87d886f"&gt;&lt;code&gt;concept_map&lt;/code&gt;&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org87d886f"&gt;

 In the original proposal for C++ concepts, there was a facility called ~concept_map~s where
&lt;blockquote&gt; Concept maps describe how a set of template arguments satisfy the requirements stated in the body of a concept definition.&lt;/blockquote&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;&lt;span class="org-keyword"&gt;class&lt;/span&gt; &lt;span class="org-type"&gt;student_record&lt;/span&gt; {
  &lt;span class="org-keyword"&gt;public&lt;/span&gt;:
    &lt;span class="org-type"&gt;string&lt;/span&gt; &lt;span class="org-variable-name"&gt;id&lt;/span&gt;;
    &lt;span class="org-type"&gt;string&lt;/span&gt; &lt;span class="org-variable-name"&gt;name&lt;/span&gt;;
    &lt;span class="org-type"&gt;string&lt;/span&gt; &lt;span class="org-variable-name"&gt;address&lt;/span&gt;;
};

&lt;span class="org-keyword"&gt;concept&lt;/span&gt; &lt;span class="org-type"&gt;EqualityComparable&lt;/span&gt;&amp;lt;&lt;span class="org-keyword"&gt;typename&lt;/span&gt; &lt;span class="org-type"&gt;T&lt;/span&gt;&amp;gt; {
    &lt;span class="org-type"&gt;bool&lt;/span&gt; &lt;span class="org-keyword"&gt;operator&lt;/span&gt;&lt;span class="org-variable-name"&gt;==&lt;/span&gt;(&lt;span class="org-type"&gt;T&lt;/span&gt;, &lt;span class="org-type"&gt;T&lt;/span&gt;);
}

&lt;span class="org-type"&gt;concept_map&lt;/span&gt; &lt;span class="org-type"&gt;EqualityComparable&lt;/span&gt;&lt;span class="org-variable-name"&gt;&amp;lt;student_record&amp;gt;&lt;/span&gt; {
    &lt;span class="org-type"&gt;bool&lt;/span&gt; &lt;span class="org-keyword"&gt;operator&lt;/span&gt;&lt;span class="org-variable-name"&gt;==&lt;/span&gt;(&lt;span class="org-keyword"&gt;const&lt;/span&gt; &lt;span class="org-type"&gt;student_record&lt;/span&gt;&amp;amp; &lt;span class="org-variable-name"&gt;a&lt;/span&gt;, &lt;span class="org-keyword"&gt;const&lt;/span&gt; &lt;span class="org-type"&gt;student_record&lt;/span&gt;&amp;amp; &lt;span class="org-variable-name"&gt;b&lt;/span&gt;) {
        &lt;span class="org-keyword"&gt;return&lt;/span&gt; a.id == b.id;
    }
};

&lt;span class="org-keyword"&gt;template&lt;/span&gt;&amp;lt;&lt;span class="org-keyword"&gt;typename&lt;/span&gt; &lt;span class="org-type"&gt;T&lt;/span&gt;&amp;gt; &lt;span class="org-keyword"&gt;requires&lt;/span&gt; &lt;span class="org-type"&gt;EqualityComparable&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;T&lt;/span&gt;&amp;gt;
&lt;span class="org-type"&gt;void&lt;/span&gt; &lt;span class="org-function-name"&gt;f&lt;/span&gt;(&lt;span class="org-type"&gt;T&lt;/span&gt;);

f(student_record()); &lt;span class="org-comment-delimiter"&gt;// &lt;/span&gt;&lt;span class="org-comment"&gt;okay, have concept_map EqualityComparable&amp;lt;student_record&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2617.pdf"&gt;n2617&lt;/a&gt;

This allowed for customizing how the various requirements for a concept were implemented for a particular type.

This was lost in Concepts Lite, a.k.a C++20 Concepts.

Other generic type systems have implemented something like this feature, as well as definition checking. In particular, Rust Traits are an analagous feature.

&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org71089d8" class="outline-2"&gt;
&lt;h3 id="org71089d8"&gt;Rust Traits&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org71089d8"&gt;
&lt;blockquote&gt; A trait is a collection of methods defined for an unknown type: &lt;code&gt;Self&lt;/code&gt;. They can access other methods declared in the same trait.&lt;/blockquote&gt;
An example that Revzin mentions, and that my first example alludes to is PartialEq:
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-rust" id="nil"&gt;&lt;span class="org-keyword"&gt;pub&lt;/span&gt; &lt;span class="org-keyword"&gt;trait&lt;/span&gt; &lt;span class="org-type"&gt;PartialEq&lt;/span&gt;&amp;lt;&lt;span class="org-variable-name"&gt;Rhs&lt;/span&gt;: &lt;span class="org-rust-question-mark"&gt;?&lt;/span&gt;&lt;span class="org-type"&gt;Sized&lt;/span&gt; = &lt;span class="org-type"&gt;Self&lt;/span&gt;&amp;gt; {
    &lt;span class="org-doc"&gt;/// This method tests for `self` and `other` values to be equal, and is used&lt;/span&gt;
    &lt;span class="org-doc"&gt;/// by `==`.&lt;/span&gt;
    &lt;span class="org-keyword"&gt;fn&lt;/span&gt; &lt;span class="org-function-name"&gt;eq&lt;/span&gt;(&lt;span class="org-rust-ampersand"&gt;&amp;amp;&lt;/span&gt;&lt;span class="org-keyword"&gt;self&lt;/span&gt;, &lt;span class="org-variable-name"&gt;other&lt;/span&gt;: &lt;span class="org-rust-ampersand"&gt;&amp;amp;&lt;/span&gt;&lt;span class="org-type"&gt;Rhs&lt;/span&gt;) -&amp;gt; &lt;span class="org-type"&gt;bool&lt;/span&gt;;

    &lt;span class="org-doc"&gt;/// This method tests for `!=`. The default implementation is almost always&lt;/span&gt;
    &lt;span class="org-doc"&gt;/// sufficient, and should not be overridden without very good reason.&lt;/span&gt;
    &lt;span class="org-keyword"&gt;fn&lt;/span&gt; &lt;span class="org-function-name"&gt;ne&lt;/span&gt;(&lt;span class="org-rust-ampersand"&gt;&amp;amp;&lt;/span&gt;&lt;span class="org-keyword"&gt;self&lt;/span&gt;, &lt;span class="org-variable-name"&gt;other&lt;/span&gt;: &lt;span class="org-rust-ampersand"&gt;&amp;amp;&lt;/span&gt;&lt;span class="org-type"&gt;Rhs&lt;/span&gt;) -&amp;gt; &lt;span class="org-type"&gt;bool&lt;/span&gt; {
        !&lt;span class="org-keyword"&gt;self&lt;/span&gt;.eq(other)
    }
}
&lt;/pre&gt;
&lt;/div&gt;
From &lt;a href="https://doc.rust-lang.org/src/core/cmp.rs.html#219"&gt;https://doc.rust-lang.org/src/core/cmp.rs.html#219&lt;/a&gt;

In Rust this is built into the language, and operators like == are automatically rewritten into &lt;code&gt;eq&lt;/code&gt; and &lt;code&gt;ne&lt;/code&gt;. At least that's my understanding. We're not going to get that in C++, ever. With both Rust and Concept Maps, though, we do get new named operations that can be used unqualified in generic code and the compiler will be directed to the correct implementation.

Giving up on that is key to a way forward in C++.

&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org9dd42da" class="outline-2"&gt;
&lt;h3 id="org9dd42da"&gt;A trait object&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org9dd42da"&gt;

 The technique I'm considering and describing here is modeled loosly after the implementation of Haskell typeclasses in GHC. For a particular instance of a typeclass, a record holding the operations based on the actual type in use is created and made available, and the named operations are lifted into scope and the functions in the record called when used. It is as if a virtual function table was implemented with name lookup rather than index.

In C++, particularly in current post-C++20 C++, we can look up an object via a template variable. The implementations of different specializations of a template variable do not need to be connected in any way. We have to provide a definition, since to make it look like a declaration it's necessary to provide some type such as false_type. Alternatively, we could declare it as an int, but mark it as &lt;code&gt;extern&lt;/code&gt; and not define it. I'm still researching alternatives.
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-C++" id="nil"&gt;&lt;span class="org-keyword"&gt;template&lt;/span&gt;&amp;lt;&lt;span class="org-keyword"&gt;class&lt;/span&gt; &lt;span class="org-type"&gt;T&lt;/span&gt;&amp;gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;someTrait&lt;/span&gt; = &lt;span class="org-constant"&gt;std&lt;/span&gt;::false_type{};

&lt;span class="org-keyword"&gt;template&lt;/span&gt; &amp;lt;&lt;span class="org-keyword"&gt;typename&lt;/span&gt; &lt;span class="org-type"&gt;T&lt;/span&gt;&amp;gt;
&lt;span class="org-keyword"&gt;extern&lt;/span&gt; &lt;span class="org-type"&gt;int&lt;/span&gt; &lt;span class="org-variable-name"&gt;otherTrait&lt;/span&gt;;
&lt;/pre&gt;
&lt;/div&gt;
These are useful if there is no good generic definition of the trait.

If there is a good generic definition of a trait, the trait variable is straightforward:
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;&lt;span class="org-keyword"&gt;constexpr&lt;/span&gt; &lt;span class="org-keyword"&gt;inline&lt;/span&gt; &lt;span class="org-keyword"&gt;struct&lt;/span&gt; {
    &lt;span class="org-keyword"&gt;constexpr&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-function-name"&gt;eq&lt;/span&gt;(&lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;rhs&lt;/span&gt;, &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;lhs&lt;/span&gt;) &lt;span class="org-keyword"&gt;const&lt;/span&gt; {&lt;span class="org-keyword"&gt;return&lt;/span&gt; rhs == lhs;}
    &lt;span class="org-keyword"&gt;constexpr&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-function-name"&gt;ne&lt;/span&gt;(&lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;rhs&lt;/span&gt;, &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;lhs&lt;/span&gt;) &lt;span class="org-keyword"&gt;const&lt;/span&gt; {&lt;span class="org-keyword"&gt;return&lt;/span&gt; &lt;span class="org-negation-char"&gt;!&lt;/span&gt;eq(lhs, rhs);}
} &lt;span class="org-variable-name"&gt;partial_eq_default&lt;/span&gt;;

&lt;span class="org-keyword"&gt;template&lt;/span&gt;&amp;lt;&lt;span class="org-keyword"&gt;class&lt;/span&gt; &lt;span class="org-type"&gt;T&lt;/span&gt;&amp;gt;
&lt;span class="org-keyword"&gt;constexpr&lt;/span&gt; &lt;span class="org-keyword"&gt;inline&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;partial_eq&lt;/span&gt; = partial_eq_default;
&lt;/pre&gt;
&lt;/div&gt;
In this case, though, there probably ought to be an opt in so that the trait can be checked by concept.

An opt in mechanism is a bit verbose, but not necessarily complicated:
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;&lt;span class="org-keyword"&gt;template&lt;/span&gt;&amp;lt;&lt;span class="org-keyword"&gt;class&lt;/span&gt; &lt;span class="org-type"&gt;T&lt;/span&gt;&amp;gt; &lt;span class="org-keyword"&gt;constexpr&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;partial_eq_type&lt;/span&gt; = &lt;span class="org-constant"&gt;false&lt;/span&gt;;
&lt;span class="org-keyword"&gt;template&lt;/span&gt;&amp;lt;&amp;gt; &lt;span class="org-keyword"&gt;constexpr&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-type"&gt;partial_eq_type&lt;/span&gt;&lt;span class="org-variable-name"&gt;&amp;lt;int&amp;gt;&lt;/span&gt; = &lt;span class="org-constant"&gt;true&lt;/span&gt;;
&lt;span class="org-keyword"&gt;template&lt;/span&gt;&amp;lt;&amp;gt; &lt;span class="org-keyword"&gt;constexpr&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-type"&gt;partial_eq_type&lt;/span&gt;&lt;span class="org-variable-name"&gt;&amp;lt;double&amp;gt;&lt;/span&gt; = &lt;span class="org-constant"&gt;true&lt;/span&gt;;

&lt;span class="org-keyword"&gt;template&lt;/span&gt;&amp;lt;&lt;span class="org-keyword"&gt;typename&lt;/span&gt; &lt;span class="org-type"&gt;T&lt;/span&gt;&amp;gt;
&lt;span class="org-keyword"&gt;concept&lt;/span&gt; &lt;span class="org-type"&gt;is_partial_eq&lt;/span&gt; =
  &lt;span class="org-type"&gt;partial_eq_type&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;T&lt;/span&gt;&amp;gt; &amp;amp;&amp;amp;
    &lt;span class="org-keyword"&gt;requires&lt;/span&gt;(&lt;span class="org-type"&gt;T&lt;/span&gt; &lt;span class="org-variable-name"&gt;lhs&lt;/span&gt;, &lt;span class="org-type"&gt;T&lt;/span&gt; &lt;span class="org-variable-name"&gt;rhs&lt;/span&gt;) {
    &lt;span class="org-type"&gt;partial_eq&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;T&lt;/span&gt;&amp;gt;.eq(lhs, rhs);
    &lt;span class="org-type"&gt;partial_eq&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;T&lt;/span&gt;&amp;gt;.ne(lhs, rhs);
};

&lt;span class="org-keyword"&gt;constexpr&lt;/span&gt; &lt;span class="org-type"&gt;bool&lt;/span&gt; &lt;span class="org-function-name"&gt;h&lt;/span&gt;(&lt;span class="org-type"&gt;is_partial_eq&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;lhs&lt;/span&gt;, &lt;span class="org-type"&gt;is_partial_eq&lt;/span&gt; &lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-variable-name"&gt;rhs&lt;/span&gt;) {
    &lt;span class="org-keyword"&gt;return&lt;/span&gt; &lt;span class="org-type"&gt;partial_eq&lt;/span&gt;&amp;lt;&lt;span class="org-keyword"&gt;decltype&lt;/span&gt;(lhs)&amp;gt;.eq(lhs, rhs);
}
&lt;/pre&gt;
&lt;/div&gt;
I have not done a good job at allocating names to the various bits and pieces. Please excuse this.

&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgf6b19fc" class="outline-2"&gt;
&lt;h3 id="orgf6b19fc"&gt;What have I missed?&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-orgf6b19fc"&gt;

 We've been making variable templates more capable in many ways, and the concept checks to ensure correctness are new, but has anyone else explored this and found insurmountable problems?

&lt;/div&gt;
&lt;/div&gt;</description><guid>https://sdowney.org/posts/index.php/2023/12/24/some-informal-remarks-towards-a-new-theory-of-trait-customization/</guid><pubDate>Sun, 24 Dec 2023 05:00:00 GMT</pubDate></item><item><title>Special Blocks and Emacs Org-mode Export</title><link>https://sdowney.org/posts/special-blocks-and-emacs-org-mode-export/</link><dc:creator>Steve Downey</dc:creator><description>&lt;nav id="table-of-contents" role="doc-toc"&gt;
&lt;h3&gt;Table of Contents&lt;/h3&gt;
&lt;div id="text-table-of-contents" role="doc-toc"&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://sdowney.org/posts/special-blocks-and-emacs-org-mode-export/#orgf2bc23f"&gt;1. Delete blocks and text&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sdowney.org/posts/special-blocks-and-emacs-org-mode-export/#org76721e5"&gt;2. Insert blocks and text&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sdowney.org/posts/special-blocks-and-emacs-org-mode-export/#org3c7f3fc"&gt;3. Comparison Table&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/nav&gt;
&lt;ul class="org-ul"&gt;
&lt;li&gt;Document number:&lt;/li&gt;
&lt;li&gt;Date:  2021-12-03&lt;/li&gt;
&lt;li&gt;Author: Steve Downey &amp;lt;sdowney2@bloomberg.net&amp;gt;, &amp;lt;sdowney@gmail.com&amp;gt;&lt;/li&gt;
&lt;li&gt;Audience: WG21 Emacs Authors&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="ABSTRACT" id="org257c800"&gt;
&lt;p&gt; Abstract: Making emacs org-mode more usable for writing WG21 papers. &lt;/p&gt;

&lt;/div&gt;

&lt;!-- TEASER_END --&gt;




&lt;div id="outline-container-orgf2bc23f" class="outline-2"&gt;
&lt;h3 id="orgf2bc23f"&gt;&lt;span class="section-number-2"&gt;1.&lt;/span&gt; Delete blocks and text&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-1"&gt;
{\color{red}\bfseries
&lt;p&gt; Remove this terrible old stuff. &lt;/p&gt;

}
&lt;p&gt; And the bad &lt;del style="color: red;"&gt;word&lt;/del&gt; from this sentence. &lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id="outline-container-org76721e5" class="outline-2"&gt;
&lt;h3 id="org76721e5"&gt;&lt;span class="section-number-2"&gt;2.&lt;/span&gt; Insert blocks and text&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-2"&gt;
&lt;ins style="color: green;"&gt;
&lt;p&gt; Add this wonderful new text &lt;/p&gt;

&lt;/ins&gt;
&lt;p&gt; And put this cool &lt;ins style="color: green;"&gt;word&lt;/ins&gt; in. &lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;div id="outline-container-org3c7f3fc" class="outline-2"&gt;
&lt;h3 id="org3c7f3fc"&gt;&lt;span class="section-number-2"&gt;3.&lt;/span&gt; Comparison Table&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-3"&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr class="header"&gt;&lt;th&gt;&lt;div style="text-align:center"&gt;&lt;strong&gt;Old Busted&lt;/strong&gt;&lt;/div&gt;&lt;/th&gt;&lt;th&gt;&lt;div style="text-align:center"&gt;&lt;strong&gt;New Hotness&lt;/strong&gt;&lt;/div&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr class="odd"&gt;
&lt;td&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-C++" id="nil"&gt;&lt;span class="org-type"&gt;int&lt;/span&gt; &lt;span class="org-variable-name"&gt;a&lt;/span&gt; = 3 + 2 + 1;
&lt;/pre&gt;
&lt;/div&gt;

&lt;/td&gt;
&lt;td&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-C++" id="nil"&gt;&lt;span class="org-type"&gt;int&lt;/span&gt; &lt;span class="org-variable-name"&gt;a&lt;/span&gt; = cool_sum({1, 2, 3});
&lt;/pre&gt;
&lt;/div&gt;

&lt;/td&gt;

&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;</description><guid>https://sdowney.org/posts/special-blocks-and-emacs-org-mode-export/</guid><pubDate>Fri, 03 Dec 2021 05:00:00 GMT</pubDate></item><item><title>A local CMake workflow with Docker</title><link>https://sdowney.org/posts/index.php/2021/10/03/a-local-cmake-workflow-with-docker/</link><dc:creator>Steve Downey</dc:creator><description>&lt;p&gt; l#+BLOG: sdowney &lt;/p&gt;

&lt;p&gt; An outline of a template that provides an automated workflow driving a CMake project in a docker container. &lt;/p&gt;

&lt;p&gt; This post must be read in concert with &lt;a href="https://github.com/steve-downey/scratch"&gt;https://github.com/steve-downey/scratch&lt;/a&gt; of which it is part. &lt;/p&gt;

&lt;div id="outline-container-orge73d9dc" class="outline-2"&gt;
&lt;h3 id="orge73d9dc"&gt;Routine process should be automated&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-orge73d9dc"&gt;
&lt;p&gt; Building a project that uses cmake runs through a predictable lifecycle that you should be able to pick up where you left off without remembering, and for which you should be able to state your goal, not the step you are on. &lt;code&gt;make&lt;/code&gt; is designed for this, and can drive the processs. &lt;/p&gt;
&lt;/div&gt;

&lt;!-- TEASER_END --&gt;

&lt;div id="outline-container-org7268417" class="outline-3"&gt;
&lt;h4 id="org7268417"&gt;The workflow&lt;/h4&gt;
&lt;div class="outline-text-3" id="text-org7268417"&gt;
&lt;ul class="org-ul"&gt;
&lt;li&gt;Update any submodules&lt;/li&gt;
&lt;li&gt;Create a build area specific to the toolchain&lt;/li&gt;
&lt;li&gt;Run cmake with that toolchain in the build area&lt;/li&gt;
&lt;li&gt;Run the build in the build area&lt;/li&gt;
&lt;li&gt;Run tests, either dependent or independent of rebuild&lt;/li&gt;
&lt;li&gt;Run the intall&lt;/li&gt;
&lt;li&gt;(optionally) Clean the build&lt;/li&gt;
&lt;li&gt;(optionally) Clean the configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; All of the steps have recognizable filesystem artifacts, need to be run in order, and if there are any failures, the process should stop. &lt;/p&gt;

&lt;p&gt; So we want a &lt;code&gt;make&lt;/code&gt; system on top of our meta-make build system. &lt;/p&gt;

&lt;p&gt; The one thing this system does, that plain cmake doesn't automate, is making sure that any changes are incorporated into a build before tests are run. CMake splits these, in order to provide the option of running tests without a recompile. I think that is a mistake to automate, but I do provide a target that just runs ctest. &lt;/p&gt;

&lt;p&gt; My normal target is &lt;code&gt;test&lt;/code&gt; &lt;/p&gt;

&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-bash" id="nil"&gt;make test
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt; This will run through all of the steps, but only those, necessary to compile and run tests. The core commands for the build driver are &lt;/p&gt;

&lt;dl class="org-dl"&gt;
&lt;dt&gt;compile&lt;/dt&gt;&lt;dd&gt;Compile all out of date source&lt;/dd&gt;
&lt;dt&gt;install&lt;/dt&gt;&lt;dd&gt;Install into the INSTALL_PREFIX&lt;/dd&gt;
&lt;dt&gt;ctest&lt;/dt&gt;&lt;dd&gt;Run the currently build test suite&lt;/dd&gt;
&lt;dt&gt;test&lt;/dt&gt;&lt;dd&gt;Build and run the test suite&lt;/dd&gt;
&lt;dt&gt;cmake&lt;/dt&gt;&lt;dd&gt;run cmake again in the build area&lt;/dd&gt;
&lt;dt&gt;clean&lt;/dt&gt;&lt;dd&gt;Clean the build area&lt;/dd&gt;
&lt;dt&gt;realclean&lt;/dt&gt;&lt;dd&gt;Delete the build area&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt; There are several makefile variables controlling the details of what toolchain is used and where things are located. By default the build and install are completely out of the source tree, in ../cmake.bld and ../install respectively, with the build directory further refined by the project name, which defaults to the current directory name, and the toolchain if that is overridden. &lt;/p&gt;

&lt;p&gt; The build is a Ninja Multi-config build, supporting RelWithDebInfo, Debug, Tsan, and Asan, with the particular flavor being selectable by the CONFIG variable. See &lt;code&gt;targets.mk&lt;/code&gt; for the variables and details, such as they are. &lt;/p&gt;

&lt;p&gt; Because other tools, unfortunately, rely on a &lt;code&gt;compile_commands.json&lt;/code&gt; this system symlinks one from the build area when reconfiguration is done. &lt;/p&gt;

&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-makefile" id="nil"&gt;&lt;span style="color: #f78fe7;"&gt;default&lt;/span&gt;: compile

&lt;span style="color: #f78fe7;"&gt;$(&lt;/span&gt;&lt;span style="color: #f78fe7;"&gt;_build_path&lt;/span&gt;&lt;span style="color: #f78fe7;"&gt;)&lt;/span&gt;:
    mkdir -p $(&lt;span style="color: #79a8ff;"&gt;_build_path&lt;/span&gt;)

&lt;span style="color: #f78fe7;"&gt;$(&lt;/span&gt;&lt;span style="color: #f78fe7;"&gt;_build_path&lt;/span&gt;&lt;span style="color: #f78fe7;"&gt;)/CMakeCache.txt&lt;/span&gt;: | $(&lt;span style="color: #79a8ff;"&gt;_build_path&lt;/span&gt;) .gitmodules
    cd $(&lt;span style="color: #79a8ff;"&gt;_build_path&lt;/span&gt;) &amp;amp;&amp;amp; $(&lt;span style="color: #79a8ff;"&gt;run_cmake&lt;/span&gt;)
    &lt;span style="color: #b6a0ff; font-weight: bold;"&gt;-&lt;/span&gt;rm compile_commands.json
    ln -s $(&lt;span style="color: #79a8ff;"&gt;_build_path&lt;/span&gt;)/compile_commands.json

&lt;span style="color: #f78fe7;"&gt;compile&lt;/span&gt;: $(&lt;span style="color: #79a8ff;"&gt;_build_path&lt;/span&gt;)/CMakeCache.txt &lt;span style="color: #a8a8a8; font-style: italic;"&gt;## &lt;/span&gt;&lt;span style="color: #a8a8a8; font-style: italic;"&gt;Compile the project&lt;/span&gt;
    cmake --build $(&lt;span style="color: #79a8ff;"&gt;_build_path&lt;/span&gt;)  --config $(&lt;span style="color: #79a8ff;"&gt;CONFIG&lt;/span&gt;) --target all -- -k 0

&lt;span style="color: #f78fe7;"&gt;install&lt;/span&gt;: $(&lt;span style="color: #79a8ff;"&gt;_build_path&lt;/span&gt;)/CMakeCache.txt &lt;span style="color: #a8a8a8; font-style: italic;"&gt;## &lt;/span&gt;&lt;span style="color: #a8a8a8; font-style: italic;"&gt;Install the project&lt;/span&gt;
    &lt;span style="color: #79a8ff;"&gt;DESTDIR&lt;/span&gt;=$(&lt;span style="color: #79a8ff;"&gt;abspath&lt;/span&gt; $(&lt;span style="color: #79a8ff;"&gt;DEST&lt;/span&gt;)) ninja -C $(&lt;span style="color: #79a8ff;"&gt;_build_path&lt;/span&gt;) -k 0  install

&lt;span style="color: #f78fe7;"&gt;ctest&lt;/span&gt;: $(&lt;span style="color: #79a8ff;"&gt;_build_path&lt;/span&gt;)/CMakeCache.txt &lt;span style="color: #a8a8a8; font-style: italic;"&gt;## &lt;/span&gt;&lt;span style="color: #a8a8a8; font-style: italic;"&gt;Run CTest on current build&lt;/span&gt;
    cd $(&lt;span style="color: #79a8ff;"&gt;_build_path&lt;/span&gt;) &amp;amp;&amp;amp; ctest

&lt;span style="color: #f78fe7;"&gt;ctest_&lt;/span&gt; : compile
    cd $(&lt;span style="color: #79a8ff;"&gt;_build_path&lt;/span&gt;) &amp;amp;&amp;amp; ctest

&lt;span style="color: #f78fe7;"&gt;test&lt;/span&gt;: ctest_ &lt;span style="color: #a8a8a8; font-style: italic;"&gt;## &lt;/span&gt;&lt;span style="color: #a8a8a8; font-style: italic;"&gt;Rebuild and run tests&lt;/span&gt;

&lt;span style="color: #f78fe7;"&gt;cmake&lt;/span&gt;: |  $(&lt;span style="color: #79a8ff;"&gt;_build_path&lt;/span&gt;)
    cd $(&lt;span style="color: #79a8ff;"&gt;_build_path&lt;/span&gt;) &amp;amp;&amp;amp; ${&lt;span style="color: #79a8ff;"&gt;run_cmake&lt;/span&gt;}

&lt;span style="color: #f78fe7;"&gt;clean&lt;/span&gt;: $(&lt;span style="color: #79a8ff;"&gt;_build_path&lt;/span&gt;)/CMakeCache.txt &lt;span style="color: #a8a8a8; font-style: italic;"&gt;## &lt;/span&gt;&lt;span style="color: #a8a8a8; font-style: italic;"&gt;Clean the build artifacts&lt;/span&gt;
    cmake --build $(&lt;span style="color: #79a8ff;"&gt;_build_path&lt;/span&gt;)  --config $(&lt;span style="color: #79a8ff;"&gt;CONFIG&lt;/span&gt;) --target clean

&lt;span style="color: #f78fe7;"&gt;realclean&lt;/span&gt;: &lt;span style="color: #a8a8a8; font-style: italic;"&gt;## &lt;/span&gt;&lt;span style="color: #a8a8a8; font-style: italic;"&gt;Delete the build directory&lt;/span&gt;
    rm -rf $(&lt;span style="color: #79a8ff;"&gt;_build_path&lt;/span&gt;)

&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id="outline-container-orgd013026" class="outline-2"&gt;
&lt;h3 id="orgd013026"&gt;To Docker or Not to Docker&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-orgd013026"&gt;
&lt;p&gt; The reason for the separate &lt;code&gt;targets.mk&lt;/code&gt; file is to simplify running the build purely locally in the host, or in a docker containter. The structure of the build is the same either way. In fact, before I dockerized this template project, there was a single makefile which was mostly the current contents of targets.mk. However, splitting does make the template easier, as project specific targets can naturally be placed in &lt;code&gt;targets&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt; Tha outer &lt;code&gt;Makefile&lt;/code&gt; is responsible for checking if Docker has been requested and for making sure the container is ready. The makefile has a handful of targets of its own, but otherwide defers everything to &lt;code&gt;targets.mk&lt;/code&gt;. &lt;/p&gt;

&lt;dl class="org-dl"&gt;
&lt;dt&gt;use-docker&lt;/dt&gt;&lt;dd&gt;set a flag file, USE_DOCKER_FILE, indicating to forward to docker&lt;/dd&gt;
&lt;dt&gt;remove-docker&lt;/dt&gt;&lt;dd&gt;remove the flag file&lt;/dd&gt;
&lt;dt&gt;docker-rebuild&lt;/dt&gt;&lt;dd&gt;rebuild the docker image&lt;/dd&gt;
&lt;dt&gt;docker-clean&lt;/dt&gt;&lt;dd&gt;Clean volumes and rebuild image&lt;/dd&gt;
&lt;dt&gt;docker-shell&lt;/dt&gt;&lt;dd&gt;Shell in the docker container&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt; The docker container is build via &lt;code&gt;docker-compose&lt;/code&gt; with the configuration &lt;code&gt;docker-compose.yml&lt;/code&gt;. It uses the &lt;code&gt;Dockerfile&lt;/code&gt; which uses &lt;code&gt;steve-downey/cxx-dev:latest&lt;/code&gt; as the base image, and mounts the current source directory as a bind mount and a volume for ../cmake.bld. &lt;/p&gt;

&lt;p&gt; I don't publish steve-downey/cxx-dev:latest and you should build your own BASE. I do provide the recipe for the base image as a subprojct in &lt;code&gt;docker-inf/docker-cxx-dev&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt; You running unknown things as root scares me. &lt;/p&gt;

&lt;p&gt; The image is assumed to provide current version of gcc and clang as c++ or gcc, or clang++ respectively. &lt;/p&gt;

&lt;p&gt; The intent of the image is to provide compilation services and operate as an lsp server using clangd. Mine doesn't provide X, editors, IDEs, etc. The intent isn't a VM, it's a controlled compiler installation. &lt;/p&gt;

&lt;p&gt; Compiler installations bleed in to each other. Mutliple compilers installed onto the same base system can't be assumed to behave the same way as a compier installed as the only compiler. The ABI libraries vary, as do the standard libaries. Deployment just makes this all an even worse problem. As a Rule I use for production Red Hat's DTS compilers and only deploy on later OSs than I've built on, with strict controls on OS deployments and statically linking everything I possibly can. &lt;/p&gt;

&lt;p&gt; The base image I am using here, steve-downey/cxx-dev, works for me, and is avaiable at &lt;a href="https://github.com/steve-downey/docker-cxx-dev"&gt;https://github.com/steve-downey/docker-cxx-dev&lt;/a&gt; as a definition as well. &lt;/p&gt;

&lt;p&gt; It is based on current Ubuntu (jammy), installs gcc-12 from the ubuntu repositories, adds the LLVM repos and installs clang-14 from them based on how &lt;a href="https://apt.llvm.org/llvm.sh"&gt;https://apt.llvm.org/llvm.sh&lt;/a&gt; does. &lt;/p&gt;

&lt;p&gt; It then installs the current release of cmake from &lt;a href="https://apt.kitware.com/ubuntu/"&gt;https://apt.kitware.com/ubuntu/&lt;/a&gt; because using out of date build tools is a bad idea all around. &lt;/p&gt;

&lt;p&gt; I also configure it to run as USER 1000, because running everything as root is strictly worse, and 1000 is a 99.99 percent solution/ &lt;/p&gt;

&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-makefile" id="nil"&gt;&lt;span style="color: #f78fe7;"&gt;.update-submodules&lt;/span&gt;:
    git submodule update --init --recursive
    touch .update-submodules

&lt;span style="color: #f78fe7;"&gt;.gitmodules&lt;/span&gt;: .update-submodules

&lt;span style="color: #f78fe7;"&gt;.PHONY&lt;/span&gt;: use-docker
&lt;span style="color: #f78fe7;"&gt;use-docker&lt;/span&gt;: &lt;span style="color: #a8a8a8; font-style: italic;"&gt;## &lt;/span&gt;&lt;span style="color: #a8a8a8; font-style: italic;"&gt;Create docker switch file so that subsequent `make` commands run inside docker container.&lt;/span&gt;
    touch $(&lt;span style="color: #79a8ff;"&gt;USE_DOCKER_FILE&lt;/span&gt;)

&lt;span style="color: #f78fe7;"&gt;.PHONY&lt;/span&gt;: remove-docker
&lt;span style="color: #f78fe7;"&gt;remove-docker&lt;/span&gt;: &lt;span style="color: #a8a8a8; font-style: italic;"&gt;## &lt;/span&gt;&lt;span style="color: #a8a8a8; font-style: italic;"&gt;Remove docker switch file so that subsequent `make` commands run locally.&lt;/span&gt;
    $(&lt;span style="color: #79a8ff;"&gt;RM&lt;/span&gt;) $(&lt;span style="color: #79a8ff;"&gt;USE_DOCKER_FILE&lt;/span&gt;)

&lt;span style="color: #f78fe7;"&gt;.PHONY&lt;/span&gt;: docker-rebuild
&lt;span style="color: #f78fe7;"&gt;docker-rebuild&lt;/span&gt;: &lt;span style="color: #a8a8a8; font-style: italic;"&gt;## &lt;/span&gt;&lt;span style="color: #a8a8a8; font-style: italic;"&gt;Rebuilds the docker file using the latest base image.&lt;/span&gt;
    docker-compose build

&lt;span style="color: #f78fe7;"&gt;.PHONY&lt;/span&gt;: docker-clean
&lt;span style="color: #f78fe7;"&gt;docker-clean&lt;/span&gt;: &lt;span style="color: #a8a8a8; font-style: italic;"&gt;## &lt;/span&gt;&lt;span style="color: #a8a8a8; font-style: italic;"&gt;Clean up the docker volumes and rebuilds the image from scratch.&lt;/span&gt;
    docker-compose down -v
    docker-compose build

&lt;span style="color: #f78fe7;"&gt;.PHONY&lt;/span&gt;: docker-shell
&lt;span style="color: #f78fe7;"&gt;docker-shell&lt;/span&gt;: &lt;span style="color: #a8a8a8; font-style: italic;"&gt;## &lt;/span&gt;&lt;span style="color: #a8a8a8; font-style: italic;"&gt;Shell in container&lt;/span&gt;
    docker-compose run --rm dev

&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id="outline-container-orgcca1c34" class="outline-2"&gt;
&lt;h3 id="orgcca1c34"&gt;Work In Progress&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-orgcca1c34"&gt;
&lt;p&gt; I expect I will make many changes to all of this. I'm providing no facilities for you to pick them up. Sorry. &lt;/p&gt;

&lt;p&gt; Please consider this as an exhibition of techniques rather than as a solution. &lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description><guid>https://sdowney.org/posts/index.php/2021/10/03/a-local-cmake-workflow-with-docker/</guid><pubDate>Sun, 03 Oct 2021 04:00:00 GMT</pubDate></item><item><title>std::execution, Sender/Receiver, and the Continuation Monad</title><link>https://sdowney.org/posts/index.php/2021/10/03/stdexecution-sender-receiver-and-the-continuation-monad/</link><dc:creator>Steve Downey</dc:creator><description>&lt;p&gt; Some thoughts on the &lt;a href="https://wg21.link/p2300"&gt;std::execution&lt;/a&gt; proposal and my understanding of the underlying theory. &lt;/p&gt;

&lt;div id="outline-container-org6280fb4" class="outline-2"&gt;
&lt;h3 id="org6280fb4"&gt;What's proposed&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org6280fb4"&gt;
&lt;p&gt; From the paper's &lt;a href="https://brycelelbach.github.io/wg21_p2300_std_execution/std_execution.html#intro"&gt;Introduction&lt;/a&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt; This paper proposes a self-contained design for a Standard C++ framework for managing asynchronous execution on generic execution contexts. It is based on the ideas in [P0443R14] and its companion papers. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt; Which doesn't tell you much. &lt;/p&gt;

&lt;p&gt; It proposes a framework where the principle abstractions are Senders, Receivers, and Schedulers. &lt;/p&gt;

&lt;dl class="org-dl"&gt;
&lt;dt&gt;Sender&lt;/dt&gt;&lt;dd&gt;A composable unit of work.&lt;/dd&gt;
&lt;dt&gt;Receiver&lt;/dt&gt;&lt;dd&gt;Delimits work, handling completion, exceptions, or cancellation.&lt;/dd&gt;
&lt;dt&gt;Schedulers&lt;/dt&gt;&lt;dd&gt;Arranges for the context work is done in.&lt;/dd&gt;
&lt;/dl&gt;

&lt;!-- TEASER_END --&gt;

&lt;p&gt; The primary user facing concept is the sender. Values and functions can be lifted directly into senders. Senders can be stacked together, with a sender passing its value on to another function. Or stacking exception or cancellation handling the same way. &lt;/p&gt;

&lt;p&gt; Receivers handle the three ways a sender can complete, by returning a value, throwing an exception, or being canceled. As described, receivers are most likely to be implemented within particular algorithms that combine senders, such as &lt;a href="https://brycelelbach.github.io/wg21_p2300_std_execution/std_execution.html#example-then"&gt;`then`&lt;/a&gt; or &lt;a href="https://brycelelbach.github.io/wg21_p2300_std_execution/std_execution.html#example-retry"&gt;`retry`&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt; Schedulers provide access to execution contexts. Like inline, single thread, a thread pool, a GPU, and so on, would all have schedulers that provide for putting a sender into the context they manage. &lt;/p&gt;

&lt;p&gt; There's a fairly large API surface being proposed. But there's an underlying theory about this, governing what algorithms need to be there and how the pieces fit together. &lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id="outline-container-org8699f4f" class="outline-2"&gt;
&lt;h3 id="org8699f4f"&gt;Continuation Passing Style and the Continuation Monad&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org8699f4f"&gt;
&lt;p&gt; Continuation passing style is a transformation from a normal function and a call stack to a direction to send the result to the "continuation" without returning. This means the functions context can be cleaned up. Delimited continuations are a slight variation, where instead of an unbounded "rest of the program", the continuation has an end point and a value. It's essentially a function, and can be handled as such. There is a purely mechanical method for converting all of the lambda calculus transforms into CPS form, and this can be profitable for compilers based on lambda, or related logics, like system F. &lt;/p&gt;

&lt;p&gt; The mechanical transformation also means that all the control structures, like loops, gotos, coroutines, exceptions, have CPS equivalents. &lt;/p&gt;

&lt;p&gt; CPS is tedious, though. Having to explicitly add a continuation to everything is complicated. &lt;/p&gt;

&lt;p&gt; However, there's also a typeclass, or concept, that allows you to convert regular functions into continuation passing style, automatically. It's then rather straightforward to involve concerns like where work is being run for something that wraps up the entire work. Even being able to switch back and forth between contexts. That's the continuation monad. &lt;/p&gt;

&lt;p&gt; And unfortunately monads became an organizing principle in programming language theory one or two decades after most CS programs were standardized. So it's all complicated and involves things we weren't trained on. Fitting it into C++ has been an ongoing challenge, and until we had generic lambda was neither reasonbly concise nor idiomatic. &lt;/p&gt;

&lt;p&gt; See, however, the new monadic interface additions for std::optional for why you want this. Or Ranges, which are solidly based in the 'list' or non-deterministic monad. &lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id="outline-container-org32f30b7" class="outline-2"&gt;
&lt;h3 id="org32f30b7"&gt;We have a poor relationship with Theory&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org32f30b7"&gt;
&lt;p&gt; There is no satisfactory PL theory for object oriented programming. There's lots of work, but it mostly ends up describing something that OO programmers don't think is quite the same as what they do. Even the ones who spend a lot of time doing theory. &lt;/p&gt;

&lt;p&gt; Yet OO was, and is, a successful discipline. Working with identity, behavior, and state has produced remarkable results. Temporal calculi, not so much. &lt;/p&gt;

&lt;p&gt; For a long while, we as a discipline thought that multi-threading was similar. There was poor theory, but we had hardware, and libraries that let us use that hardware to do concurrent work correctly. &lt;/p&gt;

&lt;p&gt; That turned out not to be the case. &lt;/p&gt;

&lt;p&gt; Concurrency can't be just a library, unfortunately. Concurrency models that hardware vendors will commit to won't promise not to violate causality. That makes producing a programming model programmers can use frighteningly difficult. &lt;/p&gt;

&lt;p&gt; Which is why having a sound theory for std::execution is a good thing, even if the theory is unfamiliar. &lt;/p&gt;

&lt;p&gt; But as a group, we learned the wrong lessons from the 80s and thought it was a researcher's job to take the successes of practitioners and put a sound basis to them. Ignoring that it is a feedback loop. In the 60s and 70s, those researchers were also the practitioners. It's not wrong to get out ahead of theory, but we do need to check back. &lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id="outline-container-org4d78be1" class="outline-2"&gt;
&lt;h3 id="org4d78be1"&gt;p2300 std::execution&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org4d78be1"&gt;
&lt;p&gt; Senders, via the Decorator pattern, lift ordinary functions into the continuation passing style. People writing functions only need to be concerned with handling the arguments they are passed, without concern for execution context or continuations. Functions used by senders act like, and are, normal functions. &lt;/p&gt;

&lt;p&gt; Senders manage a bundle of channels, representing normal return of a value, throwing an exception, or an error channel to handle cancellation, or other errors not within the bound of ordinary functions. All of these channels can be composed taking the result to another function, or monadically with a function returning a sender, where that function can determine the kind of sender based on the values of the arguments. The channels can be combined or rerouted, connecting one to another, or presenting a variant containing either result, exception, and/or error to the continuation function. &lt;/p&gt;

&lt;p&gt; Although senders form a logical graph of units of work, the physical type model is containment, much like expression templates. The result of binding senders together via an algorithm is a sender that contains the bound together senders. There are no nodes or allocations inherent to the model, just function calls. &lt;/p&gt;

&lt;p&gt; C++ coroutines fit into this model. C++ coroutines are, from the outside, functions with rules about the interaction patterns with the returned value. Making a coroutine owning type a sender, and a sender co_awaitable, is possible and has been demonstrated. &lt;/p&gt;

&lt;p&gt; std::execution takes the Continuation Monad and fits it to C++ control flow, return or exception, and adds cancellation, which incidentally allows a channel for failures from execution contexts. The thread pool can potentially signal failure via the error channel, without aliasing problems from application function code. However, for advanced users, these can be folded back into the normal function arguments and handled by application code. Policy decisions are not burned into the ROM of std::execution, but there are defaults that can be provided by application infrastructure authors. &lt;/p&gt;

&lt;p&gt; Those infrastructure authors do not have to be std library vendors. The protocols, rendered as concepts, are available to normal users. &lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id="outline-container-org2dd1cec" class="outline-2"&gt;
&lt;h3 id="org2dd1cec"&gt;Network TS&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org2dd1cec"&gt;
&lt;dl class="org-dl"&gt;
&lt;dt&gt;&lt;span class="underline"&gt;Eppur si muove&lt;/span&gt;&lt;/dt&gt;&lt;dd&gt;And yet it moves&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt; I do not believe ASIO's model is a firm foundation for all async programming. However, it is well proven, and exists. It works. &lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;div id="outline-container-org5f111d1" class="outline-2"&gt;
&lt;h3 id="org5f111d1"&gt;And …&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org5f111d1"&gt;
&lt;p&gt; I have confidence that a networking library can and will be built using p2300. I am less confident that can be done in the timeframe for C++26. I do not believe for a moment we could have one for C++23, even with an existence proof a networking library appearing now. It's simply too late to review and agree. We're in the same place as coroutines. We can have the machinery, but without all of the application user facing infrastructure we should have. &lt;/p&gt;

&lt;p&gt; I think this was the right choice with coroutines, and I think providing the machinery for general continuation based async in the standard library so that we can build on top of it is the right choice. The authors have committed to making sure all the facilities are available for programmers, in particular the pipe syntax (an issue for ranges) as well as providing bases or adapters for coroutine promises and typed senders. We can experiment and add existing practice as we go. &lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;div id="outline-container-orgb7e8b70" class="outline-2"&gt;
&lt;h3 id="orgb7e8b70"&gt;Disclaimer&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-orgb7e8b70"&gt;
&lt;p&gt; This is &lt;b&gt;all&lt;/b&gt; my personal opinion, based on my own understanding. I've been in the meetings, I've been in discussions, asked questions. But if I'm wrong about some aspect of the proposal, that's on me. Certainly not a formal opinion of Bloomberg, where I work. While we do lots of network services, and async programming, this isn't what our tech looks like at all. Getting from here to there is an open question, but it would be for ASIO, too. &lt;/p&gt;

&lt;p&gt; At least it isn't CORBA. &lt;/p&gt;

&lt;p&gt; &lt;a href="https://github.com/steve-downey/what-comes-to-mind/blob/master/send-rec.org"&gt;Source For Blog&lt;/a&gt; &lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description><guid>https://sdowney.org/posts/index.php/2021/10/03/stdexecution-sender-receiver-and-the-continuation-monad/</guid><pubDate>Sun, 03 Oct 2021 04:00:00 GMT</pubDate></item><item><title>Standard Vocabulary for Algorithms</title><link>https://sdowney.org/posts/index.php/2021/01/16/standard-vocabulary-for-algorithms/</link><dc:creator>Steve Downey</dc:creator><description>&lt;p&gt;This is feedback after considering &lt;a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2214r0.html"&gt;A Plan for C++23 Ranges&lt;/a&gt;

Disclosure: I voted in favor of this. It does &lt;b&gt;not&lt;/b&gt; suggest work on &lt;a href="https://wg21.link/P1255"&gt;views::maybe [P1255R6]​&lt;/a&gt;. I'm fine with that priority.
&lt;/p&gt;&lt;div id="outline-container-orga27da53" class="outline-2"&gt;
&lt;h3 id="orga27da53"&gt;Vocabulary is not just Types between Components&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-orga27da53"&gt;

 There's broad agreement that 'vocabulary types' belong in the standard. Domain independent types that can be used between otherwise uncoupled facilities. They each depend on facilities provided by Standard C++ and can thus be developed independently. Each component can rely on the API of a core vocabulary type not changing. This allows facilities to communicate effectively.

A component can have std::string or std::vector&amp;lt;int&amp;gt; in its interface with little concern. The STL parts of the standard library have always relied on concepts for constraining template parameters implicitly, requiring an Iterator of particular category in places, or specializing algorithms based on such. Composition of container types has also been natural. No one is confused by a std::unordered_map&amp;lt;std::string, std::vector&amp;lt;my::person&amp;gt;&amp;gt;.

&lt;!-- TEASER_END --&gt;

The new C++20 range facilities allow composition of algorithms, which means that the names of algorithms will, and must, become part of the vocabulary of C++ programmers. Algorithms, and the names for them, are far broader than the linear containers supported by C++ today. It is a particular problem because C++ has named core algorithms badly, as they were not, until recently, first class entities.

&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org1dee97c" class="outline-2"&gt;
&lt;h3 id="org1dee97c"&gt;Algorithms are now first class entities&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org1dee97c"&gt;

 Functions are a terribly overloaded term in C++. Overloaded is an overloaded term.

With respect to ranges and views, however, it should be clear that the adaptors, transformers, and other entities we apply to ranges and views to produce new ranges, views, and values, are now first class entities in their own right.

The important thing, for programmers, is that moving up the ladder of abstraction should not be conceptually more difficult than dealing with existing libraries of functions. We have algorithms that deal with generic types rather than functions that deal with concrete types, but keeping them in mind should not be fundamentally more difficult.

Naming is therefore critical.

As are chosing the algorithms that are primitive, that is, the ones that compose into others in useful ways.

I have some concerns about providing fused algorithms that a sufficiently smart compiler could optimize. On the other hand, I doubt how imminent sufficiently smart compilers are.

&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org116280c" class="outline-2"&gt;
&lt;h3 id="org116280c"&gt;Why Haskell keeps coming up&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org116280c"&gt;

 Python was the answer to "Why can't I just write pseudo-code?"

I have text books where the authors seriously discussed writing out your algorithm into pseudo code, and then translating it into actual programming language. Programming languages were too high ceremony to discuss what you wanted to do, while normal English was not structured enough. "Scripting" languages gave precise higher level semantics that were implicit in the pseudo code, or it would have been impossible to translate by hand to other computer languages.

Haskell was designed to do that for algorithm research. The primary goal was to be able to give direct executable form to a research paper. This was early replicable research. The paper provided, on its own, the mechanism to test and reproduce the result. Haskell source code can be embedded in LaTeX and given directly to a Haskell compiler. Every interesting algorithms paper for the last 30 years or so has implicitly included the prelude.

Haskell itself is not a terribly complex language. Much of it is specified as sugar where a form is translated into a more primitive expression, as range for loops are in C++. Its power for researchers is in its inherent laziness, that an expression is not evaluated unless it is required, and its purity, that values are immutable. These properties make it straightforward to reason with and about. The core property of lazy evaluation has forced it to be pure, not allowing side-effects. This has forced it to be exemplary, and evolutionary, in supporting value oriented programming.

These factors are why we end up often looking to Haskell.

Value oriented programming has been an emerging style in modern C++. The new Range facilities embody the style. Being able to crib proveably correct facilities from modern programming language research is a benefit.

There was a long period, in which C++ grew up, that academic research lagged behind the pragmatic craft of programming. This has, in retrospect, not been an unqualified success. Parallelism and concurrency were widely implemented without theoretic underpnnings. We are still trying to put C++'s memory model on firm footing. Many constructs regularly used in the past are now understood to be unsound, in explicable ways. Multi-threading should not be an experimental science.

Object orientation is an area which still does not have satisfying theoretic backing. There are various theories that provide many of the same benefits, allowing abstraction and encapsulation. In OO, however, objects have identity and state, which implies that equational reasoning can fail, as two equivalent object may have distinct identity and then different behavior. Temporal calculus formalisms are still open research.

The manifest success of OO{A,D,P} with limited underlying theory has allowed many practitioners to believe that academic research is irrelevant. To the extent of dismissing rigor. Jokes about the "M-word" are emblematic.

&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org37a9e88" class="outline-2"&gt;
&lt;h3 id="org37a9e88"&gt;Sidebar: Monads are boring&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org37a9e88"&gt;

 A monad is a generic type with a few operations, some of which can be expressed in terms of the others, that follow a few fundamental and fairly trivial rules. They allow predictable composition of entities that model monad.

It is not about `then`. Although `then` does tend to fall out.

The interesting thing is that algorithms can be built that take generic types that follow some "Laws", and they will do, something, correctly. For some kinds of generic type, what happens may be surprising, even interesting. The surprises will, however, not break anything. That's the point of the semantic guarantees surrounding the operations.

C++ has philosophically adopted semantics surrounding Concepts. A Concept is entitled to demand behavior and laws in addition to the checkable syntax that can be enforced.

The utility for an algorithm writer is that reasoning can be applied at a much higher level. Even beyond the abstraction that this is a Container, or Range, or View, being able reason about the operations for anything that provides a set of well defined operations means that the algorithm is correct, even if the details when applied to a new kind are obscure.

Iterators provide a way for algorithms to work with many containers. Those same, correct, algorithms should be able to work with things that aren't Iterable, or Containers. It turns out having a named way of converting a Type&amp;lt;Type&amp;lt;Value&amp;gt;&amp;gt; to a Type&amp;lt;Value&amp;gt; opens up many algorithms to broader use. Flattening a vector of vectors into a linear vector is not the only use of a `concat`.

&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org6725794" class="outline-2"&gt;
&lt;h3 id="org6725794"&gt;Fold: In Which I Become Cranky About Names&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org6725794"&gt;

 One of the most primitive and yet powerful algorithms is `fold`. Fold takes a binary operation and interposes it between elements in an iterable data type. It replaces the commas {a, b, c, d, …} with `op`, resulting in {a op b op c op d … }

Except that is slightly ambiguous. Is that (a op (b op (c op (d)))) or ((((a) op b) op c) op d)

Right or left evaluation of the terms.

Folding right is strictly more general, at least in the lambda calculus. Left fold can be implemented as a right fold, but not vice-versa.

However, in C++, the normal implementation of folds is not as general as it might be, because C++ is strict in evaluating function arguments. This means that even though a fold whose operation might not need to evaluate one of its arguments in order to return a value, will still do so, because the argument is evaluated before being passed to the operation. This mean, in particular, that we can't simply undo fold by using a `cons` operation, reconstructing the list. The entire, indeterminate and possibly infinite, list must be evaluated even though all that is necesary is the first element.

Left folding is tail recursive, and so can be converted to a loop. This is why it seems natural in C++.
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-C++" id="nil"&gt;&lt;span class="org-type"&gt;T&lt;/span&gt; &lt;span class="org-function-name"&gt;fold_left&lt;/span&gt;(&lt;span class="org-type"&gt;Range&lt;/span&gt;&amp;amp;&amp;amp; &lt;span class="org-variable-name"&gt;r&lt;/span&gt;, &lt;span class="org-type"&gt;T&lt;/span&gt; &lt;span class="org-variable-name"&gt;init&lt;/span&gt;, &lt;span class="org-type"&gt;BinaryOperation&lt;/span&gt; &lt;span class="org-variable-name"&gt;op&lt;/span&gt;) {
    &lt;span class="org-type"&gt;range_iterator_t&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;Range&lt;/span&gt;&amp;gt; &lt;span class="org-variable-name"&gt;b&lt;/span&gt; = begin(r);
    &lt;span class="org-type"&gt;range_sentinel_t&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;Range&lt;/span&gt;&amp;gt; &lt;span class="org-variable-name"&gt;e&lt;/span&gt; = end(r);
    &lt;span class="org-keyword"&gt;for&lt;/span&gt; (; b != e; ++b) {
        init = op(&lt;span class="org-constant"&gt;std&lt;/span&gt;::move(init), *b);
    }
    &lt;span class="org-keyword"&gt;return&lt;/span&gt; init;
&lt;/pre&gt;
&lt;/div&gt;
Right fold is not generally tail recursive, although for finite sequences in C++, using reverse iterators, foldr is also a loop.
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-C++" id="nil"&gt;&lt;span class="org-keyword"&gt;auto&lt;/span&gt; &lt;span class="org-function-name"&gt;fold_right_loop&lt;/span&gt;(&lt;span class="org-type"&gt;Range&lt;/span&gt;&amp;amp;&amp;amp; &lt;span class="org-variable-name"&gt;r&lt;/span&gt;, &lt;span class="org-type"&gt;T&lt;/span&gt; &lt;span class="org-variable-name"&gt;init&lt;/span&gt;, &lt;span class="org-type"&gt;BinaryOperation&lt;/span&gt; &lt;span class="org-variable-name"&gt;op&lt;/span&gt;) -&amp;gt; &lt;span class="org-type"&gt;result_of&lt;/span&gt;&amp;lt;&amp;gt;{
    &lt;span class="org-type"&gt;range_iterator_t&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;Range&lt;/span&gt;&amp;gt; &lt;span class="org-variable-name"&gt;b&lt;/span&gt; = begin(r);
    &lt;span class="org-type"&gt;range_sentinel_t&lt;/span&gt;&amp;lt;&lt;span class="org-type"&gt;Range&lt;/span&gt;&amp;gt; &lt;span class="org-variable-name"&gt;e&lt;/span&gt; = end(r);
    &lt;span class="org-keyword"&gt;for&lt;/span&gt; (; b != e; ++b) {
        init = op(&lt;span class="org-constant"&gt;std&lt;/span&gt;::move(init), *b);
    }
    &lt;span class="org-keyword"&gt;return&lt;/span&gt; init;
&lt;/pre&gt;
&lt;/div&gt;
To make the diagrams below pretty, we assume that foldl over a sequence of T takes a single value of type Z and an op of Z -&amp;gt; T -&amp;gt; Z, while foldr over a sequence of T takes an op of type T -&amp;gt; Z -&amp;gt; Z and a value of type Z. For a left fold, the value is given to the op that takes the first element in the sequence, while for a right fold, it is given to the op that takes the last element in the sequence.
&lt;div id="org00eb67f" class="figure"&gt;

&lt;img src="http://sdowney.org/wp-content/uploads/2021/01/list.png" alt="list.png"&gt;

&lt;/div&gt;
&lt;div id="org5f93c72" class="figure"&gt;

&lt;img src="http://sdowney.org/wp-content/uploads/2021/01/left-fold.png" alt="left-fold.png"&gt;

&lt;/div&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;result = op(op(op(op(op(op(op(op(z, a), b), c), d), e), f), g), h);
&lt;/pre&gt;
&lt;/div&gt;
&lt;div id="orge028fbf" class="figure"&gt;

&lt;img src="http://sdowney.org/wp-content/uploads/2021/01/right-fold.png" alt="right-fold.png"&gt;

&lt;/div&gt;
&lt;div class="org-src-container"&gt;
&lt;label class="org-src-name"&gt;&lt;em&gt;&lt;/em&gt;&lt;/label&gt;
&lt;pre class="src src-c++" id="nil"&gt;result = op(a, op(b, op(c, op(d, op(e, op(f, op(g, op(h, z))))))));
&lt;/pre&gt;
&lt;/div&gt;
So, left fold piles up the ops on the left and right fold piles them up on the right. The 'zero' or init value is with the last value for a right fold, and the first on a left fold. In converting to iteration, which is important, left fold is in the natural direction, and right fold is reversed, which means it can't be used that way on some sequences.

So which one should be &lt;b&gt;the&lt;/b&gt; &lt;code&gt;fold&lt;/code&gt;. It's an important question because short names are implicitly privileged. Programmers assume that the short name is the best one, and longer names indicate more specialized usage. This isn't true for C++, but not really on purpose. We did think that `map` was a good choice. The programmers should probably reach for `unordered_map` instead is unfortunate, but at this point unfixable.

Since C++ is strict, it would seem that left fold is the fold you mostly want, so it would be OK to call it &lt;code&gt;fold&lt;/code&gt;.

Haskell, as lazy as it is, has issues with folds on ranges with indeterminate bounds. &lt;code&gt;foldl&lt;/code&gt; vs &lt;code&gt;foldr&lt;/code&gt; vs &lt;code&gt;foldl'&lt;/code&gt; is a constant question. &lt;a href="https://wiki.haskell.org/Foldr_Foldl_Foldl'"&gt;Foldr Foldl Foldl'&lt;/a&gt; Memory consumption of either stack or unevaluated expressions will surprise programmers.

But in the literature, fold is right fold. In the pure lambda calculus, right fold is strictly more expressive. Tail recursion is a subset of primitive recursion, and left is tail recursive while right is not. If we call our left fold, &lt;code&gt;fold&lt;/code&gt;, we will confuse people.

Further, the forward iteration is somewhat balanced by the fact that the normal addition to a sequence is &lt;code&gt;emplace_back&lt;/code&gt; or &lt;code&gt;push_back&lt;/code&gt;, which means that left fold will tend to reverse lists if the operation is accumulation into a sequence, if for example the op were &lt;code&gt;[](auto t){v.emplace_back(t);}&lt;/code&gt;.

More, we have started to introduce lazy features into the language, with coroutines. Although we won't get them soon, the C++ standard library should eventually have good lazy algorithms. It would be unfortunate if we have to teach that you can't use &lt;code&gt;co_fold&lt;/code&gt; in place of &lt;code&gt;fold&lt;/code&gt; because they are opposite, or that &lt;code&gt;co_fold_left&lt;/code&gt; is how you spell the coroutine &lt;code&gt;fold&lt;/code&gt;. [Note co_ prefixes are mildly sarcastic.]

C++ has a long history of setting defaults and realizing later that they are a problem.

I would much prefer we not make a choice about which &lt;code&gt;fold&lt;/code&gt; is the fold, and just spell them as &lt;code&gt;fold_left&lt;/code&gt; and &lt;code&gt;fold_right&lt;/code&gt;.

We should all be able to get behind not calling it &lt;code&gt;accumulate&lt;/code&gt;, even if we must live with &lt;code&gt;transform&lt;/code&gt;.

&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org7f754e7" class="outline-2"&gt;
&lt;h3 id="org7f754e7"&gt;Monoid&lt;/h3&gt;
&lt;div class="outline-text-2" id="text-org7f754e7"&gt;

 Some other time I'll vent about the various &lt;code&gt;fold&lt;/code&gt; operations and how they get extended if your type is a monoid. See Chris Di Bella's work such as &lt;a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1813r0.pdf"&gt;A Concept Design for the Numeric Algorithms&lt;/a&gt;, although this rant suggests that algorithms that operate on different Concepts should have different names. Overloading on concepts with semantic differences can be confusing.

&lt;/div&gt;
&lt;/div&gt;</description><guid>https://sdowney.org/posts/index.php/2021/01/16/standard-vocabulary-for-algorithms/</guid><pubDate>Sat, 16 Jan 2021 23:22:19 GMT</pubDate></item></channel></rss>