<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <meta http-equiv="Content-Style-Type" content="text/css">
  <title></title>
  <meta name="Generator" content="Cocoa HTML Writer">
  <meta name="CocoaVersion" content="1187.34">
  <style type="text/css">
    p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Helvetica}
    p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Helvetica; color: #4183c4}
    p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 28.0px Helvetica; color: #4183c4; min-height: 34.0px}
    p.p4 {margin: 0.0px 0.0px 10.0px 0.0px; font: 28.0px Helvetica}
    p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 24.0px Helvetica; color: #4183c4; min-height: 29.0px}
    p.p6 {margin: 0.0px 0.0px 10.0px 0.0px; font: 24.0px Helvetica}
    p.p7 {margin: 0.0px 0.0px 15.0px 0.0px; font: 14.0px Helvetica}
    p.p8 {margin: 0.0px 0.0px 15.0px 0.0px; font: 14.0px Helvetica; min-height: 17.0px}
    p.p9 {margin: 0.0px 0.0px 10.0px 0.0px; font: 18.0px Helvetica}
    p.p10 {margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Monaco; background-color: #f8f8f8}
    p.p11 {margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Monaco; background-color: #f8f8f8; min-height: 17.0px}
    p.p12 {margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Monaco; color: #999988; background-color: #f8f8f8}
    p.p13 {margin: 0.0px 0.0px 15.0px 0.0px; font: 14.0px Helvetica; color: #777777}
    p.p14 {margin: 0.0px 0.0px 15.0px 0.0px; font: 13.0px Monaco; color: #777777; background-color: #f8f8f8}
    p.p15 {margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Monaco; color: #455588; background-color: #f8f8f8}
    p.p16 {margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Helvetica; min-height: 17.0px}
    li.li1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Helvetica}
    span.s1 {color: #4183c4}
    span.s2 {color: #455588}
    span.s3 {font: 12.0px Monaco; background-color: #f8f8f8}
    span.s4 {color: #000000}
    span.s5 {font: 14.0px Helvetica; background-color: transparent}
    span.s6 {color: #999988}
    ul.ul1 {list-style-type: disc}
  </style>
</head>
<body>
<p class="p1">N3490=12-0180</p>
<p class="p1">2012-10-31</p>
<p class="p1">Dave Abrahams</p>
<p class="p2"><a href="mailto:dave@boostpro.com">dave@boostpro.com</a></p>
<p class="p3"><b></b><br></p>
<p class="p4"><b>Controlling Argument-Dependent Lookup</b></p>
<p class="p5"><b></b><br></p>
<p class="p6"><b>Abstract:</b></p>
<p class="p7">In this paper, I present the two competing ideas about the nature of the ADL problem, identify one as important, and propose a feature that addresses it. I also propose an extension to that feature that extends proposal <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3418.pdf"><span class="s1">N3418</span></a>'s <a href="http://cpp-next.com/archive/2012/09/unifying-generic-functions-and-function-objects/comment-page-1"><span class="s1">unification</span></a> of functions, function templates, and function objects.</p>
<p class="p5"><b></b><br></p>
<p class="p6"><b>The Two Views</b></p>
<p class="p7">Previous attempts to "fix ADL" have centered around two proposals. The first, <a href="http://www.boostpro.com/writing/n1691.html"><span class="s1">Explicit Namespaces</span></a> by Dave Abrahams (full disclosure: me) sought to</p>
<ul class="ul1">
  <li class="li1">make it easy for programers to <b>control their use of ADL</b> and</li>
  <li class="li1">enable them to <b>express their intent to do so</b></li>
</ul>
<p class="p8"><br></p>
<p class="p7">The other one, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1893.pdf"><span class="s1">A Modest Proposal: Fixing ADL</span></a> by Herb Sutter, sought to change the rules of ADL so that it applies in fewer situations.</p>
<p class="p7">These two views were the source of ongoing confusion and disagreement until the Indiana committee meeting of August 2011, where Herb and I discussed the issue and realized we were solving different perceived problems.</p>
<p class="p9"><b>Herb's Scenario</b></p>
<p class="p7">The scenario Herb's proposal addresses is simple to describe, so I'll start with that one. Two conditions hold</p>
<ul class="ul1">
  <li class="li1">The programmer <b>intends to use ADL</b>, but</li>
  <li class="li1">ADL does not choose the expected overload</li>
</ul>
<p class="p8"><br></p>
<p class="p7">So far, I have not been able to find any evidence (not even the anecdotal kind) that this scenario is a real problem for anyone. Therefore, I'll let Herb argue for its importance, and move on to describe the problem I'm solving.</p>
<p class="p7">First, though, I note that changing the rules of ADL <i>will break code</i>, some of it silently. It is my understanding that in some cases the specific proposed change disables a technique currently used intentionally by libraries. Therefore, I suggest that before we take such an approach, we should be very sure that the costs of code breakage are more than balanced by real benefits.</p>
<p class="p9"><b>My Scenario</b></p>
<p class="p7">My proposal addresses the following scenario:</p>
<ul class="ul1">
  <li class="li1">The programmer <b>does not intend to use ADL</b></li>
  <li class="li1">ADL unexpectedly calls a function in some other namespace</li>
</ul>
<p class="p8"><br></p>
<p class="p7">This problem can arise in various circumstances, but the prototypical example looks something like this:</p>
<p class="p10">namespace A</p>
<p class="p10">{</p>
<p class="p10"><span class="Apple-converted-space">  </span><span class="s2">void</span> helper(some_type const&amp; x);</p>
<p class="p11"><br></p>
<p class="p10"><span class="Apple-converted-space">  </span><span class="s2">void</span> g(some_type x)</p>
<p class="p10"><span class="Apple-converted-space">  </span>{</p>
<p class="p10"><span class="Apple-converted-space">      </span>helper(x);</p>
<p class="p10"><span class="Apple-converted-space">  </span>}</p>
<p class="p10">}</p>
<p class="p8"><br></p>
<p class="p7">The problem only <i>manifests</i> when a namespace associated with <span class="s3">some_type</span> acquires its own <span class="s3">helper</span>. For example,</p>
<p class="p10">namespace B</p>
<p class="p10">{</p>
<p class="p10"><span class="Apple-converted-space">  </span>class <span class="s2">some_type</span> { ... };</p>
<p class="p11"><br></p>
<p class="p12"><span class="s4"><span class="Apple-converted-space">  </span></span>// Someone adds this overload</p>
<p class="p10"><span class="Apple-converted-space">  </span><span class="s2">void</span> helper(some_type&amp; x);</p>
<p class="p10">}</p>
<p class="p8"><br></p>
<p class="p7">If the programmer is lucky, she'll get a compiler error, but in this case she doesn't: <span class="s3">B::helper</span> silently "hijacks" the call made in <span class="s3">A::g</span>, because it is a slightly better match.</p>
<p class="p6"><b>Whose Fault Is It?</b></p>
<p class="p7"><b>Theory 1</b>: the author of <span class="s3">A</span> messed up. The argument for this theory is that the author of <span class="s3">A</span> should have known that any unqualified call is subject to ADL, and should therefore have called <span class="s3">A::helper</span> rather than simply <span class="s3">helper</span>.</p>
<p class="p7">While this argument is technically correct, I have a hard time blaming the author of <span class="s3">A</span>, for several reasons:</p>
<ul class="ul1">
  <li class="li1">adding qualification everywhere can make code quite ugly.</li>
  <li class="li1">unqualified calls are the most natural way to express the desire to call a function in the same scope. It would be perverse to blame the programmer for habitually and automatically using them.</li>
  <li class="li1">unqualified calls usually work when you test them. It's only later, as code is maintained, templates are instantiated with new parameters or libraries , that they can be a problem.</li>
  <li class="li1">ADL aside, C++ <i>and every other lexically-scoped language</i> find unqualified names in the nearest enclosing scope. To avoid this problem, you have to learn about ADL and keep it in mind—always.</li>
</ul>
<p class="p8"><b></b><br></p>
<p class="p7"><b>Theory 2</b>: the author of <span class="s3">B</span> messed up. After all, she knew that ADL was a problem, so she should have put <span class="s3">some_type</span> and <span class="s3">helper</span> in separate namespaces.</p>
<p class="p7">This argument, too, I find unconvincing. Creating special namespaces just to avoid ADL problems is tedious and ugly, and once again, to avoid the problem you have to learn about ADL and always keep it in mind. Furthermore, the author of <span class="s3">B</span> may actually <i>intend</i> <span class="s3">helper</span> to be called (but only called intentionally) via ADL.</p>
<p class="p6"><b>Is It Real?</b></p>
<p class="p7">Is this a real problem? Yes. In fact, even standard library authors, who are aware of the issue and are among our best C++ programmers, frequently use unqualified calls where they don't intend to activate ADL (references upon request).</p>
<p class="p7">Does it break code often? Probably not. However, the fact that the problem manifests infrequently just means there is less awareness: programmers are less likely to know how to avoid it or even how to fix it.</p>
<p class="p7">Can we solve it with more awareness? I don't think so. The better you understand this problem, the less fun it is to program in C++. Personally, I spend an inordinate amount of mental energy, which should go into solving real problems, trying to avoid writing code that could break in the field due to ADL.</p>
<p class="p6"><b>Therefore...</b></p>
<p class="p7">It should be fixed in the language.</p>
<p class="p6"><b>Proposed Changes</b></p>
<p class="p7">First, we provide a way to turn off ADL for non-operator names. I propose the following syntax, which affects the scope in which it is written, for the rest of the translation unit:</p>
<p class="p10">using = delete;</p>
<p class="p11"><br></p>
<p class="p13">| Note: if we wanted a way to turn off ADL for operators as well, we could use</p>
<p class="p14"><span class="s5">|<span class="Apple-converted-space"> </span></span> using operator = delete;</p>
<p class="p13">| but I'm not sure this capability is useful</p>
<p class="p8"><br></p>
<p class="p7">Then, we provide a way to turn on ADL selectively, for a given name. To enable ADL for <span class="s3">foo</span> in the current scope, I propose an <i>unqualified-using-declaration</i>:</p>
<p class="p10">using foo;</p>
<p class="p8"><br></p>
<p class="p7">Here's an example of how this capability might be used:</p>
<p class="p10">namespace algos</p>
<p class="p10">{</p>
<p class="p10"><span class="Apple-converted-space">  </span>using = delete;</p>
<p class="p11"><br></p>
<p class="p15"><span class="s4"><span class="Apple-converted-space">  </span>template &lt;class </span>RandomAccessIterator<span class="s4">&gt;</span></p>
<p class="p10"><span class="Apple-converted-space">  </span><span class="s2">void</span> reverse(RandomAccessIterator b, RandomAccessIterator e)</p>
<p class="p10"><span class="Apple-converted-space">  </span>{</p>
<p class="p12"><span class="s4"><span class="Apple-converted-space">      </span>using swap; </span>// find swap via ADL</p>
<p class="p10"><span class="Apple-converted-space">      </span>if (b == e) return;</p>
<p class="p10"><span class="Apple-converted-space">      </span>while(--e &gt; b)</p>
<p class="p10"><span class="Apple-converted-space">          </span>swap(*e, *b++);</p>
<p class="p10"><span class="Apple-converted-space">  </span>}</p>
<p class="p10">}</p>
<p class="p8"><br></p>
<p class="p7">The first <i>unqualified-using-declaration</i> in any scope turns off ADL for non-operator names, so that <span class="s3">using = delete</span> isn't needed. So:</p>
<p class="p10"><span class="s2">void</span> crazy_sort(std::vector&lt;X&gt;&amp; v)</p>
<p class="p10">{</p>
<p class="p12"><span class="s4"><span class="Apple-converted-space">    </span></span>// using = delete;<span class="Apple-converted-space">  </span>&lt;=== Not needed</p>
<p class="p12"><span class="s4"><span class="Apple-converted-space">    </span>using swap; <span class="Apple-converted-space">  </span></span>// find swap, and only swap, via ADL</p>
<p class="p12"><span class="s4"><span class="Apple-converted-space">    </span>using wiggle; </span>// find swap and wiggle via ADL</p>
<p class="p10"><span class="Apple-converted-space">    </span>...</p>
<p class="p10">}</p>
<p class="p8"><br></p>
<p class="p7">Lastly, as a way to extend the unification of function objects with functions, I propose that an <i>unqualified-using-declaration</i> should enable ADL to find not only functions, but function <i>objects</i> in associated namespaces. For example:</p>
<p class="p10">namespace X</p>
<p class="p10">{</p>
<p class="p10"><span class="Apple-converted-space">  </span>class <span class="s2">Foo</span> {...};</p>
<p class="p10"><span class="Apple-converted-space">  </span>auto bar = [](Foo a) { return a.bar(); }</p>
<p class="p10">}</p>
<p class="p11"><br></p>
<p class="p10">namespace Y</p>
<p class="p10">{</p>
<p class="p12"><span class="s4"><span class="Apple-converted-space">  </span>using bar; <span class="Apple-converted-space">      </span></span>// Find bar, including function objects, via ADL</p>
<p class="p10"><span class="Apple-converted-space">  </span><span class="s2">int</span> value = bar(X::Foo()); <span class="s6">// OK</span></p>
<p class="p10">}</p>
<p class="p5"><b></b><br></p>
<p class="p6"><b>Conclusion: Whither Modularity?</b></p>
<p class="p1">I define "modularity" as the ability to make changes in one part of the program without breaking the other parts. By this definition, ADL significantly weakens the modularity guarantees that namespaces were intended to offer (see D&amp;E §3.12, Relationship to Classic C). The <i>unqualified-using-declaration</i>, along with <span class="s3">using = delete</span>, allow us to reclaim modularity without losing the elegance of ADL where we really want it.</p>
<p class="p16"><br></p>
</body>
</html>
