Title
recursive_directory_iterator::recursion_pending() is incorrectly specified
Status
open
Section
[fs.rec.dir.itr.members]
Submitter
Eric Fiselier

Created on 2016-05-09.00:00:00 last changed 23 months ago

Messages

Date: 2022-12-18.18:56:59

Proposed resolution:

This wording is relative to N4750.

  1. Change [fs.rec.dir.itr.members] as indicated:

    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) noexcept;
    recursive_directory_iterator(const path& p, error_code& ec) noexcept;
    

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

    -2- Effects: […]

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

    • this->options() == options

    • recursion_pending() == true

    […]

    recursive_directory_iterator(const recursive_directory_iterator& rhs);
    

    -7- Effects: Constructs an object of class recursive_directory_iterator iterator that denotes the same directory entry as rhs, if any..

    -8- Postconditions: If rhs is dereferenceable,

    […]

    recursive_directory_iterator(recursive_directory_iterator&& rhs) noexcept;
    

    -9- Effects: Constructs an object of class recursive_directory_iterator iterator that denotes the directory entry denoted by rhs before the function call, if any..

    -10- Postconditions: If rhs is dereferenceable, […]

    recursive_directory_iterator& operator=(const recursive_directory_iterator& rhs);
    

    -11- Effects: If *this and rhs are the same object, the member has no effect. Causes *this to denote the same directory entry denoted by rhs, if any.

    -12- Postconditions: If rhs is dereferenceable,

    […]

    recursive_directory_iterator& operator=(recursive_directory_iterator&& rhs) noexcept;
    

    -14- Effects: If *this and rhs are the same object, the member has no effect. Causes *this to denote the directory entry denoted by rhs before the function call, if any.

    -15- Postconditions: If rhs was dereferenceable before the function call, […]

    -16- Returns: *this.

    -x- Remarks: If *this and rhs do not refer to the same object, the resulting state of rhs is unspecified ([lib.types.movedfrom]).

    directory_options options() const;
    

    -17- Returns: The value of the argument passed to the constructor for the options parameter, if present, otherwise directory_options::none established by the most recently called member that has a postcondition for options().

    […]

    bool recursion_pending() const;
    

    -21- Returns: true if disable_recursion_pending() has not been called subsequent to the prior construction or increment operation, otherwise false. If disable_recursion_pending() has been called on a copy of *this, an unspecified value. Otherwise, the value established for recursion_pending() by the postcondition of the most recent construction, assignment, increment, or disable_recursion_pending operation.

    […]

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

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

    -?- Postconditions: If *this is dereferenceable, recursion_pending() == true.

    […]

    void pop();
    void pop(error_code& ec);
    

    -26- Effects: If depth() == 0, set *this to recursive_directory_iterator(). […]

    -?- Postconditions: If *this is dereferenceable, recursion_pending() == true.

    […]

Date: 2022-12-15.00:00:00

[ 2022-12-18; Daniel comments ]

Note that this proposed wording has some overlap with LWG 3668 for recursive_directory_iterator's constructors without options argument. If we would like a different wording form for this textual location in one issue we should resync the other issue to reduce the chance of a merge conflict.

Date: 2018-08-23.00:00:00

[ 2018-08-23 Batavia Issues processing ]

General agreement that flag should be shared; Casey to reword.

Date: 2018-06-07.11:29:28

[ 2018-06, Rapperswil, Wednesday evening ]

JW: p21 currently can just say "unspecified"
BO: if we are OK with only remote implementations we can remove the unspecifiedness
BO: the problematic business is the "recursion pending" bit
JW: I want time to work on this

Move to open and note that Jonathan is reviewing and making recommendations.

Date: 2018-05-23.00:00:00

[ 2018-05-23: Casey restores the intended design with an expansion of the original PR ]

The intended design is that all copies of a single recursive_directory_iterator share a common block of state which includes the values returned by options, depth, and recursion_pending - hence the mandate that those functions not be called on a non-dereferenceable iterator in [fs.class.rec.dir.itr] para 2. To allow an implementation with such shared state, it's necessary to make changes to the value returned by recursion_pending() visible to all copies of the same dereferenceable iterator.

Also:

  • pop notionally calls increment repeatedly until the current directory is exhausted, pop should affect the value of recursion_pending similarly to increment.

  • options is not valid for all constructor signatures described by [fs.rec.dir.itr.members] para 2.

  • the copies and moves don't specify what they actually do

  • it's not quite kosher for the copies and moves to have postconditions on the value of expressions that have UB if the iterator copied/moved from is not dereferenceable.

