Date: Thu, 20 Feb 2025 19:00:34 -0600
Hi,
I can't speak to the original design of std::stack and I also don't see
prior discussion of this right off hand. But I have some thoughts:
> Is there a reason std::stack does not provide a standard iterator
I presume for the same reason std::stack does not provide access to
anything other than the top element. As a data structure, a stack by design
only provides access and operations on the top element. If you need access
to anything else, what you want isn't a stack.
> and for that matter, an *input iterator* (or what would have been a
legacy input iterator)? Is it because it would be too confusing?
> ...
> *An input iterator does not guarantee multiple passes*, so that should
avoid surprises—the stack is empty after iterating from beginning to end
I for one would be quite confused by this, at least if this were provided
as .begin()/.end()/std::begin/std::end and stack<T,
C>::iterator. std::find(pi.begin(), pi.end(), 3); is a great example of
something that would be extraordinarily confusing. I can't think of any
other container where iterating mutates. If there were some separate
std::stack_input_iterator, that would be more reasonable, but then the
question just comes down to usefulness.
Cheers,
Jeremy
On Thu, Feb 20, 2025 at 5:35 PM Javier Estrada via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> DISCLAIMER: I assume I'm not the first one asking about this. so I did a
> search in the list looking for it and spent a good 20 minutes going over
> the results and didn't find anything,
>
> Is there a reason std::stack does not provide a standard iterator, and for
> that matter, an *input iterator* (or what would have been a legacy input
> iterator)? Is it because it would be too confusing?
>
> There could be uses for it, particularly using it in a range-for loop and
> the algorithms (such as std::for_each, std::copy, std::copy_if,
> std::find, std::find_if, std::all_of, std::any_of, std::none_of) that
> take as a minimum an input iterator.
>
> *An input iterator does not guarantee multiple passes*, so that should
> avoid surprises—the stack is empty after iterating from beginning to end,
> or the elements that have been traversed are gone.
>
> The underlying sequence container is protected, so in order to gain
> access to it one would have to derive and expose the iterators, or
> specialize std::begin, std::end but and allow friendship (other solutions
> are possible, I would guess).
>
> Here are a few of motivating examples:
>
> // stack is empty after iteration
> std::stack<int> pi ({6,1,4,1,3});
> for (auto i : pi)
> cout << i << endl;
>
> // stack with one element left
> std::find(pi.begin(), pi.end(), 3);
>
> std::vector<int> dest{};
> std::copy_if(pi.begin(), pi.end(), std::back_inserter(dest), [](int i) {
> return i>3;
> });
>
> // or perhaps with function template overloads?
> std::find(std::begin(pi), std::end(pi), 3);
>
>
>
>
>
>
>
>
>
>
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
I can't speak to the original design of std::stack and I also don't see
prior discussion of this right off hand. But I have some thoughts:
> Is there a reason std::stack does not provide a standard iterator
I presume for the same reason std::stack does not provide access to
anything other than the top element. As a data structure, a stack by design
only provides access and operations on the top element. If you need access
to anything else, what you want isn't a stack.
> and for that matter, an *input iterator* (or what would have been a
legacy input iterator)? Is it because it would be too confusing?
> ...
> *An input iterator does not guarantee multiple passes*, so that should
avoid surprises—the stack is empty after iterating from beginning to end
I for one would be quite confused by this, at least if this were provided
as .begin()/.end()/std::begin/std::end and stack<T,
C>::iterator. std::find(pi.begin(), pi.end(), 3); is a great example of
something that would be extraordinarily confusing. I can't think of any
other container where iterating mutates. If there were some separate
std::stack_input_iterator, that would be more reasonable, but then the
question just comes down to usefulness.
Cheers,
Jeremy
On Thu, Feb 20, 2025 at 5:35 PM Javier Estrada via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> DISCLAIMER: I assume I'm not the first one asking about this. so I did a
> search in the list looking for it and spent a good 20 minutes going over
> the results and didn't find anything,
>
> Is there a reason std::stack does not provide a standard iterator, and for
> that matter, an *input iterator* (or what would have been a legacy input
> iterator)? Is it because it would be too confusing?
>
> There could be uses for it, particularly using it in a range-for loop and
> the algorithms (such as std::for_each, std::copy, std::copy_if,
> std::find, std::find_if, std::all_of, std::any_of, std::none_of) that
> take as a minimum an input iterator.
>
> *An input iterator does not guarantee multiple passes*, so that should
> avoid surprises—the stack is empty after iterating from beginning to end,
> or the elements that have been traversed are gone.
>
> The underlying sequence container is protected, so in order to gain
> access to it one would have to derive and expose the iterators, or
> specialize std::begin, std::end but and allow friendship (other solutions
> are possible, I would guess).
>
> Here are a few of motivating examples:
>
> // stack is empty after iteration
> std::stack<int> pi ({6,1,4,1,3});
> for (auto i : pi)
> cout << i << endl;
>
> // stack with one element left
> std::find(pi.begin(), pi.end(), 3);
>
> std::vector<int> dest{};
> std::copy_if(pi.begin(), pi.end(), std::back_inserter(dest), [](int i) {
> return i>3;
> });
>
> // or perhaps with function template overloads?
> std::find(std::begin(pi), std::end(pi), 3);
>
>
>
>
>
>
>
>
>
>
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
Received on 2025-02-21 01:00:54