3668. [recursive_]directory_iterator constructors refer to undefined options

Section: 31.12.11.2 [fs.dir.itr.members], 31.12.12.2 [fs.rec.dir.itr.members] Status: New Submitter: Jonathan Wakely Opened: 2022-01-31 Last modified: 2024-01-29

Priority: 3

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

View all issues with New status.

Discussion:

31.12.11.2 [fs.dir.itr.members] p2 and 31.12.12.2 [fs.rec.dir.itr.members] p3 refer to the options parameter, but not all overloads have a parameter of that name.

We need some "for the overloads with …" wording.

[2022-03-04; Reflector poll]

Set priority to 3 after reflector poll.

[2022-12-18; Daniel comments and provides wording]

It seems to me that we should differentiate the problems of directory_iterator and recursive_directory_iterator regarding the constructors that don't provide any options arguments at least from a logical point of view:

From the existing Postconditions: element of recursive_directory_iterator we can at least guess that the intention of the existing wording is that these suppose to reflect that the effective options within the Effects: element are also equal to directory_options::none. But for directory_iterator we don't have any options "getter" nor Postconditions from deducing the intent.

Fortunately, existing implementations (I looked at the current V2 2022 library and libstdc++ implementation) seem to behave already as if directory_options::none is set for the affected constructors for both iterator types.

Note that this issue here has some wording overlap with the the proposed wording of LWG 2708, I'm therefore using the exact wording form currently suggested there. If LWG would like to change this form (e.g. by using the word "overload" instead of "signature") this should also be done in that other issue to reduce possible merge conflicts. Note that the here suggested form using "signature" has existing practice in other places of Clause 31.12 [filesystems], so I recommend keeping that form.

Proposed resolution:

This wording is relative to N4917.

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

    [Drafting note:
    (1) The proposed wording form takes care to use the same wording form used in LWG 2708 for recursive_directory_iterator at the time of writing.
    (2) We don't need similar wording for the default constructor because this creates an end iterator and there exist no way for the user to observe the effects of directory_options for such an iterator value. ]

    directory_iterator() noexcept;
    

    -1- Effects: Constructs the end iterator.

    explicit directory_iterator(const path& p);
    directory_iterator(const path& p, directory_options options);
    directory_iterator(const path& p, error_code& ec);
    directory_iterator(const path& p, directory_options options, error_code& ec);
    

    -?- For the signatures with no parameter options, let options be directory_options::none.

    -2- Effects: For the directory that p resolves to, constructs an iterator for the first element in a sequence of directory_entry elements representing the files in the directory, if any; otherwise the end iterator. However, if

    (options & directory_options::skip_permission_denied) != directory_options::none
    

    and construction encounters an error indicating that permission to access p is denied, constructs the end iterator and does not report an error.

    […]

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

    [Drafting note:
    (1) The proposed wording form takes care to be in sync with the wording form used in LWG 2708 at the time of writing. This issue here doesn't touch the wording for the options function though, and leaves any changes to LWG 2708, because these changes don't seem essential to solve the issue here.
    (2) We don't need similar wording for the default constructor because this creates an end iterator and from 31.12.12.1 [fs.class.rec.dir.itr.general] p2 we can conclude that user code has no way to determine the effective directory_options value of this iterator value (interestingly p15 quoted below can be read to apply here as well, but 31.12.12.1 [fs.class.rec.dir.itr.general] p2 seems to be very prohibitive and LWG 2708 is going to solve this special case as well).
    (3) We easily simplify the wording of p3 as shown below, because the "scope" of the introductory new paragraph includes the Postconditions: element. But similar to the arguments provided in (1) we don't wish to introduce merge conflicts with the LWG 2708 wording and therefore intentionally leave any changes of p3 to that issue. ]

    recursive_directory_iterator() noexcept;
    

    -1- Effects: Constructs the end iterator.

    explicit recursive_directory_iterator(const path& p);
    recursive_directory_iterator(const path& p, directory_options options);
    recursive_directory_iterator(const path& p, directory_options options, error_code& ec);
    recursive_directory_iterator(const path& p, error_code& ec);
    

    -?- For the signatures with no parameter options, let options be directory_options::none.

    -2- Effects: Constructs an iterator representing the first entry in the directory to which p resolves, if any; otherwise, the end iterator. However, if

    (options & directory_options::skip_permission_denied) != directory_options::none
    

    and construction encounters an error indicating that permission to access p is denied, constructs the end iterator and does not report an error.

    -3- Postconditions: options() == options for the signatures with a directory_options argument, otherwise options() == directory_options::none.

    […]

    […]
    directory_options options() const;
    

    -15- Returns: The value of the argument passed to the constructor for the options parameter, if present, otherwise directory_options::none.

    -16- Throws: Nothing.