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

Section: 30.11.12.1 [fs.dir.itr.members], 30.11.13.1 [fs.rec.dir.itr.members] Status: New Submitter: Tim Song Opened: 2016-12-09 Last modified: 2017-03-19

Priority: 2

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

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

View all issues with New 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.

Proposed resolution:

This wording is relative to N4618.

  1. Alternative A (remove the noexcept):

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

      directory_iterator& operator++();
      directory_iterator& increment(error_code& ec) noexcept;
      
    2. Edit 30.11.12.1 [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 30.11.13 [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 30.11.13.1 [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 30.11.12.1 [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 30.11.13.1 [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.