<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang xml:lang>
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="mpark/wg21" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <meta name="dcterms.date" content="2024-11-21" />
  <title>A Utility for Creating Execution Environments</title>
  <style>
      code{white-space: pre-wrap;}
      span.smallcaps{font-variant: small-caps;}
      span.underline{text-decoration: underline;}
      div.column{display: inline-block; vertical-align: top; width: 50%;}
      div.csl-block{margin-left: 1.5em;}
      ul.task-list{list-style: none;}
      pre > code.sourceCode { white-space: pre; position: relative; }
      pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
      pre > code.sourceCode > span:empty { height: 1.2em; }
      .sourceCode { overflow: visible; }
      code.sourceCode > span { color: inherit; text-decoration: inherit; }
      div.sourceCode { margin: 1em 0; }
      pre.sourceCode { margin: 0; }
      @media screen {
      div.sourceCode { overflow: auto; }
      }
      @media print {
      pre > code.sourceCode { white-space: pre-wrap; }
      pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
      }
      pre.numberSource code
        { counter-reset: source-line 0; }
      pre.numberSource code > span
        { position: relative; left: -4em; counter-increment: source-line; }
      pre.numberSource code > span > a:first-child::before
        { content: counter(source-line);
          position: relative; left: -1em; text-align: right; vertical-align: baseline;
          border: none; display: inline-block;
          -webkit-touch-callout: none; -webkit-user-select: none;
          -khtml-user-select: none; -moz-user-select: none;
          -ms-user-select: none; user-select: none;
          padding: 0 4px; width: 4em;
          color: #aaaaaa;
        }
      pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
      div.sourceCode
        {  background-color: #f6f8fa; }
      @media screen {
      pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
      }
      code span { } /* Normal */
      code span.al { color: #ff0000; } /* Alert */
      code span.an { } /* Annotation */
      code span.at { } /* Attribute */
      code span.bn { color: #9f6807; } /* BaseN */
      code span.bu { color: #9f6807; } /* BuiltIn */
      code span.cf { color: #00607c; } /* ControlFlow */
      code span.ch { color: #9f6807; } /* Char */
      code span.cn { } /* Constant */
      code span.co { color: #008000; font-style: italic; } /* Comment */
      code span.cv { color: #008000; font-style: italic; } /* CommentVar */
      code span.do { color: #008000; } /* Documentation */
      code span.dt { color: #00607c; } /* DataType */
      code span.dv { color: #9f6807; } /* DecVal */
      code span.er { color: #ff0000; font-weight: bold; } /* Error */
      code span.ex { } /* Extension */
      code span.fl { color: #9f6807; } /* Float */
      code span.fu { } /* Function */
      code span.im { } /* Import */
      code span.in { color: #008000; } /* Information */
      code span.kw { color: #00607c; } /* Keyword */
      code span.op { color: #af1915; } /* Operator */
      code span.ot { } /* Other */
      code span.pp { color: #6f4e37; } /* Preprocessor */
      code span.re { } /* RegionMarker */
      code span.sc { color: #9f6807; } /* SpecialChar */
      code span.ss { color: #9f6807; } /* SpecialString */
      code span.st { color: #9f6807; } /* String */
      code span.va { } /* Variable */
      code span.vs { color: #9f6807; } /* VerbatimString */
      code span.wa { color: #008000; font-weight: bold; } /* Warning */
      code.diff {color: #898887}
      code.diff span.va {color: #006e28}
      code.diff span.st {color: #bf0303}
  </style>
  <style type="text/css">
body {
margin: 5em;
font-family: serif;

hyphens: auto;
line-height: 1.35;
text-align: justify;
}
@media screen and (max-width: 30em) {
body {
margin: 1.5em;
}
}
div.wrapper {
max-width: 60em;
margin: auto;
}
ul {
list-style-type: none;
padding-left: 2em;
margin-top: -0.2em;
margin-bottom: -0.2em;
}
a {
text-decoration: none;
color: #4183C4;
}
a.hidden_link {
text-decoration: none;
color: inherit;
}
li {
margin-top: 0.6em;
margin-bottom: 0.6em;
}
h1, h2, h3, h4 {
position: relative;
line-height: 1;
}
a.self-link {
position: absolute;
top: 0;
left: calc(-1 * (3.5rem - 26px));
width: calc(3.5rem - 26px);
height: 2em;
text-align: center;
border: none;
transition: opacity .2s;
opacity: .5;
font-family: sans-serif;
font-weight: normal;
font-size: 83%;
}
a.self-link:hover { opacity: 1; }
a.self-link::before { content: "§"; }
ul > li:before {
content: "\2014";
position: absolute;
margin-left: -1.5em;
}
:target { background-color: #C9FBC9; }
:target .codeblock { background-color: #C9FBC9; }
:target ul { background-color: #C9FBC9; }
.abbr_ref { float: right; }
.folded_abbr_ref { float: right; }
:target .folded_abbr_ref { display: none; }
:target .unfolded_abbr_ref { float: right; display: inherit; }
.unfolded_abbr_ref { display: none; }
.secnum { display: inline-block; min-width: 35pt; }
.header-section-number { display: inline-block; min-width: 35pt; }
.annexnum { display: block; }
div.sourceLinkParent {
float: right;
}
a.sourceLink {
position: absolute;
opacity: 0;
margin-left: 10pt;
}
a.sourceLink:hover {
opacity: 1;
}
a.itemDeclLink {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
opacity: 0;
}
a.itemDeclLink:hover { opacity: 1; }
span.marginalizedparent {
position: relative;
left: -5em;
}
li span.marginalizedparent { left: -7em; }
li ul > li span.marginalizedparent { left: -9em; }
li ul > li ul > li span.marginalizedparent { left: -11em; }
li ul > li ul > li ul > li span.marginalizedparent { left: -13em; }
div.footnoteNumberParent {
position: relative;
left: -4.7em;
}
a.marginalized {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
}
a.enumerated_item_num {
position: relative;
left: -3.5em;
display: inline-block;
margin-right: -3em;
text-align: right;
width: 3em;
}
div.para { margin-bottom: 0.6em; margin-top: 0.6em; text-align: justify; }
div.section { text-align: justify; }
div.sentence { display: inline; }
span.indexparent {
display: inline;
position: relative;
float: right;
right: -1em;
}
a.index {
position: absolute;
display: none;
}
a.index:before { content: "⟵"; }

a.index:target {
display: inline;
}
.indexitems {
margin-left: 2em;
text-indent: -2em;
}
div.itemdescr {
margin-left: 3em;
}
.bnf {
font-family: serif;
margin-left: 40pt;
margin-top: 0.5em;
margin-bottom: 0.5em;
}
.ncbnf {
font-family: serif;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
}
.ncsimplebnf {
font-family: serif;
font-style: italic;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
background: inherit; 
}
span.textnormal {
font-style: normal;
font-family: serif;
white-space: normal;
display: inline-block;
}
span.rlap {
display: inline-block;
width: 0px;
}
span.descr { font-style: normal; font-family: serif; }
span.grammarterm { font-style: italic; }
span.term { font-style: italic; }
span.terminal { font-family: monospace; font-style: normal; }
span.nonterminal { font-style: italic; }
span.tcode { font-family: monospace; font-style: normal; }
span.textbf { font-weight: bold; }
span.textsc { font-variant: small-caps; }
a.nontermdef { font-style: italic; font-family: serif; }
span.emph { font-style: italic; }
span.techterm { font-style: italic; }
span.mathit { font-style: italic; }
span.mathsf { font-family: sans-serif; }
span.mathrm { font-family: serif; font-style: normal; }
span.textrm { font-family: serif; }
span.textsl { font-style: italic; }
span.mathtt { font-family: monospace; font-style: normal; }
span.mbox { font-family: serif; font-style: normal; }
span.ungap { display: inline-block; width: 2pt; }
span.textit { font-style: italic; }
span.texttt { font-family: monospace; }
span.tcode_in_codeblock { font-family: monospace; font-style: normal; }
span.phantom { color: white; }

span.math { font-style: normal; }
span.mathblock {
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 1.2em;
margin-bottom: 1.2em;
text-align: center;
}
span.mathalpha {
font-style: italic;
}
span.synopsis {
font-weight: bold;
margin-top: 0.5em;
display: block;
}
span.definition {
font-weight: bold;
display: block;
}
.codeblock {
margin-left: 1.2em;
line-height: 127%;
}
.outputblock {
margin-left: 1.2em;
line-height: 127%;
}
div.itemdecl {
margin-top: 2ex;
}
code.itemdeclcode {
white-space: pre;
display: block;
}
span.textsuperscript {
vertical-align: super;
font-size: smaller;
line-height: 0;
}
.footnotenum { vertical-align: super; font-size: smaller; line-height: 0; }
.footnote {
font-size: small;
margin-left: 2em;
margin-right: 2em;
margin-top: 0.6em;
margin-bottom: 0.6em;
}
div.minipage {
display: inline-block;
margin-right: 3em;
}
div.numberedTable {
text-align: center;
margin: 2em;
}
div.figure {
text-align: center;
margin: 2em;
}
table {
border: 1px solid black;
border-collapse: collapse;
margin-left: auto;
margin-right: auto;
margin-top: 0.8em;
text-align: left;
hyphens: none; 
}
td, th {
padding-left: 1em;
padding-right: 1em;
vertical-align: top;
}
td.empty {
padding: 0px;
padding-left: 1px;
}
td.left {
text-align: left;
}
td.right {
text-align: right;
}
td.center {
text-align: center;
}
td.justify {
text-align: justify;
}
td.border {
border-left: 1px solid black;
}
tr.rowsep, td.cline {
border-top: 1px solid black;
}
tr.even, tr.odd {
border-bottom: 1px solid black;
}
tr.capsep {
border-top: 3px solid black;
border-top-style: double;
}
tr.header {
border-bottom: 3px solid black;
border-bottom-style: double;
}
th {
border-bottom: 1px solid black;
}
span.centry {
font-weight: bold;
}
div.table {
display: block;
margin-left: auto;
margin-right: auto;
text-align: center;
width: 90%;
}
span.indented {
display: block;
margin-left: 2em;
margin-bottom: 1em;
margin-top: 1em;
}
ol.enumeratea { list-style-type: none; background: inherit; }
ol.enumerate { list-style-type: none; background: inherit; }

code.sourceCode > span { display: inline; }
</style>
  <link href="data:image/x-icon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAVoJEAN6CRADegkQAWIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wCCRAAAgkQAAIJEAACCRAAsgkQAvoJEAP+CRAD/gkQA/4JEAP+CRADAgkQALoJEAACCRAAAgkQAAP///wD///8AgkQAAIJEABSCRACSgkQA/IJEAP99PQD/dzMA/3czAP99PQD/gkQA/4JEAPyCRACUgkQAFIJEAAD///8A////AHw+AFiBQwDqgkQA/4BBAP9/PxP/uZd6/9rJtf/bybX/upd7/39AFP+AQQD/gkQA/4FDAOqAQgBc////AP///wDKklv4jlEa/3o7AP+PWC//8+3o///////////////////////z7un/kFox/35AAP+GRwD/mVYA+v///wD///8A0Zpk+NmibP+0d0T/8evj///////+/fv/1sKz/9bCs//9/fr//////+/m2/+NRwL/nloA/5xYAPj///8A////ANKaZPjRmGH/5cKh////////////k149/3UwAP91MQD/lmQ//86rhv+USg3/m1YA/5hSAP+bVgD4////AP///wDSmmT4zpJY/+/bx///////8+TV/8mLT/+TVx//gkIA/5lVAP+VTAD/x6B//7aEVv/JpH7/s39J+P///wD///8A0ppk+M6SWP/u2sf///////Pj1f/Nj1T/2KFs/8mOUv+eWhD/lEsA/8aee/+0glT/x6F7/7J8Rvj///8A////ANKaZPjRmGH/48Cf///////+/v7/2qt//82PVP/OkFX/37KJ/86siv+USg7/mVQA/5hRAP+bVgD4////AP///wDSmmT40ppk/9CVXP/69O////////7+/v/x4M//8d/P//7+/f//////9u7n/6tnJf+XUgD/nFgA+P///wD///8A0ppk+NKaZP/RmWL/1qNy//r07///////////////////////+vXw/9akdP/Wnmn/y5FY/6JfFvj///8A////ANKaZFTSmmTo0ppk/9GYYv/Ql1//5cWm//Hg0P/x4ND/5cWm/9GXYP/RmGH/0ppk/9KaZOjVnmpY////AP///wDSmmQA0ppkEtKaZI7SmmT60ppk/9CWX//OkVb/zpFW/9CWX//SmmT/0ppk/NKaZJDSmmQS0ppkAP///wD///8A0ppkANKaZADSmmQA0ppkKtKaZLrSmmT/0ppk/9KaZP/SmmT/0ppkvNKaZCrSmmQA0ppkANKaZAD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkUtKaZNzSmmTc0ppkVNKaZADSmmQA0ppkANKaZADSmmQA////AP5/AAD4HwAA4AcAAMADAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAMADAADgBwAA+B8AAP5/AAAoAAAAIAAAAEAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAyCRACMgkQA6oJEAOqCRACQgkQAEIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRABigkQA5oJEAP+CRAD/gkQA/4JEAP+CRADqgkQAZoJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAA4gkQAwoJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQAxIJEADyCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAP///wD///8A////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAWgkQAmIJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAJyCRAAYgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAdIJEAPCCRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAPSCRAB4gkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQASoJEANKCRAD/gkQA/4JEAP+CRAD/g0YA/39AAP9zLgD/bSQA/2shAP9rIQD/bSQA/3MuAP9/PwD/g0YA/4JEAP+CRAD/gkQA/4JEAP+CRADUgkQAToJEAACCRAAAgkQAAP///wD///8A////AP///wB+PwAAgkUAIoJEAKiCRAD/gkQA/4JEAP+CRAD/hEcA/4BBAP9sIwD/dTAA/5RfKv+viF7/vp56/76ee/+wiF7/lWAr/3YxAP9sIwD/f0AA/4RHAP+CRAD/gkQA/4JEAP+CRAD/gkQArIJEACaBQwAA////AP///wD///8A////AIBCAEBzNAD6f0EA/4NFAP+CRAD/gkQA/4VIAP92MwD/bSUA/6N1Tv/ezsL/////////////////////////////////38/D/6V3Uv9uJgD/dTEA/4VJAP+CRAD/gkQA/4JEAP+BQwD/fUAA/4FDAEj///8A////AP///wD///8AzJRd5qBlKf91NgD/dDUA/4JEAP+FSQD/cy4A/3YyAP/PuKP//////////////////////////////////////////////////////9K7qP94NQD/ciwA/4VJAP+CRAD/fkEA/35BAP+LSwD/mlYA6v///wD///8A////AP///wDdpnL/4qx3/8KJUv+PUhf/cTMA/3AsAP90LgD/4dK+/////////////////////////////////////////////////////////////////+TYxf91MAD/dTIA/31CAP+GRwD/llQA/6FcAP+gWwD8////AP///wD///8A////ANGZY/LSm2X/4ap3/92mcP+wdT3/byQA/8mwj////////////////////////////////////////////////////////////////////////////+LYxv9zLgP/jUoA/59bAP+hXAD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/RmWL/1p9q/9ubXv/XqXj////////////////////////////7+fD/vZyG/6BxS/+gcUr/vJuE//r37f//////////////////////3MOr/5dQBf+dVQD/nVkA/5xYAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmWP/yohJ//jo2P//////////////////////4NTG/4JDFf9lGAD/bSQA/20kAP9kGAD/fz8S/+Xb0f//////5NG9/6txN/+LOgD/m1QA/51aAP+cWAD/m1cA/5xYAP+cWADy////AP///wD///8A////ANKaZPLSmmT/0ppk/8+TWf/Unmv//v37//////////////////////+TWRr/VwsA/35AAP+ERgD/g0UA/4JGAP9lHgD/kFga/8KXX/+TRwD/jT4A/49CAP+VTQD/n10A/5xYAP+OQQD/lk4A/55cAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/y4tO/92yiP//////////////////////8NnE/8eCQP+rcTT/ez0A/3IyAP98PgD/gEMA/5FSAP+USwD/jj8A/5lUAP+JNwD/yqV2/694Mf+HNQD/jkAA/82rf/+laBj/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/LiUr/4byY///////////////////////gupX/0I5P/+Wuev/Lklz/l1sj/308AP+QSwD/ol0A/59aAP+aVQD/k0oA/8yoh///////+fXv/6pwO//Lp3v///////Pr4f+oay7y////AP///wD///8A////ANKaZPLSmmT/0ppk/8uJSv/hvJj//////////////////////+G7l//Jhkb/0ppk/96nc//fqXX/x4xO/6dkFP+QSQD/llEA/5xXAP+USgD/yaOA///////38uv/qG05/8ijdv//////8efb/6ZpLPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/zIxO/9yxh///////////////////////7dbA/8iEQf/Sm2X/0Zlj/9ScZv/eqHf/2KJv/7yAQf+XTgD/iToA/5lSAP+JNgD/yKFv/611LP+HNQD/jT8A/8qmeP+kZRT/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/Pk1n/1J5q//78+//////////////////+/fv/1aFv/8iEQv/Tm2b/0ppl/9GZY//Wn2z/1pZc/9eldf/Bl2b/kUcA/4w9AP+OQAD/lUwA/59eAP+cWQD/jT8A/5ZOAP+eXADy////AP///wD///8A////ANKaZPLSmmT/0ppk/9KZY//KiEn/8d/P///////////////////////47+f/05tm/8iCP//KiEj/yohJ/8eCP//RmGH//vfy///////n1sP/rXQ7/4k4AP+TTAD/nVoA/5xYAP+cVwD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/0ptl/8uLTf/aq37////////////////////////////+/fz/6c2y/961jv/etY7/6Myx//78+v//////////////////////3MWv/5xXD/+ORAD/mFQA/51ZAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmmT/0ppk/8mFRP/s1b//////////////////////////////////////////////////////////////////////////////+PD/0JFU/7NzMv+WUQD/kUsA/5tXAP+dWQDy////AP///wD///8A////ANKaZP/SmmT/0ppk/9KaZP/Sm2X/z5NZ/8yMT//z5NX/////////////////////////////////////////////////////////////////9Ofa/8yNUP/UmGH/36p5/8yTWv+qaSD/kksA/5ROAPz///8A////AP///wD///8A0ppk5NKaZP/SmmT/0ppk/9KaZP/TnGf/zY9T/82OUv/t1sD//////////////////////////////////////////////////////+7Yw//OkFX/zI5R/9OcZ//SmmP/26V0/9ymdf/BhUf/ol8R6P///wD///8A////AP///wDSmmQ80ppk9tKaZP/SmmT/0ppk/9KaZP/TnGj/zpFW/8qJSv/dson/8uHS//////////////////////////////////Lj0//etIv/y4lL/86QVf/TnGj/0ppk/9KaZP/RmWP/05xn/9ymdfjUnWdC////AP///wD///8A////ANKaZADSmmQc0ppkotKaZP/SmmT/0ppk/9KaZP/Tm2b/0Zli/8qJSf/NjlH/16Z3/+G8mP/myKr/5siq/+G8mP/Xp3f/zY5S/8qISf/RmGH/05tm/9KaZP/SmmT/0ppk/9KaZP/SmmSm0pljINWdaQD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkQtKaZMrSmmT/0ppk/9KaZP/SmmT/0ptl/9GYYf/Nj1P/y4lL/8qISP/KiEj/y4lK/82PU//RmGH/0ptl/9KaZP/SmmT/0ppk/9KaZP/SmmTO0ppkRtKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZGzSmmTu0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmTw0ppkcNKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZBLSmmSQ0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppklNKaZBTSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQy0ppkutKaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppkvtKaZDbSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkXNKaZODSmmT/0ppk/9KaZP/SmmT/0ppk5NKaZGDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkBtKaZIbSmmTo0ppk6tKaZIrSmmQK0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP/8P///+B///+AH//+AAf//AAD//AAAP/AAAA/gAAAHwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAfwAAAP/AAAP/8AAP//gAH//+AH///4H////D//" rel="icon" />
  
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<div class="wrapper">
<header id="title-block-header">
<h1 class="title" style="text-align:center">A Utility for Creating
Execution Environments</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P3325R4</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2024-11-21</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Project:</td>
    <td>Programming Language C++</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Audience:</td>
    <td>
      LWG Library Evolution<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Eric Niebler<br>&lt;<a href="mailto:eric.niebler@gmail.com" class="email">eric.niebler@gmail.com</a>&gt;<br>
    </td>
  </tr>
</table>
</header>
<div style="clear:both">
<div id="TOC" role="doc-toc">
<h1 id="toctitle">Contents</h1>
<ul>
<li><a href="#introduction" id="toc-introduction"><span class="toc-section-number">1</span> Introduction<span></span></a></li>
<li><a href="#executive-summary" id="toc-executive-summary"><span class="toc-section-number">2</span> Executive
Summary<span></span></a></li>
<li><a href="#revision-history" id="toc-revision-history"><span class="toc-section-number">3</span> Revision History<span></span></a>
<ul>
<li><a href="#r4" id="toc-r4"><span class="toc-section-number">3.1</span> R4<span></span></a></li>
<li><a href="#r3" id="toc-r3"><span class="toc-section-number">3.2</span> R3<span></span></a></li>
<li><a href="#r2" id="toc-r2"><span class="toc-section-number">3.3</span> R2<span></span></a></li>
<li><a href="#r1" id="toc-r1"><span class="toc-section-number">3.4</span> R1<span></span></a></li>
<li><a href="#r0" id="toc-r0"><span class="toc-section-number">3.5</span> R0<span></span></a></li>
</ul></li>
<li><a href="#discussion" id="toc-discussion"><span class="toc-section-number">4</span> Discussion<span></span></a>
<ul>
<li><a href="#motivation" id="toc-motivation"><span class="toc-section-number">4.1</span> Motivation<span></span></a></li>
<li><a href="#design-considerations" id="toc-design-considerations"><span class="toc-section-number">4.2</span> Design
Considerations<span></span></a>
<ul>
<li><a href="#singleton-environments" id="toc-singleton-environments"><span class="toc-section-number">4.2.1</span> Singleton
Environments<span></span></a></li>
<li><a href="#environment-composition" id="toc-environment-composition"><span class="toc-section-number">4.2.2</span> Environment
Composition<span></span></a></li>
<li><a href="#by-value-vs.-by-reference" id="toc-by-value-vs.-by-reference"><span class="toc-section-number">4.2.3</span> By Value vs. By
Reference<span></span></a></li>
<li><a href="#should-environments-be-constrained" id="toc-should-environments-be-constrained"><span class="toc-section-number">4.2.4</span> Should Environments Be
Constrained?<span></span></a></li>
</ul></li>
<li><a href="#naming" id="toc-naming"><span class="toc-section-number">4.3</span> Naming<span></span></a></li>
</ul></li>
<li><a href="#implementation-experience" id="toc-implementation-experience"><span class="toc-section-number">5</span> Implementation
Experience<span></span></a></li>
<li><a href="#future-extensions" id="toc-future-extensions"><span class="toc-section-number">6</span> Future
Extensions<span></span></a></li>
<li><a href="#proposed-wording" id="toc-proposed-wording"><span class="toc-section-number">7</span> Proposed
Wording<span></span></a></li>
<li><a href="#acknowledgements" id="toc-acknowledgements"><span class="toc-section-number">8</span>
Acknowledgements<span></span></a></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">9</span> References<span></span></a></li>
</ul>
</div>
<div style="text-align: right;">
<p><em>“The environment is everything that isn’t me.”</em><br /> — Albert
Einstein</p>
</div>
<h1 data-number="1" id="introduction"><span class="header-section-number">1</span> Introduction<a href="#introduction" class="self-link"></a></h1>
<p>Execution environments are a fundamental part of the sender-based
facilities in <code class="sourceCode default">std::execution</code>,
but the current working draft provides no utility for creating or
manipulating environments. Such utilities are increasingly necessary
considering that some proposed APIs (e.g.,
<code class="sourceCode default">write_env</code> from <span class="citation" data-cites="P3284R0">[<a href="#ref-P3284R0" role="doc-biblioref">P3284R0</a>]</span>) require passing an
environment.</p>
<p>This paper proposes two simple utilities for creating execution
environments: one to create an environment out of a query/value pair and
another to join several environments into one.</p>
<h1 data-number="2" id="executive-summary"><span class="header-section-number">2</span> Executive Summary<a href="#executive-summary" class="self-link"></a></h1>
<p>This paper proposes the following changes to the working draft:</p>
<ul>
<li><p>Add a class template provisionally called
<code class="sourceCode default">prop</code> to the
<code class="sourceCode default">std::execution</code> namespace.
<code class="sourceCode default">prop</code> associates a query
<code class="sourceCode default">Q</code> with a value
<code class="sourceCode default">V</code>, yielding a
<em><code class="sourceCode default">queryable</code></em> object
<code class="sourceCode default">E</code> such that
<code class="sourceCode default">E.query(Q)</code> is equal to
<code class="sourceCode default">V</code>.</p></li>
<li><p>Add a class template provisionally called
<code class="sourceCode default">env</code> to the
<code class="sourceCode default">std::execution</code> namespace.
<code class="sourceCode default">env</code> aggregates several
environments into one, giving precedence to the environments in lexical
order.</p></li>
<li><p>Optionally, replace
<code class="sourceCode default">empty_env</code> with
<code class="sourceCode default">env&lt;&gt;</code>.</p></li>
</ul>
<h1 data-number="3" id="revision-history"><span class="header-section-number">3</span> Revision History<a href="#revision-history" class="self-link"></a></h1>
<h2 data-number="3.1" id="r4"><span class="header-section-number">3.1</span> R4<a href="#r4" class="self-link"></a></h2>
<ul>
<li>Wording fixes requested by LWG.</li>
</ul>
<h2 data-number="3.2" id="r3"><span class="header-section-number">3.2</span> R3<a href="#r3" class="self-link"></a></h2>
<ul>
<li>Delete the assignment operators of
<code class="sourceCode default">prop</code> and
<code class="sourceCode default">env</code>.</li>
</ul>
<h2 data-number="3.3" id="r2"><span class="header-section-number">3.3</span> R2<a href="#r2" class="self-link"></a></h2>
<ul>
<li><p>Change the target to the working draft instead of P2300.</p></li>
<li><p>For the type
<code class="sourceCode default">prop&lt;Query, Value&gt;</code> mandate
that <code class="sourceCode default">Query()(env)</code> is
well-formed, where <code class="sourceCode default">env</code> is an
environment whose type is equivalent to
<code class="sourceCode default">prop&lt;Query,   Value&gt;</code>.</p></li>
<li><p>From the <code class="sourceCode default">env</code> class
template, remove support for queries that take extra arguments.</p></li>
<li><p>Attributes <code class="sourceCode default">[[nodiscard]]</code>
and <code class="sourceCode default">[[no_unique_address]]</code> are
removed from the specification, following LEWG’s and LWG’s
policies.</p></li>
</ul>
<h2 data-number="3.4" id="r1"><span class="header-section-number">3.4</span> R1<a href="#r1" class="self-link"></a></h2>
<ul>
<li>Added a section considering whether
<code class="sourceCode default">prop</code> or
<code class="sourceCode default">env</code> should enforce the syntactic
requirements of the queries they support. See <a href="#should-environments-be-constrained">“Should Environments Be
Constrained?”</a>.</li>
</ul>
<h2 data-number="3.5" id="r0"><span class="header-section-number">3.5</span> R0<a href="#r0" class="self-link"></a></h2>
<ul>
<li>Initial revision</li>
</ul>
<h1 data-number="4" id="discussion"><span class="header-section-number">4</span> Discussion<a href="#discussion" class="self-link"></a></h1>
<h2 data-number="4.1" id="motivation"><span class="header-section-number">4.1</span> Motivation<a href="#motivation" class="self-link"></a></h2>
<p>In [exec], execution environments are an internal implementation
detail of the sender algorithms. There are no public-facing APIs that
accept environment objects as a parameter. One may wonder why a utility
for constructing environments is even necessary.</p>
<p>There are several reasons why the Standard Library would benefit from
a utility to construct an environment:</p>
<ol type="1">
<li><p>The set of sender algorithms is openly extensible. For those who
decide to implement their own sender algorithms, the manipulation of
execution environments is part of the job. Standard utilities will make
this easier.</p></li>
<li><p><span class="citation" data-cites="P3284R0">[<a href="#ref-P3284R0" role="doc-biblioref">P3284R0</a>]</span> proposes a
<code class="sourceCode default">write_env</code> sender adaptor that
merges a user-specified environment with the environment of the receiver
to which the sender is eventually connected. Using this adaptor requires
the user to construct an environment. Although implementing an
environment is not hard, an out-of-the-box solution will make using
<code class="sourceCode default">write_env</code> simpler.</p></li>
<li><p><span class="citation" data-cites="P3149R3">[<a href="#ref-P3149R3" role="doc-biblioref">P3149R3</a>]</span> proposes
two new algorithms, <code class="sourceCode default">spawn</code> and
<code class="sourceCode default">spawn_future</code>, both of which can
be parameterized by passing an environment as an optional
argument.</p></li>
<li><p>Currently, there is no way to parameterize algorithms like
<code class="sourceCode default">sync_wait</code> and
<code class="sourceCode default">start_detached</code>. The author
intends to bring a paper proposing overloads of those functions that
accept environments as a way to inject things like stop tokens,
allocators, and schedulers into the asynchronous operations that those
algorithms launch.</p></li>
</ol>
<p>In short, environments are how users will inject dependencies into
async computations. We can expect to see more APIs that will require (or
will optionally allow) the user to pass an environment. Thus, a standard
utility for making environments is desirable.</p>
<h2 data-number="4.2" id="design-considerations"><span class="header-section-number">4.2</span> Design Considerations<a href="#design-considerations" class="self-link"></a></h2>
<h3 data-number="4.2.1" id="singleton-environments"><span class="header-section-number">4.2.1</span> Singleton Environments<a href="#singleton-environments" class="self-link"></a></h3>
<p>Defining an execution environment is quite simple. To build an
environment with a single query/value pair, the following suffices:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Query, <span class="kw">class</span> Value<span class="op">&gt;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> prop</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">[[</span><span class="at">no_unique_address</span><span class="op">]]</span> Query query_;</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>  Value value_;</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> query<span class="op">(</span>Query<span class="op">)</span> <span class="kw">const</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> <span class="kw">const</span> Value <span class="op">&amp;</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">{</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> value_;</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a><span class="co">// Example usage:</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> my_env <span class="op">=</span> prop<span class="op">(</span>get_allocator, std<span class="op">::</span>allocator<span class="op">{})</span>;</span></code></pre></div>
<p>Although simple, this template has some nice properties:</p>
<ol type="1">
<li><p>It is an aggregate so that members can be direct initialized from
temporaries without so much as a move. A function that constructs and
returns an environment using
<code class="sourceCode default">prop</code> will benefit from RVO:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="co">// The frobnicator object will be constructed directly in</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="co">// the callers stack frame:</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> prop<span class="op">(</span>get_frobnicator, make_a_frobnicator<span class="op">())</span>;</span></code></pre></div></li>
<li><p>An object constructed like <code class="sourceCode default">prop(get_allocator, my_allocator{})</code>
will have the simple and unsurprising type <code class="sourceCode default">prop&lt;get_allocator_t, my_allocator&gt;</code>.</p></li>
</ol>
<p>The <code class="sourceCode default">prop</code> utility proposed in
this paper is only slightly more elaborate than the
<code class="sourceCode default">prop</code> class template shown above,
and it shares these properties.</p>
<h3 data-number="4.2.2" id="environment-composition"><span class="header-section-number">4.2.2</span> Environment Composition<a href="#environment-composition" class="self-link"></a></h3>
<p>What if you need to construct an environment with more than one
query/value pair, say, an allocator and a scheduler? A utility to join
multiple environments would work together with
<code class="sourceCode default">prop</code> to make a general
environment-building utility. This paper calls that utility
<code class="sourceCode default">env</code>.</p>
<p>The following code demonstrates:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Env, <span class="kw">class</span> Query<span class="op">&gt;</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="kw">concept</span> <em><code class="sourceCode default">has-query</code></em> <span class="op">=</span> <span class="kw">requires</span> <span class="op">(</span><span class="kw">const</span> Env<span class="op">&amp;</span> env<span class="op">)</span> <span class="op">{</span> env<span class="op">.</span>query<span class="op">(</span>Query<span class="op">())</span>; <span class="op">}</span>;</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> Envs<span class="op">&gt;</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> env <span class="op">:</span> Envs<span class="op">...</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Query<span class="op">&gt;</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">constexpr</span> <span class="dt">size_t</span> _index_of<span class="op">()</span> <span class="op">{</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="dt">bool</span> flags<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span><em><code class="sourceCode default">has-query</code></em><span class="op">&lt;</span>Envs, Query<span class="op">&gt;...}</span>;</span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> ranges<span class="op">::</span>find<span class="op">(</span>flags, <span class="kw">true</span><span class="op">)</span> <span class="op">-</span> flags;</span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Query<span class="op">&gt;</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <span class="op">(</span><em><code class="sourceCode default">has-query</code></em><span class="op">&lt;</span>Envs, Query<span class="op">&gt;</span> <span class="op">||...)</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>  <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> query<span class="op">(</span>Query q<span class="op">)</span> <span class="kw">const</span> <span class="kw">noexcept</span><span class="op">(...)</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>  <span class="op">{</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> tup <span class="op">=</span> tie<span class="op">(</span><span class="kw">static_cast</span><span class="op">&lt;</span><span class="kw">const</span> Envs<span class="op">&amp;&gt;(*</span><span class="kw">this</span><span class="op">)...)</span>;</span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> get<span class="op">&lt;</span>_index_of<span class="op">&lt;</span>Query<span class="op">&gt;()&gt;(</span>tup<span class="op">).</span>query<span class="op">(</span>q<span class="op">)</span>;</span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> Envs<span class="op">&gt;</span></span>
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true" tabindex="-1"></a>env<span class="op">(</span>Envs<span class="op">...)</span> <span class="op">-&gt;</span> env<span class="op">&lt;</span>Envs<span class="op">...&gt;</span>;</span>
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-25"><a href="#cb3-25" aria-hidden="true" tabindex="-1"></a><span class="co">// Example usage:</span></span>
<span id="cb3-26"><a href="#cb3-26" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> my_env <span class="op">=</span> env<span class="op">{</span>prop<span class="op">(</span>get_allocator, my_alloc<span class="op">{})</span>,</span>
<span id="cb3-27"><a href="#cb3-27" aria-hidden="true" tabindex="-1"></a>                            prop<span class="op">(</span>get_scheduler, my_sched<span class="op">{})}</span>;</span></code></pre></div>
<p>This <code class="sourceCode default">env</code> class template
shares the desirable properties of
<code class="sourceCode default">prop</code>: aggregate initialization
and unsprising naming. A query is handled by the “leftmost” child
environment that can handle it.</p>
<p>Note that the above code has the issue that two child environments
cannot have the same type. That is not a limitation of the facility
proposed below.</p>
<h3 data-number="4.2.3" id="by-value-vs.-by-reference"><span class="header-section-number">4.2.3</span> By Value vs. By Reference<a href="#by-value-vs.-by-reference" class="self-link"></a></h3>
<p>There are times when you would like an environment to respond to a
query with a reference to a particular object rather than a copy.
Capturing a reference is dangerous, so the opt-in to reference semantics
should be explicit.</p>
<p><code class="sourceCode default">std::reference_wrapper</code> is how
the Standard Library deals with such problems. It should be possible to
construct an environment using
<code class="sourceCode default">std::ref</code> to specify that the
“value” should be stored by reference:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>mutex mtx;</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> <span class="kw">auto</span> my_env <span class="op">=</span> prop<span class="op">(</span>get_mutex, std<span class="op">::</span>ref<span class="op">(</span>mtx<span class="op">))</span>;</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>mutex <span class="op">&amp;</span> ref <span class="op">=</span> get_mutex<span class="op">(</span>my_env<span class="op">)</span>;</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="ot">assert</span><span class="op">(&amp;</span>ref <span class="op">==</span> <span class="op">&amp;</span>mtx<span class="op">)</span>;</span></code></pre></div>
<p>Similarly, there are times when you would like to store the child
environment by reference.
<code class="sourceCode default">std::ref</code> should work for that
case as well:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="co">// At namespace scope, construct a reusable environment:</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> global_env <span class="op">=</span> prop<span class="op">(</span>get_frobnicator, make_frobnicator<span class="op">())</span>;</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="co">// Construct an environment with a particular value for the get_allocator</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="co">// query, and a reference to the constexpr global_env:</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> env_with_allocator<span class="op">(</span><span class="kw">auto</span> alloc<span class="op">)</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> env<span class="op">{</span>prop<span class="op">(</span>get_allocator, alloc<span class="op">)</span>, std<span class="op">::</span>ref<span class="op">(</span>global_env<span class="op">)}</span>;</span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The utility proposed in this paper satisfies all of the above use
cases.</p>
<h3 data-number="4.2.4" id="should-environments-be-constrained"><span class="header-section-number">4.2.4</span> Should Environments Be
Constrained?<a href="#should-environments-be-constrained" class="self-link"></a></h3>
<p>An interesting question came up during LEWG design review at the
St. Louis committee meeting. Consider a
<em><code class="sourceCode default">queryable</code></em> object
<code class="sourceCode default">e</code> such that
<code class="sourceCode default">e.query(get_scheduler)</code> is
well-formed. The <code class="sourceCode default">get_scheduler</code>
query should always return an object whose type satisfies the
<code class="sourceCode default">scheduler</code> concept. So, should
the expression
<code class="sourceCode default">e.query(get_scheduler)</code> be
somehow constrained with that requirement? Should the expression be
ill-formed if it returns an <code class="sourceCode default">int</code>,
say.</p>
<p>During the LEWG telecon on July 16, 2024, it was decided that
instantiations of the
<code class="sourceCode default">prop&lt;Query, Value&gt;</code> class
template should mandate that
<code class="sourceCode default">Query</code> is callable with
<code class="sourceCode default">prop&lt;Query, Value&gt;</code> (or
rather, a type equivalent to
<code class="sourceCode default">prop&lt;Query, Value&gt;</code> since
the <code class="sourceCode default">prop&lt;Query, Value&gt;</code>
type will be incomplete at the time the requirement is checked).</p>
<p>This will have the effect that, if
<code class="sourceCode default">Query()(env)</code> has requirements or
mandates on the expression
<code class="sourceCode default">env.query(Query())</code>, that those
requirements or mandates will cause a hard error when they are not met,
and that the error happens as early as possible: when the
<code class="sourceCode default">prop</code> class template is
instantiated.</p>
<p>For example, consider the following query:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> get_scheduler_t</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Env<span class="op">&gt;</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <em><code class="sourceCode default">has-query</code></em><span class="op">&lt;</span>Env, get_scheduler_t<span class="op">&gt;</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> <span class="kw">operator</span><span class="op">()(</span><span class="kw">const</span> Env<span class="op">&amp;</span> env<span class="op">)</span> <span class="kw">const</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">{</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Mandates: env.query(*this) returns a scheduler</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static_assert</span><span class="op">(</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>      scheduler<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>env<span class="op">.</span>query<span class="op">(*</span><span class="kw">this</span><span class="op">))&gt;</span>,</span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>      <span class="st">&quot;The &#39;get_scheduler&#39; query must return a type that satisfies the &#39;scheduler&#39; concept.&quot;</span><span class="op">)</span>;</span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> env<span class="op">.</span>query<span class="op">(*</span><span class="kw">this</span><span class="op">)</span>;</span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a><span class="kw">inline</span> <span class="kw">constexpr</span> get_scheduler_t get_scheduler <span class="op">{}</span>;</span></code></pre></div>
<p>With the code above, the expression
<code class="sourceCode default">prop(get_scheduler, 42)</code> will
cause the program to be ill-formed because the type
<code class="sourceCode default">int</code> does not satisfy the
<code class="sourceCode default">scheduler</code> concept.</p>
<h2 data-number="4.3" id="naming"><span class="header-section-number">4.3</span> Naming<a href="#naming" class="self-link"></a></h2>
<p>For the <code class="sourceCode default">prop</code> utility, a
couple of other plausible names come to mind:</p>
<ul>
<li><code class="sourceCode default">attr</code></li>
<li><code class="sourceCode default">with</code></li>
<li><code class="sourceCode default">property</code></li>
<li><code class="sourceCode default">key_value</code></li>
<li><code class="sourceCode default">query_value</code></li>
</ul>
<p>Other possibile names for <code class="sourceCode default">env</code>
are:</p>
<ul>
<li><code class="sourceCode default">attributes</code>, or
<code class="sourceCode default">attrs</code></li>
<li><code class="sourceCode default">properties</code>, or
<code class="sourceCode default">props</code></li>
<li><code class="sourceCode default">dictionary</code>, or
<code class="sourceCode default">dict</code></li>
</ul>
<h1 data-number="5" id="implementation-experience"><span class="header-section-number">5</span> Implementation Experience<a href="#implementation-experience" class="self-link"></a></h1>
<p>Types with a very similar designs have seen heavy use in
<code class="sourceCode default">stdexec</code> for over two years. The
design proposed below has been prototyped and can be found on <a href="https://godbolt.org/z/976b1G45a">Compiler Explorer</a><a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a>.</p>
<p><em>A note on implementability:</em> The implementation of
<code class="sourceCode default">env</code> is simple if we only want to
support braced list initialization with class template argument
deduction, like <code class="sourceCode default">env{e1, e2, e2}</code>.
Initialization from a parenthesized expression list with CTAD for an
arbitrary number of arguments (e.g.,
<code class="sourceCode default">env(e1, e2, e3, ...)</code>) is not
implementable in standard C++ to the author’s knowledge.</p>
<p>In the proposed wording, <code class="sourceCode default">env</code>
is specified such that it will be able to benefit from member packs
(<span class="citation" data-cites="P3115R0">[<a href="#ref-P3115R0" role="doc-biblioref">P3115R0</a>]</span>) if and when they become
available or should aggregate initialization with a parenthesized
expression list ever be extended to support brace elision for
subobjects.</p>
<h1 data-number="6" id="future-extensions"><span class="header-section-number">6</span> Future Extensions<a href="#future-extensions" class="self-link"></a></h1>
<p>There are several ways this utility might be extended in the
future:</p>
<ul>
<li>Add a way to <em>remove</em> a query from an environment.</li>
<li>Add a wrapper for a reference to an environment.</li>
<li>Add a wrapper that only accepts queries that are <em>forwarding</em>
(see <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r9.html#spec-execution.forwarding_query">[exec.fwd.env]</a>).</li>
</ul>
<h1 data-number="7" id="proposed-wording"><span class="header-section-number">7</span> Proposed Wording<a href="#proposed-wording" class="self-link"></a></h1>
<p>Replace all occurances of
<code class="sourceCode default">empty_env</code> with
<code class="sourceCode default">env&lt;&gt;</code>.</p>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: Change
[exec.syn] as follows: ]</span></p>
<blockquote>
<p><b>Header <code class="sourceCode default">&lt;execution&gt;</code>
synopsis [exec.syn]</b></p>
<div class="sourceCode" id="cb7"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>namespace std::execution {</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>  <em>…as before…</em></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>  <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">struct empty_env {};</code></span></del></span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>  struct get_env_t { <em>see below</em> };</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>  inline constexpr get_env_t get_env{};</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>  template&lt;class T&gt;</span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>    using env_of_t = decltype(get_env(declval&lt;T&gt;()));</span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a>  <span class="add" style="color: #006e28"><ins><em><span><code class="sourceCode default">// [exec.prop] class template prop</code></span></em></ins></span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a>  <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">template&lt;class QueryTag, class ValueType&gt;</code></span></ins></span></span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">struct prop;</code></span></ins></span></span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true" tabindex="-1"></a>  <span class="add" style="color: #006e28"><ins><em><span><code class="sourceCode default">// [exec.env] class template env</code></span></em></ins></span></span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true" tabindex="-1"></a>  <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">template&lt;<em>queryable</em>... Envs&gt;</code></span></ins></span></span>
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">struct env;</code></span></ins></span></span>
<span id="cb7-18"><a href="#cb7-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-19"><a href="#cb7-19" aria-hidden="true" tabindex="-1"></a>  <em>// [exec.domain.default], execution domains</em></span>
<span id="cb7-20"><a href="#cb7-20" aria-hidden="true" tabindex="-1"></a>  struct default_domain;</span>
<span id="cb7-21"><a href="#cb7-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-22"><a href="#cb7-22" aria-hidden="true" tabindex="-1"></a>  <em>// [exec.sched], schedulers</em></span>
<span id="cb7-23"><a href="#cb7-23" aria-hidden="true" tabindex="-1"></a>  struct scheduler_t {};</span>
<span id="cb7-24"><a href="#cb7-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-25"><a href="#cb7-25" aria-hidden="true" tabindex="-1"></a>  <em>…as before…</em></span>
<span id="cb7-26"><a href="#cb7-26" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
</blockquote>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: After
[exec.utils], add a new subsection [exec.envs] as follows: ]</span></p>
<div class="add" style="color: #006e28">

<blockquote>
<p><b>34.12 Queryable utilities [exec.envs]</b></p>
<p><b>34.12.1 Class template
<code class="sourceCode default">prop</code> [exec.prop]</b></p>
<div class="sourceCode" id="cb8"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>namespace std::execution {</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>  template&lt;class QueryTag, class ValueType&gt;</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>  struct prop {</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>    QueryTag <em><code class="sourceCode default">query_</code></em>;    <em>// exposition only</em></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>    ValueType <em><code class="sourceCode default">value_</code></em>;    <em>// exposition only</em></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>    constexpr const ValueType&amp; query(QueryTag) const noexcept {</span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>      return <em><code class="sourceCode default">value_</code></em>;</span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>    }</span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>  };</span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a>  template&lt;class QueryTag, class ValueType&gt;</span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a>    prop(QueryTag, ValueType) -&gt; prop&lt;QueryTag, unwrap_reference_t&lt;ValueType&gt;&gt;;</span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
<ol type="1">
<li><p>Class template <code class="sourceCode default">prop</code> is
for building a queryable object from a query object and a
value.</p></li>
<li><p><em>Mandates:</em> <code class="sourceCode default"><em>callable</em>&lt;QueryTag, <em>prop-like</em>&lt;ValueType&gt;&gt;</code>,
where <em><code class="sourceCode default">prop-like</code></em> is the
following exposition-only class template:</p></li>
</ol>
<blockquote>
<div class="sourceCode" id="cb9"><pre class="sourceCode default default"><code class="sourceCode default"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>template&lt;class ValueType&gt;</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>struct <em>prop-like</em> { <em>// exposition only</em></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>  const ValueType&amp; query(auto) const noexcept;</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>};</span></code></pre></div>
</blockquote>
<ol start="3" type="1">
<li>[<em>Example 1:</em></li>
</ol>
<blockquote>
<div class="sourceCode" id="cb10"><pre class="sourceCode default default"><code class="sourceCode default"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>template&lt;sender Sndr&gt;</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>sender auto parameterize_work(Sndr sndr) {</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>  <em><code class="sourceCode default">// Make an environment such that get_allocator(env) returns a reference to a copy</code></em></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>  <em><code class="sourceCode default">// of my_alloc{}</code></em></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>  auto e = prop(get_allocator, my_alloc{});</span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>  <em><code class="sourceCode default">// parameterize the input sender so that it will use our custom execution environment</code></em></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>  return write_env(sndr, e);</span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
<p>— <em>end example</em>]</p>
</blockquote>
<ol start="4" type="1">
<li>Specializations of <code class="sourceCode default">prop</code> are
not assignable.</li>
</ol>
<p><b>34.12.2 Class template <code class="sourceCode default">env</code>
[exec.env]</b></p>
<div class="sourceCode" id="cb11"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>namespace std::execution {</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>  template&lt;<em><code class="sourceCode default">queryable</code></em>... Envs&gt;</span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>  struct env {</span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>    Envs<em><sub>0</sub></em> <em><code class="sourceCode default">envs_</code><sub>0</sub></em>;       <em>// exposition only</em></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>    Envs<em><sub>1</sub></em> <em><code class="sourceCode default">envs_</code><sub>1</sub></em>;       <em>// exposition only</em></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>      ...</span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>    Envs<em><sub>n-1</sub></em> <em><code class="sourceCode default">envs_</code><sub>n-1</sub></em>;   <em>// exposition only</em></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a>    template&lt;class QueryTag&gt;</span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a>      constexpr decltype(auto) query(QueryTag q) const noexcept(<em>see below</em>);</span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a>  };</span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a>  template&lt;class... Envs&gt;</span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true" tabindex="-1"></a>    env(Envs...) -&gt; env&lt;unwrap_reference_t&lt;Envs&gt;...&gt;;</span>
<span id="cb11-15"><a href="#cb11-15" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
<ol type="1">
<li><p>The class template <code class="sourceCode default">env</code> is
used to construct a queryable object from several queryable objects.
Query invocations on the resulting object are resolved by attempting to
query each subobject in lexical order.</p></li>
<li><p>Specializations of <code class="sourceCode default">env</code>
are not assignable.</p></li>
<li><p>It is unspecified whether
<code class="sourceCode default">env</code> supports class template
argument deduction ([over.match.class.deduct]) when performing
initialization using a parenthesized <em>expression-list</em>
([dcl.init]).</p></li>
<li><p>[<em>Example 1:</em></p></li>
</ol>
<blockquote>
<div class="sourceCode" id="cb12"><pre class="sourceCode default default"><code class="sourceCode default"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>template&lt;sender Sndr&gt;</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>sender auto parameterize_work(Sndr sndr) {</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>  <em><code class="sourceCode default">// Make an environment such that:</code></em></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>  <em><code class="sourceCode default">//  - get_allocator(env) returns a reference to a copy of my_alloc{}</code></em></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>  <em><code class="sourceCode default">//  - get_scheduler(env) returns a reference to a copy of my_sched{}</code></em></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>  auto e = env{prop(get_allocator, my_alloc{}),</span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a>               prop(get_scheduler, my_sched{})};</span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>  <em><code class="sourceCode default">// parameterize the input sender so that it will use our custom execution environment</code></em></span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a>  return write_env(sndr, e);</span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
<p>— <em>end example</em>]</p>
</blockquote>
<p><b>34.12.2.1 <code class="sourceCode default">env</code> members
[exec.env.members]</b></p>
<div class="sourceCode" id="cb13"><pre class="sourceCode default default"><code class="sourceCode default"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a>template&lt;class QueryTag&gt;</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>constexpr decltype(auto) query(QueryTag q) const noexcept(<em>see below</em>);</span></code></pre></div>
<ol type="1">
<li>Let <em><code class="sourceCode default">has-query</code></em> be
the following exposition-only concept:</li>
</ol>
<blockquote>
<div class="sourceCode" id="cb14"><pre class="sourceCode default default"><code class="sourceCode default"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a>template&lt;class Env, class QueryTag&gt;</span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>  concept <em>has-query</em> =                   <em>// exposition only</em></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>    requires (const Env&amp; env) {</span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>      env.query(QueryTag());</span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>    };</span></code></pre></div>
</blockquote>
<ol start="2" type="1">
<li><p>Let <em><code class="sourceCode default">fe</code></em> be the
first element of <code class="sourceCode default"><em><code class="sourceCode default">envs_</code><sub>0</sub></em>, <em><code class="sourceCode default">envs_</code><sub>1</sub></em>, ... <em><code class="sourceCode default">envs_</code><sub>n-1</sub></em></code>
such that the expression
<code class="sourceCode default"><em>fe</em>.query(q)</code> is
well-formed.</p></li>
<li><p><em>Requires:</em> <code class="sourceCode default">(<em>has-query</em>&lt;Envs, QueryTag&gt; || ...)</code>
is <code class="sourceCode default">true</code>.</p></li>
<li><p><em>Effects:</em> Equivalent to
<code class="sourceCode default"><em>fe</em>.query(q)</code>.</p></li>
<li><p><em>Remarks:</em> The expression in the
<code class="sourceCode default">noexcept</code> clause is equivalent to
<code class="sourceCode default">noexcept(<em>fe</em>.query(q))</code>.</p></li>
</ol>
</blockquote>

</div>
<h1 data-number="8" id="acknowledgements"><span class="header-section-number">8</span> Acknowledgements<a href="#acknowledgements" class="self-link"></a></h1>
<p>I would like to thank Lewis Baker for many enlightening conversations
about the design of execution environments. The design presented here
owes much to Lewis’s insights.</p>
<h1 data-number="9" id="bibliography"><span class="header-section-number">9</span> References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references csl-bib-body hanging-indent" role="doc-bibliography">
<div id="ref-P3115R0" class="csl-entry" role="doc-biblioentry">
[P3115R0] Corentin Jabot. 2024-02-15. Data Member, Variable and Alias
Declarations Can Introduce A Pack. <a href="https://wg21.link/p3115r0"><div class="csl-block">https://wg21.link/p3115r0</div></a>
</div>
<div id="ref-P3149R3" class="csl-entry" role="doc-biblioentry">
[P3149R3] Ian Petersen, Ján Ondrušek; Jessica Wong; Kirk Shoop; Lee
Howes; Lucian Radu Teodorescu; 2024-05-22. async_scope — Creating scopes
for non-sequential concurrency. <a href="https://wg21.link/p3149r3"><div class="csl-block">https://wg21.link/p3149r3</div></a>
</div>
<div id="ref-P3284R0" class="csl-entry" role="doc-biblioentry">
[P3284R0] Eric Niebler. 2024-05-16. `finally`, `write_env`, and
`unstoppable` Sender Adaptors. <a href="https://wg21.link/p3284r0"><div class="csl-block">https://wg21.link/p3284r0</div></a>
</div>
</div>
<section class="footnotes footnotes-end-of-document" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p><a href="https://godbolt.org/z/976b1G45a">https://godbolt.org/z/976b1G45a</a><a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
</div>
</div>
</body>
</html>
