This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of Open status.
Section: 31.12.12.2 [fs.rec.dir.itr.members] Status: Open Submitter: Eric Fiselier Opened: 2016-05-09 Last modified: 2022-12-18
Priority: 2
View all other issues in [fs.rec.dir.itr.members].
View all issues with Open status.
Discussion:
The current specification of recursion_pending() says (31.12.12.2 [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.
[2016-08 Chicago]
Wed AM: Move to Open
[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.
Change 31.12.12.2 [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.
[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.
Change [fs.rec.dir.itr] as indicated:
[…] // other members as required by 25.3.5.3 [input.iterators], input iterators private: bool recurse_; // exposition-only }; }Change 31.12.12.2 [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(), andrhs.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(), andrhs.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- Postcondition
s:recursion_pending()recurse_ == false.[…]
[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 31.12.12 [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 31.12.12.2 [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.
[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
[2018-08-23 Batavia Issues processing]
General agreement that flag should be shared; Casey to reword.
[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.
Proposed resolution:
This wording is relative to N4750.
Change 31.12.12.2 [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_iteratoriterator 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_iteratoriterator 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 (16.4.6.15 [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::noneestablished 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 (25.3.5.3 [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.
[…]