<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 3326: enable_view has false positives</title>
<meta property="og:title" content="Issue 3326: enable_view has false positives">
<meta property="og:description" content="C++ library issue. Status: C++20">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue3326.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#C++20">C++20</a> status.</em></p>
<h3 id="3326"><a href="lwg-defects.html#3326">3326</a>. <code>enable_view</code> has false positives</h3>
<p><b>Section:</b> 25.4.5 <a href="https://wg21.link/range.view">[range.view]</a> <b>Status:</b> <a href="lwg-active.html#C++20">C++20</a>
 <b>Submitter:</b> Germany <b>Opened:</b> 2019-11-06 <b>Last modified:</b> 2021-02-25</p>
<p><b>Priority: </b>0
</p>
<p><b>View all other</b> <a href="lwg-index.html#range.view">issues</a> in [range.view].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++20">C++20</a> status.</p>
<p><b>Discussion:</b></p>
<p><b>Addresses <a href="https://github.com/cplusplus/nbballot/issues/278">DE 282</a></b></p>

<p>
"Since the difference between range and view is largely semantic, the
two are differentiated with the help of <code>enable_view</code>." (&sect;3)
<p/>
<code>enable_view</code> is designed as on opt-in trait to specify that a type is a
view. It defaults to true for types derived from <code>view_base</code> (&sect;4.2) which
is clearly a form of opt-in. But it also employs a heuristic assuming that anything with 
<code>iterator == const_iterator</code> is also view (&sect;4.3).
<p/>
This is a very poor heuristic, the same paragraph already needs to define six
exceptions from this rule for standard library types (&sect;4.2).
<p/>
Experience in working with range-v3 has revealed multiple of our own library types as being 
affected from needing to opt-out from the "auto-opt-in", as well. This is counter-intuitive: 
something that was never designed to be a view shouldn't go through hoops so that it isn't
treated as a view.
<p/>
Proposed change:
</p>
<p>
Make <code>enable_view</code> truly be opt-in by relying only on explicit specialisation or 
inheritance from <code>view_base</code>. This means removing 24.4.4 &sect;4.2 - &sect;4.4 and 
introducing new &sect;4.2 "Otherwise, false".
<p/>
Double-check if existing standard library types like <code>basic_string_view</code> and <code>span</code> 
need to opt-in to being a view now.
</p>
<p>
<b>Casey Carter:</b>
<p/>
<code>enable_view</code> (25.4.5 <a href="https://wg21.link/range.view">[range.view]</a>) is designed as on opt-in trait to specify that a type 
is a view. It defaults to <code>true</code> for types derived from <code>view_base</code> &mdash; which is a 
form of opt-in &mdash; and it also employs a heuristic. Unfortunately, the heuristic has false positives. 
The working draft itself includes six exceptions to the heuristic for standard library types. Since 
false positives are much more problematic for users than false negatives, we should eliminate the heuristic.
</p>
<p><i>[2019-11 Status to Ready during Wednesday night issue processing in Belfast.]</i></p>



<p id="res-3326"><b>Proposed resolution:</b></p>
<p>This wording is relative to <a href="https://wg21.link/n4835">N4835</a>.</p>

<ol>
<li><p>Modify 25.4.5 <a href="https://wg21.link/range.view">[range.view]</a> as indicated:</p>

<blockquote>
<pre>
template&lt;class T&gt;
  inline constexpr bool enable_view = <del><i>see below</i></del><ins>derived_from&lt;T, view_base&gt;</ins>;