Date: 2018-01-29.00:00:00

[ 2018-01-29: Casey provides a PR with an exposition-only member ]

Status to 'Review'.

Previous resolution from Casey [SUPERSEDED]:

This wording is relative to N4713.

  1. Change [fs.rec.dir.itr] as indicated:

        […]
    
        // other members as required by [input.iterators], input iterators
    
      private:
        bool recurse_; // exposition-only
      };
    }
    
  2. Change [fs.rec.dir.itr.members] as indicated:

    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) noexcept;
    recursive_directory_iterator(const path& p, error_code& ec) noexcept;
    

    […]

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

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

    • recurse_ == true.

    […]

    recursive_directory_iterator(const recursive_directory_iterator& rhs);
    

    […]

    -8- Postconditions:

    […]

    (8.3) — recursion_pending() == rhs.recursion_pending()recurse_ == rhs.recurse_

    recursive_directory_iterator(recursive_directory_iterator&& rhs) noexcept;
    

    […]

    -10- Postconditions: options(), depth(), and recursion_pending()recurse_ have the values that rhs.options(), rhs.depth(), and rhs.recursion_pending()rhs.recurse_, respectively, had before the function call.

    recursive_directory_iterator& operator=(const recursive_directory_iterator& rhs);
    

    […]

    -12- Postconditions:

    […]

    (12.3) — recursion_pending() == rhs.recursion_pending()recurse_ == rhs.recurse_

    […]

    recursive_directory_iterator& operator=(recursive_directory_iterator&& rhs) noexcept;
    

    […]

    -15- Postconditions: options(), depth(), and recursion_pending()recurse_ have the values that rhs.options(), rhs.depth(), and rhs.recursion_pending()rhs.recurse_, respectively, had before the function call.

    […]

    bool recursion_pending() const;
    

    -21- Returns: true if disable_recursion_pending() has not been called subsequent to the prior construction or increment operation, otherwise falserecurse_.

    […]

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

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

    […]

    -?- Postcondition: recurse_ == true.

    void disable_recursion_pending();
    

    -28- Postconditions: recursion_pending()recurse_ == false.

    […]

Date: 2018-01-26.00:00:00

[ 2018-1-26 issues processing telecon ]

Status to 'Tentatively Ready'; Casey will explore whether making recursion_pending an exposition-only member makes this clearer.

Previous resolution from Eric [SUPERSEDED]:

This wording is relative to N4582.

  1. Change [fs.rec.dir.itr.members] as indicated:

    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) noexcept;
    recursive_directory_iterator(const path& p, error_code& ec) noexcept;
    

    […]

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

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

    • recursion_pending() == true.

    […]

    [Drafting note: The following changes the specification of recursion_pending() seemingly recursive. Perhaps it would be easier to specify recursion_pending() in terms of a exposition only member in recursive_directory_iterator.]

    bool recursion_pending() const;
    

    […]

    -24- Returns: true if disable_recursion_pending() has not been called subsequent to the prior construction or increment operation, otherwise falsefalse if disable_recursion_pending() has been called subsequent to the prior construction or increment operation, otherwise the value of recursion_pending() set by that operation.

    […]

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

    […]

    -27- Effects: As specified by Input iterators (24.2.3), except that: […]

    -?- Postcondition: recursion_pending() == true.

Date: 2016-08-04.02:52:49

[ 2016-08 Chicago ]

Wed AM: Move to Open

Date: 2017-03-19.19:35:20

The current specification of recursion_pending() says ([fs.rec.dir.itr.members]/24):

Returns: true if disable_recursion_pending() has not been called subsequent to the prior construction or increment operation, otherwise false.

This language does not take into account cases where the prior construction was a copy construction from a iterator, it, where it.recursion_pending() == false.

History
Date User Action Args
2022-12-18 18:56:59adminsetmessages: + msg13160
2018-08-24 13:31:33adminsetmessages: + msg10115
2018-06-07 11:29:28adminsetmessages: + msg9872
2018-06-07 11:29:28adminsetstatus: review -> open
2018-05-17 03:36:44adminsetmessages: + msg9851
2018-01-29 21:34:17adminsetmessages: + msg9665
2018-01-29 21:34:17adminsetstatus: ready -> review
2018-01-28 19:43:07adminsetmessages: + msg9647
2018-01-28 19:43:07adminsetstatus: open -> ready
2016-08-04 02:52:49adminsetmessages: + msg8384
2016-08-04 02:52:49adminsetstatus: new -> open
2016-05-10 20:42:20adminsetmessages: + msg8115
2016-05-09 00:00:00admincreate