recursive_directory_iterator::recursion_pending()
is incorrectly specifiedSection: 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
ifdisable_recursion_pending()
has not been called subsequent to the prior construction or increment operation, otherwisefalse
.
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.
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 adirectory_options
argument, otherwiseoptions() == directory_options::none
.
options() == options
for the signatures with adirectory_options
argument, otherwiseoptions() == directory_options::none
.
recursion_pending() == true
.[…]
[Drafting note: The following changes the specification of
recursion_pending()
seemingly recursive. Perhaps it would be easier to specifyrecursion_pending()
in terms of a exposition only member inrecursive_directory_iterator
.]bool recursion_pending() const;[…]
-24- Returns:true
ifdisable_recursion_pending()
has not been called subsequent to the prior construction or increment operation, otherwisefalse
false
ifdisable_recursion_pending()
has been called subsequent to the prior construction or increment operation, otherwise the value ofrecursion_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 24.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 adirectory_options
argument, otherwiseoptions() == directory_options::none
.
options() == options
for the signatures with adirectory_options
argument, otherwiseoptions() == 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()
, andrecursion_pending()
recurse_
have the values thatrhs.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()
, andrecursion_pending()
recurse_
have the values thatrhs.options()
,rhs.depth()
, andrhs.recursion_pending()
rhs.recurse_
, respectively, had before the function call.[…]
bool recursion_pending() const;-21- Returns:
recurse_.true
ifdisable_recursion_pending()
has not been called subsequent to the prior construction or increment operation, otherwisefalse
[…]
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
, letoptions
bedirectory_options::none
.-2- Effects: […]
-3- Postconditions:
options() == options
for the signatures with adirectory_options
argument, otherwiseoptions() == directory_options::none
.
this->options() == options
recursion_pending() == true
[…]
recursive_directory_iterator(const recursive_directory_iterator& rhs);-7- Effects: Constructs an
object of classiterator that denotes the same directory entry asrecursive_directory_iterator
rhs
, if any..-8- Postconditions: If
rhs
is dereferenceable,[…]
recursive_directory_iterator(recursive_directory_iterator&& rhs) noexcept;-9- Effects: Constructs an
object of classiterator that denotes the directory entry denoted byrecursive_directory_iterator
rhs
before the function call, if any..-10- Postconditions: If
rhs
is dereferenceable, […]recursive_directory_iterator& operator=(const recursive_directory_iterator& rhs);-11- Effects:
IfCauses*this
andrhs
are the same object, the member has no effect.*this
to denote the same directory entry denoted byrhs
, if any.-12- Postconditions: If
rhs
is dereferenceable,[…]
recursive_directory_iterator& operator=(recursive_directory_iterator&& rhs) noexcept;-14- Effects:
IfCauses*this
andrhs
are the same object, the member has no effect.*this
to denote the directory entry denoted byrhs
before the function call, if any.-15- Postconditions: If
rhs
was dereferenceable before the function call, […]-16- Returns:
*this
.-x- Remarks: If
*this
andrhs
do not refer to the same object, the resulting state ofrhs
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 theestablished by the most recently called member that has a postcondition foroptions
parameter, if present, otherwisedirectory_options::none
options()
.[…]
bool recursion_pending() const;-21- Returns:
Iftrue
ifdisable_recursion_pending()
has not been called subsequent to the prior construction or increment operation, otherwisefalse
.disable_recursion_pending()
has been called on a copy of*this
, an unspecified value. Otherwise, the value established forrecursion_pending()
by the postcondition of the most recent construction, assignment, increment, ordisable_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 (24.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
torecursive_directory_iterator()
. […]-?- Postconditions: If
*this
is dereferenceable,recursion_pending() == true
.[…]