</pre>
<blockquote>
<p>
<del>-4- <i>Remarks:</i> For a type <code>T</code>, the default value of <code>enable_view&lt;T&gt;</code> is:</del>
<ol style="list-style-type: none">
<li><p><del>(4.1) &mdash; If <code>derived_from&lt;T, view_base&gt;</code> is <code>true</code>, 
<code>true</code>.</del></p></li>
<li><p><del>(4.2) &mdash; Otherwise, if <code>T</code> is a specialization of class template 
<code>initializer_list</code> (17.11 <a href="https://wg21.link/support.initlist">[support.initlist]</a>), <code>set</code> (23.4.6 <a href="https://wg21.link/set">[set]</a>),
<code>multiset</code> (23.4.7 <a href="https://wg21.link/multiset">[multiset]</a>), <code>unordered_set</code> (23.5.6 <a href="https://wg21.link/unord.set">[unord.set]</a>), 
<code>unordered_multiset</code> (23.5.7 <a href="https://wg21.link/unord.multiset">[unord.multiset]</a>), or <code>match_results</code>
(28.6.9 <a href="https://wg21.link/re.results">[re.results]</a>), <code>false</code>.</del></p></li>
<li><p><del>(4.3) &mdash; Otherwise, if both <code>T</code> and <code>const T</code> model <code>range</code> and 
<code>range_reference_t&lt;T&gt;</code> is not the same type as <code>range_reference_t&lt;const T&gt;</code>, 
<code>false</code>. [<i>Note:</i> Deep <code>const</code>-ness implies element ownership, whereas shallow const-ness 
implies reference semantics. &mdash; <i>end note</i>]</del></p></li>
<li><p><del>(4.4) &mdash; Otherwise, true.</del></p></li>
</ol>
</p>
</blockquote>
</blockquote>
</li>

<li><p>Modify 27.3.2 <a href="https://wg21.link/string.view.synop">[string.view.synop]</a>, header <code>&lt;string_view&gt;</code> synopsis, as indicated:</p>

<blockquote>
<pre>
namespace std {
  <i>// 27.3.3 <a href="https://wg21.link/string.view.template">[string.view.template]</a>, class template basic_string_view</i>
  template&lt;class charT, class traits = char_traits&lt;charT&gt;&gt;
  class basic_string_view;
  
  <ins>template&lt;class charT, class traits&gt;
    inline constexpr bool ranges::enable_view&lt;basic_string_view&lt;charT, traits&gt;&gt; = true;</ins>
    
  [&hellip;]
}
</pre>
</blockquote>
</li>

<li><p>Modify 23.7.2.1 <a href="https://wg21.link/span.syn">[span.syn]</a>, header <code>&lt;span&gt;</code> synopsis, as indicated:</p>

<blockquote>
<pre>
namespace std {
  <i>// constants</i>
  inline constexpr size_t dynamic_extent = numeric_limits&lt;size_t&gt;::max();
  
  <i>// 23.7.2.2 <a href="https://wg21.link/views.span">[views.span]</a>, class template span</i>
  template&lt;class ElementType, size_t Extent = dynamic_extent&gt;
  class span;
    
  <ins>template&lt;class ElementType, size_t Extent&gt;
    inline constexpr bool ranges::enable_view&lt;span&lt;ElementType, Extent&gt;&gt; = Extent == 0 || 
      Extent == dynamic_extent;</ins>
    
  [&hellip;]
}
</pre>
</blockquote>
</li>

<li><p>Modify  [range.split.outer.value], class <code>split_view::outer_iterator::value_type</code>
synopsis, as indicated:</p>

<blockquote class="note">
<p>
[<i>Drafting note:</i> The following applies the proposed wording for LWG <a href="lwg-defects.html#3276" title="Class split_view::outer_iterator::value_type should inherit from view_interface (Status: C++20)">3276</a><sup><a href="https://cplusplus.github.io/LWG/issue3276" title="Latest snapshot">(i)</a></sup>]
</p>
</blockquote>

<blockquote>
<pre>
namespace std::ranges {
  template&lt;class V, class Pattern&gt;
  template&lt;bool Const&gt;
  struct split_view&lt;V, Pattern&gt;::outer_iterator&lt;Const&gt;::value_type 
    <ins>: view_interface&lt;value_type&gt;</ins> {
  private:
    outer_iterator i_ = outer_iterator(); <i>// exposition only</i>
  public:
    value_type() = default;
    constexpr explicit value_type(outer_iterator i);

    constexpr inner_iterator&lt;Const&gt; begin() const;
    constexpr default_sentinel_t end() const;
  };
}
</pre>
</blockquote>
</li>

</ol>





</body>
</html>
