<html>

<head>
<meta http-equiv="Content-Language" content="en-us">
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Directory Entry Caching</title>
<style>
body
{
  font-family: arial, sans-serif;
  max-width: 6.75in;
  margin: 0px auto;
  font-size: 85%;
}
 ins  {background-color: #CCFFCC; text-decoration: none;}
 del  {background-color: #FFCACA; text-decoration: none;}
 pre  {background-color: #D7EEFF; font-size: 95%; font-family: "courier new", courier, serif;}
 code {font-family: "courier new", courier, serif;}
 table {font-size: 90%; border-collapse: collapse;}
</style>
</head>

<body>

<table>
<tr>
  <td align="left">Doc. no.:</td>
  <td align="left">P0317R1</td>
</tr>
<tr>
  <td align="left">Date:</td>
  <td align="left">
  <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%Y-%m-%d" startspan -->2016-10-15<!--webbot bot="Timestamp" endspan i-checksum="12049" --></td>
</tr>
<tr>
  <td align="left">Reply to:</td>
  <td align="left">Beman Dawes &lt;bdawes at acm dot org&gt;</tr>
<tr>
  <td align="left">Audience:</td>
  <td align="left">Library</td>
</tr>
</table>

<h1 align="center">Directory Entry Caching for Filesystem (R1)</h1>


<p align="center"><b>Fixing issue 
<a href="https://cplusplus.github.io/LWG/lwg-active.html#2663">2663</a>, <i>Enable efficient retrieval 
of file size from <code>directory_entry</code><br> </i>and issue
<a href="http://cplusplus.github.io/LWG/lwg-active.html#2677">2677</a>, <i>
<code>directory_entry::status</code> is not allowed to be cached ...</i></b></p>


  <p style="margin-left:20%; margin-right:20%;">This paper provides a solution 
  to the problem of efficiently caching state information obtained during 
  directory iteration.</p>


  <p style="margin-left:20%; margin-right:20%;">The proposal has been 
  implemented. Guidance 
  is provided for users on how to use or not use cached information as desired, without exposing to the user 
  whether information is actually cached. The proposal allows the user to write code that 
  is fully portable between&nbsp;implementations that cache or do not cache.</p>


  <h2>Background</h2>

  <p>Directory iteration in real-world operating systems always returns directory 
  state information containing at least the file name. POSIX has an 
  option to also return file status, but not all popular distributions implement this. Windows always 
  returns file status, 
  file size, and last modification date. Accessing this additional state from the directory entry is much more efficient than re-accessing 
  the file system to obtain it. Users know this and expect the standard library 
  filesystem to deliver the same efficiency.</p>

  <p>The initial filesystem TS proposal and the Boost 
  Filesystem implementation limited the additional state stored by class
  <code>directory_entry</code> to the regular status and symlink status, since these were the 
  only additional elements common to several operating systems. The caching of 
  this additional information was described using mutable exposition-only 
  data members. The LWG removed the mutable members and associated caching 
  wording because mutable members are problematic and race prone in 
  multi-threaded environments. The original design also exposed too many implementation 
  details and was not easily extendible to additional cache information such as 
  file size and last write timestamp.</p>

  <p>When <code>directory_entry</code> caching was removed from the TS, the LWG 
  promised to revisit the issue when Filesystem was added to the standard. Two 
  issues where subsequently filed that remind us of that promise.</p>

  <blockquote>

  <p>LWG issue <a href="http://cplusplus.github.io/LWG/lwg-active.html#2663">2663</a>, <i>Enable efficient retrieval of file size from </i><code><i>directory_entry</i></code>, 
  requests that for Windows caching be extended to file size.</p>

  <p>LWG issue
<a href="http://cplusplus.github.io/LWG/lwg-active.html#2677">2677</a>, <i>
<code>directory_entry::status</code> is not allowed to be cached as a 
  quality-of-implementation issue</i>, requests the reinstatement of permission 
  for implementations to cache directory entry information.</p>

  </blockquote>

  <p>The Boost Filesystem library has implemented directory entry caching for 
  many years. That implementation has been updated to conform to this proposal, 
  and is passing its test suite. It will ship to users later this year. </p>

  <h2>Design decisions</h2>

  <h3>Add cache <code>refresh()</code> functions</h3>

  <p>The original TS design conflated the observer functions that access cached 
  state information with refreshing the cached state. Since refreshing the 
  cached state is non-const, the cached member data had to be mutable and that 
  was unacceptable. This proposal provides separate 
  non-const <code>refresh</code> functions that are called by all other 
  non-const functions that modify the stored path, ensuring cache integrity. The
  <code>refresh</code> functions can be called by users if desired to refresh 
  stale cached data. With the separation of refresh and observer functionality, the  
  observer functions become truly const.</p>

  <h3>Provide observer functions for future needs</h3>

  <p>During LEWG discussions in Oulu, Geoffrey Romer suggested providing 
  observer functions for attributes beyond those currently supported by 
  real-world file systems. This has the effect of future-proofing <code>
  directory_entry</code> as file systems evolve. It also sparked the realization 
  that the <code>is_</code>* family of filesystem query functions could be 
  supported efficiently in a user-convenient way.</p>

  <h2>Revision History</h2>

  <p><b>R1 - pre-Issaquah:</b></p>

  <blockquote>

  <p><b>Changes requested in Oulu</b></p>

  </blockquote>

  <ul>
    <li>Select the first of the two approaches proposed in R0, 
    per Oulu LEWG vote, enhanced with Geoffrey Romer&#39;s suggestion to provide observer functions 
    for future needs, per Oulu LEWG vote.</li>
    <li>Change &quot;for&quot; to &quot;such as&quot; in [class.directory_entry], per 
    Oulu LWG.</li>
    <li>Use <code>endl</code> rather than <code>&#39;\n&#39;</code> in example, per 
    Oulu LWG.</li>
    <li>Clarify the relationship between directory iteration (which stores the 
    cached values) and directory entries (which provide observers for the cached 
    values and are where the cached values are stored). In reviewing the Oulu LWG 
    discussion it became obvious that the split in caching responsibilities between the
    <code>directory_entry</code> and <code>directory_iteration</code> was not 
    adequately described.</li>
    <li>Modify the [class.directory_entry] example to use explicit call to <code>
    refresh()</code>.</li>
    <li>Reviewed all <code>directory_entry</code> member functions, per Oulu LWG, and 
    add wording to <i>Returns</i> or other elements when needed to specify 
    what happens when an error occurs. Note: If a <i>Returns</i> element is 
    specified as simply calling a function whose returned value is 
    well-specified as to the value returned on an error, there is no need to say 
    anything further.</li>
    <li>Add an additional signature taking an <code>error_code&amp;</code> 
    argument to several functions, and updated specifications accordingly, per 
    Oulu 
    LWG.</li>
    <li>Add Acknowledgements.</li>
</ul>

  <blockquote>
    <p><b>Changes requested in Chicago</b></p>
</blockquote>

  <ul>
    <li>Fix mispelling and spurious backslash per Walter Brown.</li>
    <li>After several flip-flops, Chicago LWG settles on &quot;// exposition only&quot; 
    for &quot;<ins><code>friend class directory_iterator;&nbsp; // exposition only</code></ins>&quot;.</li>
    <li>Strike &quot;() and change &quot;the&quot; to &quot;any&quot; to now read <ins>
    &quot;any <code>directory_entry</code> <code>refresh</code> function&quot;</ins> in 
    the new paragraph being added to [class.directory_iterator], per Chicago LWG.</li>
    <li>Add [directory_entry.obs] introductory sentence per Chicago LWG.</li>
</ul>

  <p><b>R0 - pre-Oulu:</b> Initial proposal providing two possible approaches to 
  directory entry caching.</p>

  <h2>Acknowledgements</h2>

  <p>Thanks to the LEWG and LWG for their many corrections and helpful 
  suggestions. Thanks to Daniel Krügler for his 
  pre-Chicago wording review. Special thanks to Geoffrey Romer for suggesting 
  observer functions to meet future needs, resolving a major concern.</p>

  <h1>Proposed wording</h1>

  <p><i><span style="background-color: #CCCCCC">Changes are relative to N4606.</span></i></p>

  <h2>27.10.12 Class <code>directory_entry</code> [class.directory_entry]</h2>
</h2>



<pre>namespace std::filesystem {
  class directory_entry {
  public:
    // <a href="#directory_entry-constructors-1">constructors</a> and destructor
    directory_entry() noexcept = default;
    directory_entry(const directory_entry&amp;) = default;
    directory_entry(directory_entry&amp;&amp;) noexcept = default;
    explicit directory_entry(const path&amp; p);
    <ins>directory_entry(const path&amp; p, error_code& ec);</ins>
   ~directory_entry();

    // assignments
    directory_entry&amp; operator=(const directory_entry&amp;) = default;
    directory_entry&amp; operator=(directory_entry&amp;&amp;) noexcept = default;

    // <a href="#directory_entry-modifiers-1">modifiers</a>
    void assign(const path&amp; p);
    <ins>void assign(const path&amp; p, error_code&amp; ec);</ins>
    void replace_filename(const path&amp; p);
    <ins>void replace_filename(const path&amp; p, error_code&amp; ec);</ins>
    <ins>void refresh();</ins>
    <ins>void refresh(error_code&amp; ec) noexcept;</ins>

    // <a href="#directory_entry-observers-1">observers</a>
    const path&amp;  path() const noexcept;
    operator const path&amp;() const noexcept;
    <ins>bool exists() const;</ins>
    <ins>bool exists(error_code&amp; ec) const noexcept;</ins>
    <ins>bool is_block_file() const;</ins>
    <ins>bool is_block_file(error_code&amp; ec) const noexcept;</ins>
    <ins>bool is_character_file() const;</ins>
    <ins>bool is_character_file(error_code&amp; ec) const noexcept;</ins>
    <ins>bool is_directory() const;</ins>
    <ins>bool is_directory(error_code&amp; ec) const noexcept;</ins>
    <ins>bool is_fifo() const;</ins>
    <ins>bool is_fifo(error_code&amp; ec) const noexcept;</ins>
    <ins>bool is_other() const;</ins>
    <ins>bool is_other(error_code&amp; ec) const noexcept;</ins>
    <ins>bool is_regular_file() const;</ins>
    <ins>bool is_regular_file(error_code&amp; ec) const noexcept;</ins>
    <ins>bool is_socket() const;</ins>
    <ins>bool is_socket(error_code&amp; ec) const noexcept;</ins>
    <ins>bool is_symlink() const;</ins>
    <ins>bool is_symlink(error_code&amp; ec) const noexcept;</ins>
    <ins>uintmax_t file_size() const;</ins>
    <ins>uintmax_t file_size(error_code& ec) const noexcept;</ins>
    <ins>uintmax_t hard_link_count() const;</ins>
    <ins>uintmax_t hard_link_count(error_code&amp; ec) const noexcept;</ins>
    <ins>file_time_type last_write_time() const;</ins> 
    <ins>file_time_type last_write_time(error_code& ec) const noexcept;</ins> 
    file_status status() const;
    file_status status(error_code&amp; ec) const noexcept;
    file_status symlink_status() const;
    file_status symlink_status(error_code&amp; ec) const noexcept;

    bool operator&lt; (const directory_entry&amp; rhs) const noexcept;
    bool operator==(const directory_entry&amp; rhs) const noexcept;
    bool operator!=(const directory_entry&amp; rhs) const noexcept;
    bool operator&lt;=(const directory_entry&amp; rhs) const noexcept;
    bool operator&gt; (const directory_entry&amp; rhs) const noexcept;
    bool operator&gt;=(const directory_entry&amp; rhs) const noexcept;
  private:
    path   pathobject; // exposition only
    <ins>friend class directory_iterator;  // exposition only</ins>
  };

}</pre>

<p>A <code>directory_entry</code> object stores a <code>path</code> object <ins>
and may store additional objects for file attributes such as hard link count, 
status, symlink status, file size, and last write time.</ins></p>
<p><ins>Implementations are  encouraged to store  such 
additional file attributes during directory iteration if their values are available and storing 
the values would 
allow the implementation to eliminate file system accesses by <code>directory_entry</code> 
observer functions ([fs.op.funcs]). Such stored file attribute values are said to be
<i>cached</i>.</ins></p>
<p><ins>[<i>Note:</i> For purposes of exposition, class <code>directory_iterator</code> ([class.directory_iterator]) 
is shown above as a friend of class <code>directory_entry</code>. Friendship 
allows the <code>directory_iterator</code> implementation to cache already 
available attribute values directly into a <code>directory_entry</code> object 
without the cost of an unneeded call to <code>refresh()</code>.&nbsp; —<i>end 
note</i>]</ins></p>
<blockquote>
<p><ins>[<i>Example: </i></ins></p>
<pre><ins>using namespace std::filesystem;

// use possibly cached last write time to minimize disk accesses
for (auto&& x : directory_iterator("."))
{
  std::cout << x.path() << " " << x.last_write_time() << std::endl;
}

// call refresh() to refresh a stale cache
for (auto&& x : directory_iterator("."))
{
  lengthy_function(x.path());  // cache becomes stale
  x.refresh();
  std::cout << x.path() << " " << x.last_write_time() << std::endl;
}</ins></pre>
<p><ins>On implementations that do not cache the last write time, both loops will 
result in a potentially expensive call to the <code>
std::filesystem::last_write_time</code> function.</ins></p>
<p><ins>On implementations that do cache the last write time, the first loop will use 
the cached value and so will not result in a potentially expensive call to the
<code>std::filesystem::last_write_time</code> function.</ins></p>
<p><ins>The code is portable to any implementation, regardless of whether or not it 
employs caching.</ins></p>
<p><ins><i>&nbsp;</i>—<i>end 
example</i>]</ins></p>
</blockquote>
<h3>27.10.12.1 <a name="directory_entry-constructors-1"><code>directory_entry</code> 
constructors </a>[directory_entry.cons] </h3>
<pre>explicit directory_entry(const path&amp; p);
<ins>directory_entry(const path&amp; p, error_code& ec);</ins></pre>
<blockquote>
  <p><i>Effects: </i>Constructs an object of type <code>directory_entry</code><ins>, 
  then <code>refresh()</code>or <code>
  refresh(ec)</code>, respectively</ins>.
  </p>
  <p><i>Postcondition:</i> <code>path() == p</code><ins> if no error occurs, otherwise 
  <code>path() == std::filesystem::path()</code></ins>.</p>
  <p><ins><i>Throws:</i> As specified in Error 
  reporting ([fs.err.report]).</ins></p>
</blockquote>
<h3>27.10.12.2 <a name="directory_entry-modifiers-1"><code>directory_entry</code> 
modifiers </a>[directory_entry.mods] </h3>
<pre>void assign(const path&amp; p);
<ins>void assign(const path&amp; p, error_code&amp; ec);</ins></pre>
<blockquote>
  <p><ins><i>Effects:</i> Equivalent to <code>pathobject = p</code>, then <code>refresh()</code>or <code>
  refresh(ec)</code>, respectively. If an error occurs the value of any cached 
  attributes is unspecified</ins>.</p>
  <p><del><i>Postcondition:</i> <code>path() == p</code>.</del></p>
  <p><ins><i>Throws:</i> As specified in Error 
  reporting ([fs.err.report]).</ins> </p>
</blockquote>
<pre>void replace_filename(const path&amp; p);
<ins>void replace_filename(const path&amp; p, error_code&amp; ec);</ins></pre>
<blockquote>
  <p><ins><i>Effects:</i> Equivalent to <code>pathobject = pathobject.parent_path()/ p</code>, then <code>refresh()</code>or <code>
  refresh(ec)</code>, respectively. If an error occurs&nbsp; the value of any cached 
  attributes is unspecified.</ins></p>
  <p><del><i>Postcondition:</i> <code>path() == x.parent_path() / p</code> where <code>x</code> is the value of <code>path()</code> before the function is 
  called.</del></p>
<p><ins><i>Throws:</i> As specified in Error 
  reporting ([fs.err.report]).</ins></p>
</blockquote>
<pre><ins>void refresh();</ins>
<ins>void refresh(error_code&amp; ec) noexcept;</ins></pre>
<blockquote>
<p><ins><i>Effects:</i> Stores the current value for any cached attribute values of the 
file <code>p</code> resolves to. If an error occurs, an error is reported
(27.10.7 [fs.err.report]) and the value of any cached attributes is unspecified.</ins></p>
<p><ins><i>Throws:</i> As specified in Error 
  reporting ([fs.err.report]).</ins> </p>
<p><ins>[<i>Note</i>: Implementations of <code>directory_iterator</code> [class.directory_iterator] are prohibited from 
directly or indirectly calling the <code>refresh</code> function since it must 
access the external file system, and the objective of caching is to avoid 
unnecessary file system accesses.&nbsp; &mdash;<i>end note</i>]</ins></p>
</blockquote>
<h3>27.10.12.3 <a name="directory_entry-observers-1"><code>directory_entry</code> observers
</a>[directory_entry.obs] </h3>
<p><ins><code>directory_entry</code> observers described below as returning a 
function with an unqualified name shall behave as if calling the namespace <code>
std::filesystem</code> non-member function of that name.</ins></p>
<pre>const path&amp; path() const noexcept;
operator const path&amp;() const noexcept;</pre>
<blockquote>
  <p><i>Returns:</i> <code>pathobject</code> </p>
</blockquote>

<pre><ins>bool exists() const;</ins>
<ins>bool exists(error_code&amp; ec) const noexcept;</ins></pre>
<blockquote>
<p><ins><i>Returns:</i> <code>exists(this->status())</code> or
 <code>exists(this->status(ec))</code>, respectively.</ins></p>
<p><ins><i>Throws:</i> As specified in Error 
  reporting ([fs.err.report]).</ins> </p>
</blockquote>

<pre><ins>bool is_block_file() const;</ins>
<ins>bool is_block_file(error_code&amp; ec) const noexcept;</ins></pre>
<blockquote>
<p><ins><i>Returns:</i> <code>is_block_file(this->status())</code> or
 <code>is_block_file(this->status(ec))</code>, respectively.</ins></p>
<p><ins><i>Throws:</i> As specified in Error 
  reporting ([fs.err.report]).</ins> </p>
</blockquote>

<pre><ins>bool is_character_file() const;</ins>
<ins>bool is_character_file(error_code&amp; ec) const noexcept;</ins></pre>
<blockquote>
<p><ins><i>Returns:</i> <code>is_character_file(this->status())</code> or
 <code>is_character_file(this->status(ec))</code>, respectively.</ins></p>
<p><ins><i>Throws:</i> As specified in Error 
  reporting ([fs.err.report]).</ins> </p>
</blockquote>

<pre><ins>bool is_directory() const;</ins>
<ins>bool is_directory(error_code&amp; ec) const noexcept;</ins></pre>
<blockquote>
<p><ins><i>Returns:</i> <code>is_directory(this->file_status())</code> or
 <code>is_directory(this->file_status(ec))</code>, respectively.</ins></p>
<p><ins><i>Throws:</i> As specified in Error 
  reporting ([fs.err.report]).</ins> </p>
</blockquote>

<pre><ins>bool is_fifo() const;</ins>
<ins>bool is_fifo(error_code&amp; ec) const noexcept;</ins></pre>
<blockquote>
<p><ins><i>Returns:</i> <code>is_fifo(this->status())</code> or
 <code>is_fifo(this->status(ec))</code>, respectively.</ins></p>
<p><ins><i>Throws:</i> As specified in Error 
  reporting ([fs.err.report]).</ins> </p>
</blockquote>

<pre><ins>bool is_other() const;</ins>
<ins>bool is_other(error_code&amp; ec) const noexcept;</ins></pre>
<blockquote>
<p><ins><i>Returns:</i> <code>is_other(this->status())</code> or
 <code>is_other(this->status(ec))</code>, respectively.</ins></p>
<p><ins><i>Throws:</i> As specified in Error 
  reporting ([fs.err.report]).</ins> </p>
</blockquote>

<pre><ins>bool is_regular_file() const;</ins>
<ins>bool is_regular_file(error_code&amp; ec) const noexcept;</ins></pre>
<blockquote>
<p><ins><i>Returns:</i> <code>is_regular_file(this->status())</code> or
 <code>is_regular_file(this->status(ec))</code>, respectively.</ins></p>
<p><ins><i>Throws:</i> As specified in Error 
  reporting ([fs.err.report]).</ins> </p>
</blockquote>

<pre><ins>bool is_socket() const;</ins>
<ins>bool is_socket(error_code&amp; ec) const noexcept;</ins></pre>
<blockquote>
<p><ins><i>Returns:</i> <code>is_socket(this->status())</code> or
 <code>is_socket(this->status(ec))</code>, respectively.</ins></p>
<p><ins><i>Throws:</i> As specified in Error 
  reporting ([fs.err.report]).</ins> </p>
</blockquote>

<pre><ins>bool is_symlink() const;</ins>
<ins>bool is_symlink(error_code&amp; ec) const noexcept;</ins></pre>
<blockquote>
<p><ins><i>Returns:</i> <code>is_symlink(this->symlink_status())</code> or
 <code>is_symlink(this->symlink_status(ec))</code>, respectively.</ins></p>
<p><ins><i>Throws:</i> As specified in Error 
  reporting ([fs.err.report]).</ins> </p>
</blockquote>

<pre><ins>uintmax_t file_size() const;</ins>
<ins>uintmax_t file_size(error_code& ec) const noexcept;</ins></pre>
<blockquote>
<p><ins><i>Returns:</i> If cached, the file size attribute value. Otherwise,
<code>file_size(path())</code> or <code>file_size(path(), ec)</code>, respectively.</ins></p>
<p><ins><i>Throws:</i> As specified in Error 
  reporting ([fs.err.report]).</ins> </p>
</blockquote>

<pre><ins>uintmax_t hard_link_count() const;</ins>
<ins>uintmax_t hard_link_count(error_code&amp; ec) const noexcept;</ins></pre>
<blockquote>
<p><ins><i>Returns:</i> If cached, the hard link count attribute value. Otherwise,
<code>hard_link_count(path())</code> or <code>hard_link_count(path(), ec)</code>, respectively.</ins></p>
<p><ins><i>Throws:</i> As specified in Error 
  reporting ([fs.err.report]).</ins> </p>
</blockquote>

<pre><ins>file_time_type last_write_time() const;</ins> 
<ins>file_time_type last_write_time(error_code& ec) const noexcept;</ins></pre> 
<blockquote>
<p><ins><i>Returns:</i> If cached, the last write time attribute value. 
Otherwise, <code>last_write_time(path())</code> or <code>last_write_time(path(), ec)</code>, respectively.</ins></p>
<p><ins><i>Throws:</i> As specified in Error 
  reporting ([fs.err.report]).</ins> </p>
</blockquote>

<pre>file_status status() const;
file_status status(error_code&amp; ec) const noexcept;</pre>
<blockquote>
  <p><i>Returns:</i> <ins>If cached, the status 
  attribute value. 
  Otherwise, </ins> <code>status(path())</code> or <code>status(path(), ec)</code>, 
  respectively.</p>
  <p para_num="5"><i>Throws:</i> As specified in Error 
  reporting ([fs.err.report]).</p>
</blockquote>
<pre para_num="6">file_status symlink_status() const;
file_status symlink_status(error_code&amp; ec) const noexcept;</pre>
<blockquote>
   <p para_num="7"><i>Returns:</i> <ins>If cached, the&nbsp; symlink status attribute value. Otherwise, </ins> <code>symlink_status(path())</code> or <code>
   symlink_status(path(), ec)</code>, respectively.</p>
  <p para_num="8"><i>Throws:</i> As specified in Error 
  reporting ([fs.err.report]).</p>
</blockquote>


<pre para_num="9">bool operator==(const directory_entry&amp; rhs) const noexcept;</pre>
<blockquote>
  <p><i>Returns:</i> <code>pathobject == rhs.pathobject</code>. </p>
</blockquote>
<pre>bool operator!=(const directory_entry&amp; rhs) const noexcept;</pre>
<blockquote>
  <p><i>Returns:</i> <code>pathobject != rhs.pathobject</code>. </p>
</blockquote>
<pre>bool operator&lt; (const directory_entry&amp; rhs) const noexcept;</pre>
<blockquote>
  <p><i>Returns:</i> <code>pathobject &lt; rhs.pathobject</code>. </p>
</blockquote>
<pre>bool operator&lt;=(const directory_entry&amp; rhs) const noexcept;</pre>
<blockquote>
  <p><i>Returns:</i> <code>pathobject &lt;= rhs.pathobject</code>. </p>
</blockquote>
<pre>bool operator&gt; (const directory_entry&amp; rhs) const noexcept;</pre>
<blockquote>
  <p><i>Returns:</i> <code>pathobject &gt; rhs.pathobject</code>. </p>
</blockquote>
<pre>bool operator&gt;=(const directory_entry&amp; rhs) const noexcept;</pre>
<blockquote>
  <p para_num="20"><i>Returns:</i> <code>pathobject &gt;= rhs.pathobject</code>.</blockquote>


  <h3 para_num="20">&nbsp;7.10.13 Class <code>directory_iterator</code> [class.directory_iterator]</h3>
  <p>An object of type <code>directory_iterator</code> provides an iterator for 
  a sequence of <code>directory_entry</code> elements
  representing the <del>files</del> <ins>path and any cached attribute values ([class.directory_entry]) for each file</ins> in a directory. [ <i>Note:</i> For iteration into 
  sub-directories, see class <code>recursive_directory_iterator</code> (27.10.14). —<i>end note</i> 
  ]<p>
<span style="font-style: italic; background-color: #CCCCCC">Insert a new 
paragraph before the current note that begins at paragraph 9:</span><p dir="ltr"><ins>
Constructors and non-const <code>directory_iterator</code> member 
functions shall store the cached attribute values, if any, described in ([class.directory_entry]) 
in the <code>directory_entry</code> element returned by <code>operator*()</code>.&nbsp; <code>
directory_iterator</code> member functions shall not directly or indirectly call 
any <code>directory_entry</code> <code>refresh</code> function.[<i>Note:</i> The exact mechanism 
for storing cached attribute values is not exposed to users.&nbsp; For 
exposition class <code>directory_iterator</code> is shown in [class.directory_entry] as a friend of class 
<code>directory_entry</code>. &mdash;<i>end 
note</i>]</ins><hr>

    <h2>Note for implementors</h2>

    <p>For Windows, <code>directory_entry</code> information is obtained during 
    directory iteration by calling function
      <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa364418(v=vs.85).aspx">
      FindFirstFile</a>,
      <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa364419(v=vs.85).aspx">
      FindFirstFileEx</a>, 
      or 
      <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa364428(v=vs.85).aspx">
      FindNextFile</a>, and can be refreshed by calling function
      <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa364952(v=vs.85).aspx">
      GetFileInformationByHandle</a> or
    <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa364946(v=vs.85).aspx">
    GetFileAttributesEx</a>.</p>

    <p>For some POSIX-like systems, such as
    <a href="http://man7.org/linux/man-pages/man3/readdir.3.html">Linux</a> and 
    some BSD-based distributions, glibc versions since 2.19 may support an 
    additional <code>struct dirent</code> field named <code>d_type</code> 
    &quot;making it possible to avoid the expense of calling <code>lstat</code>&quot;. 
    POSIX specifies that the macro <code>_DIRENT_HAVE_D_TYPE</code> is defined 
    if <code>d_type</code> is present.</p>


  <h2><a name="References">References</a></h2>


  <p>Issue 2663, <i>Enable efficient retrieval of file size from directory_entry</i>,<br>
  <a href="https://cplusplus.github.io/LWG/lwg-active.html#2663">
  cplusplus.github.io/LWG/lwg-active.html#2663</a></p>


  <p>Issue 2677, <i><code>directory_entry::status</code> is not allowed to be 
  cached as a quality-of-implementation issue</i>,<br>
  <a href="https://cplusplus.github.io/LWG/lwg-active.html#2663">
  cplusplus.github.io/LWG/lwg-active.html#2677</a></p>

<p>N4582, <i>Working Draft, Standard for Programming Language C++, 2016</i>,<br>
<a class="uri" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4582.pdf">www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4582.pdf</a></p>

<p>N4100, <i>Programming Languages — C++ — File System Technical Specification, 
2014</i>,<br>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4100.pdf" class="uri">
www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4100.pdf</a></p>
<p> <i>Boost Filesystem Library, V3</i>, 2015,<br>
<a href="https://www.boost.org/doc/libs/1_60_0/libs/filesystem/doc/index.htm" class="uri">
www.boost.org/doc/libs/1_60_0/libs/filesystem/doc/index.htm</a></p>

  <hr>

<p>&nbsp;</p>

</body>
</html>