2840. directory_iterator::increment is seemingly narrow-contract but marked noexcept

Section: 31.12.11.2 [fs.dir.itr.members], 31.12.12.2 [fs.rec.dir.itr.members] Status: Resolved Submitter: Tim Song Opened: 2016-12-09 Last modified: 2020-09-06

Priority: 2

View all other issues in [fs.dir.itr.members].

View all issues with Resolved status.

Discussion:

directory_iterator::increment and recursive_directory_iterator::increment are specified by reference to the input iterator requirements, which is narrow-contract: it has a precondition that the iterator is dereferenceable. Yet they are marked as noexcept.

Either the noexcept (one of which was added by LWG 2637) should be removed, or the behavior of increment when given a nondereferenceable iterator should be specified.

Currently, libstdc++ and MSVC report an error via the error_code argument for a nondereferenceable directory_iterator, while libc++ and boost::filesystem assert.

[2017-01-27 Telecon]

Priority 2; there are some problems with the wording in alternative B.

[2018-01-24 Tim Song comments]

LWG 3013 will remove this noexcept (for a different reason). The behavior of calling increment on a nondereferenceble iterator should still be clarified, as I was informed that LWG wanted it to be well-defined.

[2018-1-26 issues processing telecon]

Part A is already done by 3013.

Marshall to talk to Tim about Part B; it would be odd if operator++ was undefined behaviour, but increment on the same iterator returned an error

[2018-8-15 Offline discussions]

Tim and Marshall recommend NAD for about Part B

[2018-08-20 Batavia Issues processing]

Status to resolved.

Proposed resolution:

This wording is relative to N4618.

  1. Alternative A (remove the noexcept):

    1. Edit [fs.class.directory_iterator], class directory_iterator synopsis, as indicated:

      directory_iterator& operator++();
      directory_iterator& increment(error_code& ec) noexcept;
      
    2. Edit 31.12.11.2 [fs.dir.itr.members] before p10 as indicated:

      directory_iterator& operator++();
      directory_iterator& increment(error_code& ec) noexcept;
      

      -10- Effects: As specified for the prefix increment operation of Input iterators (24.2.3).

      -11- Returns: *this.

      -12- Throws: As specified in 27.10.7.

    3. Edit 31.12.12 [fs.class.rec.dir.itr], class recursive_directory_iterator synopsis, as indicated:

      recursive_directory_iterator& operator++();
      recursive_directory_iterator& increment(error_code& ec) noexcept;
      
    4. Edit 31.12.12.2 [fs.rec.dir.itr.members] before p23 as indicated:

      recursive_directory_iterator& operator++();
      recursive_directory_iterator& increment(error_code& ec) noexcept;
      

      -23- Effects: As specified for the prefix increment operation of Input iterators (24.2.3), except that: […]

      -24- Returns: *this.

      -25- Throws: As specified in 27.10.7.

  2. Alternative B (specify that increment reports an error if the iterator is not dereferenceable):

    1. Edit 31.12.11.2 [fs.dir.itr.members] p10 as indicated:

      directory_iterator& operator++();
      directory_iterator& increment(error_code& ec) noexcept;
      

      -10- Effects: As specified for the prefix increment operation of Input iterators (24.2.3), except that increment reports an error if *this is not dereferenceable.

      -11- Returns: *this.

      -12- Throws: As specified in 27.10.7.

    2. Edit 31.12.12.2 [fs.rec.dir.itr.members] p23 as indicated:

      recursive_directory_iterator& operator++();
      recursive_directory_iterator& increment(error_code& ec) noexcept;
      

      -23- Effects: As specified for the prefix increment operation of Input iterators (24.2.3), except that:

      • increment reports an error if *this is not dereferenceable.

      • If there are no more entries at the current depth, […]

      • Otherwise if […]

      -24- Returns: *this.

      -25- Throws: As specified in 27.10.7.